Kontekst: Używany jest framework Spring, a wszystkie zapytania są uruchamiane za pomocą JdbcTemplate. Wersja Mysql Server to 5.6.19. table
To InnoDB table
i domyślnie jak auto commit
i poziom izolacji powtarzalne odczytania jest ustawiony.
Problem : Insert
Występuje wewnątrz transakcji, a select
czytający te same wstawione dane nie widzi danych. W select
biegnie poinsert
i po insert
transakcja ma commited
.
Włączyłem dziennik bin oraz ogólny dziennik w mysql. Odpowiednie dzienniki poniżej
bin-log:
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/*!*/;
Dziennik zapytań
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'
Co ciekawe, First insert
(249935389) w ogóle nie powinien być częścią transakcji. Jest to osobne wywołanie API i całkowicie niezwiązane. Może to być wiosenne mieszanie go z transakcją lub źle czytam dziennik? AFAIK, ponieważ jest w tym samym wątku, oznacza to, że wstawka jest w transakcji.
Następne dwa inserts
są częścią transakcji i wygląda na to, że się zobowiązuje. (249936514). Teraz wybrane zapytanie (ostatnie w dzienniku ogólnym) działa po zatwierdzeniu i nie widzi danych. Zwraca 0 wierszy. Jak to się może stać, biorąc pod uwagę dane committed
? A może commit
nie ma nici 40? Ponieważ nie ma identyfikatora wątku.
Podsumowując, mam dwa pytania.
Czy
BEGIN
w binlogu znajdującym się przedINSERT INTO user_geo_loc
(który nie jest częścią transakcji), jest to błąd z spring / Jdbc lub MySql po prostu robi to, ponieważ wie, że transakcja już się dokonała (ponieważ transakcje są zapisywane w binlog, gdy mają udało się) i dlatego nigdy nie zostanie wycofany.Biorąc pod uwagę, że zatwierdzenie następuje przed wyborem (zatwierdzenie jest o 14:16:06, a wybranie o 14:16:07), w jaki sposób zaznaczenie nie zwraca wiersza wstawionego przez transakcję?
To jest bardzo kłopotliwe. Każda pomoc będzie mile widziana
Uwaga: Zapytania w bin i dzienniku zapytań zostały edytowane w celu usunięcia poufnych informacji. Ale istota zapytań pozostaje taka sama
Edycja: zaktualizowano ogólny dziennik i dziennik zapytań ze szczegółowym przykładem.
BEGIN
ani START TRANSACTION
. Czy zamiast tego używasz autocommit=0
? (Wolę zacząć ... zatwierdzić; to wyjaśnia zakres transakcji.)