Saya mendapatkan Deadlock dari kunci celah di atas meja ketika sering memasukkannya ke berbagai sumber. Berikut ini adalah ikhtisar proses saya.
START TRANSACTION
UPDATE vehicle_image
SET active = 0
WHERE vehicleID = SOMEID AND active = 1
Loop:
INSERT INTO vehicle_image (vehicleID, vehicleImageFilePath, vehicleImageSplashFilePath
,vehicleImageThumbnailFilePath, vehicleImageMiniFilePath, mainVehicleImage, active)
VALUES (%s, %s, %s, %s, %s, %s, 1);
END TRANSACTION
Output dari SHOW Create table vehicle_image;
adalah:
CREATE TABLE `vehicle_image` (
`vehicleImageID` int(11) NOT NULL AUTO_INCREMENT,
`vehicleID` int(11) DEFAULT NULL,
`vehicleImageFilePath` varchar(200) DEFAULT NULL,
`vehicleImageSplashFilePath` varchar(200) DEFAULT NULL,
`vehicleImageThumbnailFilePath` varchar(200) DEFAULT NULL,
`vehicleImageMiniFilePath` varchar(200) DEFAULT NULL,
`mainVehicleImage` bit(1) DEFAULT NULL,
`active` bit(1) DEFAULT b'1',
`userCreated` int(11) DEFAULT NULL,
`dateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`userModified` int(11) DEFAULT NULL,
`dateModified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`vehicleImageID`),
KEY `active` (`active`),
KEY `mainvehicleimage` (`mainVehicleImage`),
KEY `vehicleid` (`vehicleID`)
) ENGINE=InnoDB AUTO_INCREMENT=22878102 DEFAULT CHARSET=latin1
Dan Deadlock terakhir diberikan oleh SHOW engine innodb status
:
LATEST DETECTED DEADLOCK
------------------------
2018-03-27 12:31:15 11a58
*** (1) TRANSACTION:
TRANSACTION 5897678083, ACTIVE 2 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 873570, OS thread handle 0x124bc, query id 198983754 ec2-34-239-240-179.compute-1.amazonaws.com 34.239.240.179 image_processor update
INSERT INTO vehicle_image (vehicleID, vehicleImageFilePath, vehicleImageSplashFilePath, vehicleImageThumbnailFilePath, vehicleImageMiniFilePath, mainVehicleImage, active)
VALUES (70006176, 'f180928(1)1522168276.230837full.jpg', 'f180928(1)1522168276.230837splash.jpg', 'f180928(1)1522168276.230837thumb.jpg', 'f180928(1)1522168276.230837mini.jpg', 1, 1)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 875 page no 238326 n bits 472
index `vehicleid` of table `ipacket`.`vehicle_image` trx id 5897678083
lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 378 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 842c365a; asc ,6Z;;
1: len 4; hex 815d03bc; asc ] ;;
*** (2) TRANSACTION:
TRANSACTION 5897678270, ACTIVE 1 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1248, 2 row lock(s), undo log entries 1
MySQL thread id 873571, OS thread handle 0x11a58, query id 198983849 ec2-35-171-169-21.compute-1.amazonaws.com 35.171.169.21 image_processor update
INSERT INTO vehicle_image (vehicleID, vehicleImageFilePath, vehicleImageSplashFilePath, vehicleImageThumbnailFilePath, vehicleImageMiniFilePath, mainVehicleImage, active)
VALUES (70006326, '29709(1)1522168277.4443843full.jpg', '29709(1)1522168277.4443843splash.jpg', '29709(1)1522168277.4443843thumb.jpg', '29709(1)1522168277.4443843mini.jpg', 1, 1)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 875 page no 238326 n bits 464
index `vehicleid` of table `ipacket`.`vehicle_image` trx id 5897678270
lock_mode X locks gap before rec
Record lock, heap no 378 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 842c365a; asc ,6Z;;
1: len 4; hex 815d03bc; asc ] ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 875 page no 238326 n bits 472
index `vehicleid` of table `ipacket`.`vehicle_image` trx id 5897678270
lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 378 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 842c365a; asc ,6Z;;
1: len 4; hex 815d03bc; asc ] ;;
*** WE ROLL BACK TRANSACTION (2)
Saya menjalankan banyak proses ini secara bersamaan tetapi tidak pernah menjalankan dua proses yang menggunakan hal yang sama VehicleID
. Saya benar-benar bingung mengapa saya mendapatkan Deadlock.
Saya sementara telah memecahkan masalah dengan menggunakan level Isolasi READ COMMITTED
, tetapi saya telah membaca bahwa ini memerlukan perubahan replikasi karena Anda harus melakukan replikasi level baris.
Saya telah membaca pertanyaan lain di sini yang mirip dengan saya, tetapi saya agak baru untuk SQL dan masih tidak dapat memahami mengapa ini terjadi.
Pertanyaan Serupa:
- Deadlock pada statments insert MySQL
- Deadlock MySQL InnoDB Untuk 2 query insert sederhana
MEMPERBARUI:
Saya menemukan bahwa menggunakan READ COMMITTED
belum benar-benar menyelesaikan masalah. Saya masih belum menemukan mengapa kebuntuan terjadi dan saya benar-benar tidak tahu bagaimana cara mendiagnosis lebih jauh dari yang saya miliki saat ini. Saya terus mendapatkan Deadlock dalam sistem produksi saya. Bantuan apa pun akan dihargai.
SHOW PROCESSLIST;
. Sebagian besar waktu,REPEATABLE READ
adalah tingkat isolasi terbaik untuk sebagian besar aplikasi, jadi saya tidak akan terlalu khawatir menggunakannya. Apakah ada peningkatan kinerja yang nyata ketika Anda mengubahnya dari default -REPEATABLE READ
?VARCHARs
.loop
ini hanya kodesemu untuk mewakili apa yang sedang terjadi.repeatable read
keread committed
yang merupakan tingkat isolasi yang lebih rendah kemudian diulang membaca, tapi sayangnya hal itu tidak menghentikan kebuntuan. Saya tahu bahwa perangkat keras akan mempengaruhi server (ini adalah contoh EC2, saya harus mencari secara spesifik) tetapi saya tidak berpikir bahwa informasi itu perlu untuk memahami mengapa kebuntuan terjadi. Sifat sporadis ini juga membuatnya sulit untuk menangkap output dari daftar proses acara; ketika kebuntuan terjadi.Jawaban:
Saya bukan ahli MySQL, tetapi dengan tampilan Deadlock log Anda, meskipun Anda MEMASANG ID kendaraan yang berbeda per pernyataan, mereka memerlukan seluruh datapage (238326) dari indeks
VehicleID
non-cluster untuk dikunci .Fakta bahwa Anda kadang-kadang mendapatkan kebuntuan berarti bahwa dalam 1 halaman Anda memiliki beberapa ID kendaraan, jadi ada kemungkinan kecil bahwa 2 proses yang berbeda akan membutuhkan kunci untuk halaman yang sama.
Hal terbaik untuk disarankan adalah menjaga transaksi Anda sekecil mungkin .
Jika ada beberapa cara yang dapat Anda lakukan berikut ini, ini akan membantu mengurangi kemungkinan kebuntuan:
Jika Anda bisa, cobalah untuk mengubah faktor pengisian indeks menjadi 95% , dan uji untuk melihat apakah Anda mendapatkan lebih sedikit deadlock.
Tes yang lebih ekstrem adalah menghapus indeks itu sepenuhnya saat INSERTing, lalu membuatnya kembali ketika selesai.
sumber
MySQL tidak hanya mengunci baris yang terpengaruh, tetapi juga baris indeks yang terpengaruh dan kesenjangan antara baris indeks (seperti dijelaskan di sini ). Karena kunci utama selalu diindeks dan Anda menggunakannya dalam pembaruan Anda, saya menduga bahwa beberapa transaksi mencoba untuk memperbarui beberapa baris setiap hasil dalam tumpang tindih kunci kesenjangan indeks yang pada gilirannya menciptakan kebuntuan.
Untuk mengatasi ini, saya juga merekomendasikan saran Oreos untuk menjaga transaksi sekecil mungkin. Jika baris yang diperbarui saling independen, Anda harus menggunakan transaksi terpisah untuk masing-masingnya.
sumber