컨텍스트 : 사용 된 프레임 워크는 Spring이며 모든 쿼리는 JdbcTemplate을 사용하여 실행됩니다. MySQL 서버 버전은 5.6.19입니다. 는 table
입니다 InnoDB table
및 기본 설정과 같이 auto commit
격리 수준 반복-읽기를 설정합니다.
문제점 : Insert
트랜잭션 내부에서 발생하고 select
삽입 된 동일한 데이터를 읽는 데이터에 데이터가 표시되지 않습니다. select
실행 후insert
과 후 insert
트랜잭션이있다 commited
.
mysql에서 bin 로그와 일반 로그를 활성화했습니다. 아래 관련 로그
빈 로그 :
SET TIMESTAMP=1438265764/*!*/;
BEGIN
/*!*/;
# at 249935389
#150730 14:16:04 server id 1 end_log_pos 249935606 CRC32 0xa6aca292 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265764/*!*/;
insert into user_geo_loc_latest(user_id, lat, lng) values(x,y,z) on duplicate key update lat=y, lng=z
/*!*/;
# at 249935606
#150730 14:16:06 server id 1 end_log_pos 249936255 CRC32 0x2a52c734 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table(txnid) VALUES ('885851438265675046')
/*!*/;
# at 249936255
#150730 14:16:06 server id 1 end_log_pos 249936514 CRC32 0x6cd85eb5 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table2(x) VALUES (y)
/*!*/;
# at 249936514
#150730 14:16:06 server id 1 end_log_pos 249936545 CRC32 0xceb9ec56 Xid = 9406873
COMMIT/*!*/;
쿼리 로그
150730 14:16:04 40 Query ...
....
40 Query select count(*) from table where txnid = '885851438265675046'
40 Query select @@session.tx_read_only
40 Query INSERT INTO table(txnid) VALUES ('885851438265675046')
40 Query select @@session.tx_read_only
40 Query INSERT INTO table2(x) values(y)
40 Query commit
....
150730 14:16:07 36 Query select pp.*, b.create_date from table pp left join bill b on pp.bill_id = b.bill_id where pp.txnid = '885851438265675046'
흥미롭게도 First insert
(249935389)는 거래의 일부가되어서는 안됩니다. 별도의 API 호출이며 완전히 관련이 없습니다. 트랜잭션과 스프링 믹싱이 될 수 있습니까? 아니면 로그를 잘못 읽고 있습니까? AFAIK는 동일한 스레드에 있기 때문에 삽입이 트랜잭션에 있음을 의미합니다.
다음 두 inserts
가지는 트랜잭션의 일부이며 커밋 된 것처럼 보입니다. (249936514). 이제 커밋 후에 선택 쿼리 (일반 로그의 마지막 쿼리)가 실행되고 데이터가 표시되지 않습니다. 0 행을 반환합니다. 데이터를 고려하면 어떻게 이런 일이 일어날 수 committed
있습니까? 아니면 commit
스레드 40에 있지 않습니까? 스레드 ID가 없기 때문입니다.
요약하면 두 가지 질문이 있습니다.
BEGIN
binlog에서INSERT INTO user_geo_loc
(트랜잭션의 일부가 아닌) 이전에 있습니까? 이것은 spring / Jdbc 또는 MySql의 버그 입니까? 성공) 따라서 롤백되지 않습니다.커밋이 선택 전에 발생하면 (커밋은 14:16:06이고 선택은 14:16:07입니다) 어떻게 선택이 트랜잭션에 의해 삽입 된 행을 반환하지 않습니까?
이것은 매우 당혹 한 일입니다. 도움을 주시면 감사하겠습니다.
참고 : 저장소 및 쿼리 로그의 쿼리는 중요한 정보를 제거하도록 편집되었습니다. 그러나 쿼리의 본질은 동일하게 유지됩니다.
편집 : 자세한 예제를 사용하여 일반 로그 및 쿼리 로그로 업데이트했습니다.
BEGIN
또는 START TRANSACTION
. 대신에 autocommit=0
?를 사용하고 있습니까? (나는 begin ... commit; 트랜잭션의 범위를 명확하게한다.)