Data MySQL Commited tidak terlihat untuk memilih kueri


13

Konteks: Kerangka kerja yang digunakan adalah Spring dan semua kueri dijalankan dengan JdbcTemplate. Versi Mysql Server adalah 5.6.19. The tableadalah InnoDB tabledan default seperti auto commitdan tingkat isolasi berulang-read diatur.

Masalah : Terjadi Insertdi dalam transaksi dan selectyang membaca data yang sama dimasukkan tidak melihat data. The selectberjalan setelah itu insertdan setelah inserttransaksi 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 insertsadalah 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 committidak pada utas 40? Karena tidak memiliki id utas.

Untuk meringkas saya punya dua pertanyaan.

  1. Apakah BEGINdalam binlog sebelum INSERT 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.

  2. 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.


Anda memberi tag 5.5, tetapi menyebutkan 5.6; yang mana Apakah replikasi terlibat?
Rick James

@ RickJames maaf, ini 5.6.19. Saya telah memperbarui pertanyaan dengan contoh dari kueri dan log bin. Juga tidak ada replikasi yang terlibat. Saya menyalakan log bin hanya setelah melihat masalah untuk debug itu. Terima kasih
Ahmed Aeon Axan 15

Terima kasih, itu membantu. Saya tidak melihat BEGINatau START TRANSACTION. Apakah Anda, sebaliknya, menggunakan autocommit=0? (Saya lebih suka memulai ... komit; itu membuat tingkat transaksi jelas.)
Rick James

Jadi framework (spring) mengelola transaksi dan biasanya mengatur autocommit = 0 dan melakukan di akhir. Saya kira kita tidak melihat autocommit = 0 di sini karena koneksi sudah dalam keadaan itu.
Ahmed Aeon Axan

Jawaban:


3

Saya mencoba membuat hipotesis tentang pertanyaan kedua:

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?

Transaksi dikelola oleh Spring. Jadi ada kemungkinan bahwa sebelum menjalankan selectpegas telah meningkatkan start transactionatau telah menggunakan koneksi untuk menjalankan kueri lain.

Saya memulai sesi pertama di mana saya mensimulasikan memasukkan ke dalam tabel t:

session1> create table t (i int auto_increment primary key);
Query OK, 0 rows affected (0,32 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

session1> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

session1> start transaction;
Query OK, 0 rows affected (0,00 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

Saya membuat sesi baru, session2, di mana autocommitdiatur ke 0. Ke sesi baru ini, transaksi secara implisit dimulai ketika menjalankan pilih.

session2> set autocommit = 0;
Query OK, 0 rows affected (0,00 sec)

session2> select * from t;  -- this starts a transaction
+---+
| i |
+---+
| 1 |
+---+
1 rows in set (0,00 sec)

Pindah ke session1 untuk melakukan penyisipan.

session1> commit;

Sekarang pindah lagi ke session2:

session2> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

Session2 tidak dapat melihat baris yang baru saja dimasukkan. Jika a commitdinaikkan di session2 kita bisa melihat baris baru dimasukkan di session1

session2> commit
1 row in set (0,00 sec)

session2> select * from t;
+---+
| i |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0,00 sec)

Log umum terlihat seperti:

150804 14:04:10     2 Query select * from t

150804 14:04:30     1 Query start transaction
150804 14:04:39     1 Query insert into t values ()
150804 14:04:44     1 Query commit
150804 14:04:51     2 Query select * from t

150804 14:05:07     2 Query commit
150804 14:05:10     2 Query select * from t

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.