Kontext: Das verwendete Framework ist Spring und alle Abfragen werden mit JdbcTemplate ausgeführt. MySQL Server Version ist 5.6.19. Das tableist ein InnoDB tableund Standard auto commitund die Isolationsstufe Wiederholbares Lesen ist eingestellt.
Problem : Ein InsertEreignis innerhalb einer Transaktion und ein selectEreignis, das dieselben eingefügten Daten liest, sieht die Daten nicht. Das selectläuft nach dem insertund nach der insertTransaktion 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'
insertErstaunlicherweise 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 insertssind 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 commitnicht am Faden 40? Da es nicht die Thread-ID hat.
Zusammenfassend habe ich zwei Fragen.
BEGINBefindet 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.
BEGINoder START TRANSACTION. Verwenden Sie stattdessen autocommit=0? (Ich bevorzuge begin ... commit; es macht den Umfang der Transaktion klar.)