Kontext: Das verwendete Framework ist Spring und alle Abfragen werden mit JdbcTemplate ausgeführt. MySQL Server Version ist 5.6.19. Das table
ist ein InnoDB table
und Standard auto commit
und die Isolationsstufe Wiederholbares Lesen ist eingestellt.
Problem : Ein Insert
Ereignis innerhalb einer Transaktion und ein select
Ereignis, das dieselben eingefügten Daten liest, sieht die Daten nicht. Das select
läuft nach dem insert
und nach der insert
Transaktion hat commited
.
Ich habe sowohl das bin-Protokoll als auch das allgemeine Protokoll in MySQL aktiviert. Relevante Protokolle unten
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/*!*/;
Abfrageprotokoll
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'
insert
Erstaunlicherweise sollte First (249935389) überhaupt nicht Teil der Transaktion sein. Es ist ein separater API-Aufruf und völlig unabhängig. Es könnte Frühling sein, der es mit der Verhandlung mischt, oder ich lese das falsche Protokoll? AFAIK, da es sich um denselben Thread handelt, der impliziert, dass sich die Einfügung in der Transaktion befindet.
Die nächsten beiden inserts
sind Teil der Transaktion und es sieht so aus, als ob sie festgeschrieben wurde. (249936514). Jetzt wird die Auswahlabfrage (letzte im allgemeinen Protokoll) nach dem Festschreiben ausgeführt und die Daten werden nicht angezeigt. Es werden 0 Zeilen zurückgegeben. Wie kann dies angesichts der Datenlage geschehen committed
? Oder liegt das commit
nicht am Faden 40? Da es nicht die Thread-ID hat.
Zusammenfassend habe ich zwei Fragen.
BEGIN
Befindet sich das im Binlog vor demINSERT INTO user_geo_loc
(was nicht Teil der Transaktion ist), ist dies ein Fehler mit spring / Jdbc oder MySql, da bekannt ist, dass diese Transaktion bereits festgeschrieben wurde (da Transaktionen in das Binlog geschrieben werden, wenn sie festgeschrieben wurden) erfolgreich war) und würde daher niemals zurückgesetzt werden.Wenn das Festschreiben vor dem Auswählen erfolgt (Festschreiben ist um 14:16:06 Uhr und Auswählen ist um 14:16:07 Uhr), wie kommt es dann, dass das Festschreiben die von der Transaktion eingefügte Zeile nicht zurückgibt?
Das ist äußerst verwirrend. Jede Hilfe wäre dankbar
Hinweis: Die Abfragen im Bin und im Abfrageprotokoll wurden bearbeitet, um vertrauliche Informationen zu entfernen. Der Kern der Abfragen bleibt jedoch derselbe
Bearbeiten: Aktualisiert mit allgemeinem Protokoll und Abfrageprotokoll mit einem detaillierten Beispiel.
BEGIN
oder START TRANSACTION
. Verwenden Sie stattdessen autocommit=0
? (Ich bevorzuge begin ... commit; es macht den Umfang der Transaktion klar.)