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.
sumber
BEGIN
atauSTART TRANSACTION
. Apakah Anda, sebaliknya, menggunakanautocommit=0
? (Saya lebih suka memulai ... komit; itu membuat tingkat transaksi jelas.)Jawaban:
Saya mencoba membuat hipotesis tentang pertanyaan kedua:
Transaksi dikelola oleh Spring. Jadi ada kemungkinan bahwa sebelum menjalankan
select
pegas telah meningkatkanstart transaction
atau telah menggunakan koneksi untuk menjalankan kueri lain.Saya memulai sesi pertama di mana saya mensimulasikan memasukkan ke dalam tabel
t
:Saya membuat sesi baru, session2, di mana
autocommit
diatur ke 0. Ke sesi baru ini, transaksi secara implisit dimulai ketika menjalankan pilih.Pindah ke session1 untuk melakukan penyisipan.
Sekarang pindah lagi ke session2:
Session2 tidak dapat melihat baris yang baru saja dimasukkan. Jika a
commit
dinaikkan di session2 kita bisa melihat baris baru dimasukkan di session1Log umum terlihat seperti:
Baris pertama terkait dengan sesi 2. Itu adalah ketika sesi 2 membuka transaksi.
Saya tidak tahu apakah ini yang terjadi dalam kasus Anda. Anda dapat memeriksa log umum Anda jika connection_id 36 digunakan untuk pertanyaan lain. Beri tahu kami
sumber