Konteks: Kerangka kerja yang digunakan adalah Spring dan semua kueri dijalankan dengan JdbcTemplate. Versi Mysql Server adalah 5.6.19. The table
adalah InnoDB table
dan default seperti auto commit
dan tingkat isolasi berulang-read diatur.
Masalah : Terjadi Insert
di dalam transaksi dan select
yang membaca data yang sama dimasukkan tidak melihat data. The select
berjalan setelah itu insert
dan setelah insert
transaksi memiliki commited
.
Saya telah mengaktifkan log bin serta log umum di mysql. Log yang relevan di bawah ini
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/*!*/;
Log Kueri
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'
Anehnya, Pertama insert
(249935389) tidak boleh menjadi bagian dari transaksi sama sekali. Ini adalah panggilan API terpisah dan sama sekali tidak terkait. Bisa jadi musim semi mencampurnya dengan transaksi atau saya salah membaca log? AFAIK karena berada di utas yang sama itu menyiratkan masukkan dalam transaksi.
Dua berikutnya inserts
adalah bagian dari transaksi dan sepertinya itu berkomitmen. (249936514). Sekarang kueri pemilihan (yang terakhir dalam log umum) berjalan setelah komit dan tidak melihat data. Ini mengembalikan 0 baris. Bagaimana ini bisa terjadi mengingat data tersebut committed
? Atau commit
tidak pada utas 40? Karena tidak memiliki id utas.
Untuk meringkas saya punya dua pertanyaan.
Apakah
BEGIN
dalam binlog sebelumINSERT INTO user_geo_loc
(yang bukan bagian dari transaksi), apakah ini bug dengan spring / Jdbc atau MySql hanya melakukan ini karena ia tahu transaksi ini telah dilakukan (karena transaksi ditulis ke binlog ketika mereka sudah berhasil) dan karena itu tidak akan pernah dibatalkan.Mengingat komit terjadi sebelum pilih (komit pada 14:16:06 dan pilih pada 14:16:07) bagaimana mungkin bahwa pilih tidak mengembalikan baris yang dimasukkan oleh transaksi?
Ini sangat membingungkan. Bantuan apa pun akan dihargai
Catatan: Kueri di bin dan log kueri telah diedit untuk menghapus informasi sensitif. Tetapi esensi dari pertanyaan tetap sama
Sunting: Diperbarui dengan log umum dan log kueri dengan contoh terperinci.
BEGIN
atau START TRANSACTION
. Apakah Anda, sebaliknya, menggunakan autocommit=0
? (Saya lebih suka memulai ... komit; itu membuat tingkat transaksi jelas.)