Apakah InnoDB Deadlock eksklusif untuk INSERT / UPDATE / DELETE?

8

Saya Mengatasi kesalahan MySQL "Deadlock ditemukan ketika mencoba mendapatkan kunci; coba memulai kembali transaksi" .

Saya harus memperbarui program untuk memungkinkan kebuntuan. Apakah mungkin SELECTpernyataan itu akan menghasilkan kesalahan jalan buntu? Saya tahu bahwa ini hanya kunci baca sehingga banyak pilihan tidak akan menjadi masalah, tetapi bagaimana jika ada INSERT, UPDATEatau DELETEpernyataan (dengan subquery yang dimungkinkan dengan gabungan) dan SELECTpernyataan (mungkin dengan gabungan atau subkueri) ?

Apakah mungkin bahwa kesalahan akan dilemparkan pada SELECTbukan INSERT, UPDATEatau DELETE.

Ceritanya ada di sini jika Anda penasaran.

Bryan Field
sumber
+1 untuk ini adalah pertanyaan yang bagus karena ini menjelaskan tentang kekhasan InnoDB yang kebanyakan orang tidak sadari sehubungan dengan SELECT terhadap tabel InnoDB.
RolandoMySQLDBA

Jawaban:

5

Jawaban langsung untuk judul pertanyaan Anda adalah Tidak.

SELECT query dapat melakukan kunci pada gen_clust_index , alias Indeks Clustered.

Berikut adalah tiga pertanyaan DBA Stack Exchanges yang saya teliti dengan @RedBlueThing , orang yang menanyakan pertanyaan-pertanyaan ini. @RedBlueThing menemukan pekerjaan sekitar untuk pertanyaannya.

Hanya untuk menjaga pertanyaan Anda dalam perspektif, ketika Anda melihat jawaban ini (jangan melihat terlalu dalam, bahkan saya pusing melihat jawaban saya yang berbelit-belit) harus segera jelas bahwa pertanyaan SELECT dapat mengunci data.

Anda juga memiliki kasus SELECT khusus di mana Anda dapat mengunci baris tertentu berdasarkan permintaan .

UPDATE 2011-08-08 16:49 EDT

Anda mengajukan pertanyaan variasi: "Apakah pengecualian kebuntuan InnoDB mungkin akan dilempar oleh SELECT" Jawabannya bisa berupa Ya dalam kondisi tertentu. Kondisi apa itu? Jika hanya satu pernyataan SQL yang dibatalkan karena kesalahan, beberapa kunci yang ditetapkan oleh pernyataan tersebut dapat dipertahankan. Ini terjadi karena InnoDB menyimpan kunci baris dalam format yang tidak dapat diketahui sesudahnya kunci mana yang ditetapkan oleh pernyataan mana .

Berdasarkan pernyataan itu, urutan peristiwa yang menyebabkan hal ini secara teoritis dapat sebagai berikut:

  • SQL UPDATE Anda satu baris tetapi menghasilkan kesalahan
  • UPDATE menyebabkan kemunduran dari satu baris
  • Baris memiliki kunci yang melekat

Secara pribadi, pernyataan terakhir itu membuatku takut. Akan lebih baik bagi MySQL untuk memberi tahu semua orang tentang kekhasan ini. Namun, pernyataan itu dari Dokumentasi MySQL. (Oh ya, Oracle memiliki InnoDB)

UPDATE 2015-09-22 18:40 EST

Pada awal tahun, saya mengetahui bahwa Percona memiliki cek Nagi yang keren untuk menemukan kunci-kunci sial ini bersembunyi di balik koneksi yang tertidur. Yang harus Anda lakukan sekarang adalah menjalankan kode dari tautan itu:

SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS b ON  b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS r ON  r.trx_id = w.requesting_trx_id
LEFT JOIN  INFORMATION_SCHEMA.PROCESSLIST       AS p ON  p.id     = b.trx_mysql_thread_id;

Ini hanya akan berfungsi untuk MySQL 5.5+. Jika Anda memiliki MySQL 5.1 atau sebelumnya, Anda harus membunuh semua koneksi tidur untuk melepaskan kunci.

RolandoMySQLDBA
sumber
@Rando - bukankah benar dengan MVCC InnoDB yang bertuliskan tidak pernah memblokir (kecuali saat Anda menggunakan for updatetentu saja)?
Jack bilang coba topanswers.xyz
@ Jack - Jika Anda membaca tautan di 3 poin pertama, Anda akan melihat bahwa MVCC tidak dipermasalahkan. Ini adalah kebuntuan yang mendalam dalam indeks berkerumun yang bahkan MVCC tidak dapat mengurangi.
RolandoMySQLDBA
@Rando - Saya sudah membaca tautan sedikit lebih hati-hati dan saya masih tidak dapat melihat indikasi bahwa orang normal selectdapat mengunci baris atau dengan cara apa pun diblokir oleh DML dalam transaksi lain. Itu tentu benar untuk Oracle dan sejauh yang saya tahu itu juga berlaku untuk InnoDB? Kecuali perkara ketika selectpernyataan benar-benar melakukan DML melalui suatu fungsi atau rute putaran lain tentu saja.
Jack bilang coba topanswers.xyz
@Jack - Jika SELECT dapat memblokir indeks, apalagi UPDATE seperti yang ditunjukkan oleh 3 tautan pertama saya.
RolandoMySQLDBA