MySQL "Deadlock found when trying to get lock" — Neden Olur, Nasıl Kalıcı Çözülür?
MySQL 1213 deadlock hatasının nedeni, LATEST DETECTED DEADLOCK çıktısını okuma, gap lock kaynaklı kilitlenmeler ve uygulama tarafında retry tasarımı.
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transactionÖnce şunu netleştirelim: deadlock bir hata değil, InnoDB'nin koruma mekanizmasıdır. İki işlem birbirinin kilidini beklerken döngü oluşur; InnoDB döngüyü tespit eder, kurban seçer ve o işlemi tamamen geri alır. Bu yüzden doğru refleks "deadlock'ı engellemek" değil, "deadlock'a dayanıklı uygulama yazmak" ve ardından oluşum sıklığını azaltmaktır.
▸Grafiği bulma
1. Anlık kayıt:
SHOW ENGINE INNODB STATUS\GÇıktıda LATEST DETECTED DEADLOCK bölümüne bakın. Bu yalnızca son deadlock'ı gösterir.
2. Kalıcı kayıt (bunu açın):
SET GLOBAL innodb_print_all_deadlocks = ON;Artık her deadlock, MySQL hata günlüğüne grafiğiyle birlikte yazılır. Maliyeti ihmal edilebilir, teşhis değeri yüksektir.
3. Bekleyen kilitleri canlı görme:
SELECT w.requesting_engine_transaction_id AS bekleyen,
w.blocking_engine_transaction_id AS bloklayan,
r.trx_query AS bekleyen_sorgu,
b.trx_query AS bloklayan_sorgu,
b.trx_mysql_thread_id AS bloklayan_thread
FROM performance_schema.data_lock_waits w
LEFT JOIN information_schema.innodb_trx r
ON r.trx_id = w.requesting_engine_transaction_id
LEFT JOIN information_schema.innodb_trx b
ON b.trx_id = w.blocking_engine_transaction_id;▸En sık üç neden
1. Ters erişim sırası. Bir işlem A sonra B tablosuna, diğeri B sonra A'ya dokunuyorsa deadlock kaçınılmazdır. Uygulamada sabit bir erişim sırası belirleyin. Kodu düzeltmeden yapılan her parametre değişikliği geçicidir.
2. İndekssiz `WHERE` ve gap lock. REPEATABLE READ izolasyon seviyesinde, indekssiz bir UPDATE/DELETE taranan tüm aralığa gap lock koyar. İki işlem farklı satırları güncellese bile birbirini bekler. Kontrol:
EXPLAIN UPDATE hesaplar SET bakiye = bakiye - 10 WHERE musteri_no = 42;type: ALL ya da rows çok yüksekse, önce indeks ekleyin. Yüksek eşzamanlı OLTP iş yüklerinde READ COMMITTED'a geçmek gap lock kaynaklı deadlock'ların büyük kısmını ortadan kaldırır:
SELECT @@transaction_isolation;3. Uzun işlemler ve toplu güncellemeler. Tek bir UPDATE ile 500.000 satır güncellemek, kilitleri saniyeler boyunca tutar. Toplu işlemleri parçalayın:
UPDATE siparisler SET durum = 'arsiv'
WHERE durum = 'tamamlandi' AND id BETWEEN 1 AND 10000;
-- her partiden sonra COMMIT▸Uygulama tarafında retry tasarımı
Deadlock kurbanı olan işlem tamamen geri alınır; uygulama bunu beklenen bir durum olarak ele almalıdır.
- •Retry yalnızca
1213(deadlock) ve1205(lock wait timeout) için yapılmalı. - •İşlem idempotent olmalı; aksi halde retry çift kayıt üretir.
- •Retry sayısı sınırlı (3-5), bekleme süresi artan (jitter'lı) olmalı.
- •Retry, deadlock'ın oluştuğu *tüm* transaction'ı kapsamalı.
▸İlgili Mühendislik Rehberleri ve İç Linkler
- •MySQL InnoDB Tuning CheatSheet
- •MySQL Lock wait timeout (ERROR 1205) Rehberi
- •MySQL InnoDB Cluster Mimarisi
- •Test edilen sürümler: MySQL 8.0 / 8.4 LTS
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
PostgreSQL too many clients already Hatası: 6 Adımda Çözüm
FATAL: sorry, too many clients already hatasının üç nedeni, nedeni ayırt eden tek sorgu ve max_connections ile PgBouncer üzerinden kalıcı çözümü.
PostgreSQL password authentication failed Hatası: Neden ve Çözüm
psql password authentication failed hatasının dört nedeni: yanlış şifre, md5/SCRAM uyuşmazlığı, pg_hba.conf sırası ve yanlış cluster. Adım adım teşhis.
MySQL ERROR 1045 Access denied: root Şifresi Sıfırlama Rehberi
MySQL 1045 hatasının dört nedeni, "using password: YES/NO" ayrımının anlamı ve kilitli kalınca --init-file ile güvenli şifre sıfırlama.