Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

MySQL'de Sıkışıklık (Deadlock) Tespiti, Analizi ve Uygulama Tarafında Önleme Stratejileri

byteon

Üye
Katılım
14 Mart 2026
Mesajlar
6
Merhaba arkadaşlar, bugün sizlere özellikle yoğun veritabanı trafiği olan sunucularda can sıkıcı bir problem olan MySQL deadlock'larını nasıl tespit edip analiz edeceğimizi ve en önemlisi, uygulama tarafında nasıl önleyebileceğimizi anlatacağım. Benim yönettiğim sistemlerde bu stratejileri uygulayarak ciddi oranda deadlock hatası azalttım. Sizin de işinize yarayacağını düşünüyorum.

🔍 Deadlock Nedir ve Neden Oluşur?

Basitçe anlatmak gerekirse, deadlock (kilitlenme veya sıkışıklık), iki veya daha fazla işlemin (transaction) birbirini sonsuza kadar beklediği bir durumdur. Örneğin, Transaction A, X kaynağını kilitledi ve Y kaynağına ihtiyaç duyuyor. Aynı anda Transaction B, Y kayrağını kilitledi ve X kayrağına ihtiyaç duyuyor. İkisi de birbirinin elindeki kilidi beklemeye başlar ve sistem bu kilitlenmeyi çözmek için birini "kurban" seçip işlemi geri alır (rollback). Bu da kullanıcıya hata olarak yansır.

⚙️ Deadlock'ları Anlık ve Geçmişe Dönük Tespit Etme

Öncelikle sistemde deadlock olup olmadığını veya geçmişte olmuş mu diye bakalım.

Anlık durumu görmek için `SHOW ENGINE INNODB STATUS` komutunu kullanabilirsiniz. Çıktıda `LATEST DETECTED DEADLOCK` başlığını arayın. Ancak bu komutun çıktısı biraz karışıktır ve sadece en son tespit edilen deadlock'u gösterir.

Daha sistematik izlemek için InnoDB durum değişkenlerini sorgulayalım:
SQL:
SHOW STATUS LIKE 'innodb_row_lock%';
SHOW STATUS LIKE '%deadlock%';

`Innodb_row_lock_current_waits` ve `Innodb_row_lock_time_avg` değerlerinin yüksek olması, kilit çekişmelerinin yoğun olduğuna işaret eder. `innodb_deadlocks` değişkeni ise sunucunun başlangıcından beri oluşan toplam deadlock sayısını verir.

Geçmişe dönük daha detaylı log tutmak isterseniz, /etc/mysql/my.cnf veya /etc/my.cnf dosyasına aşağıdaki ayarı ekleyerek deadlock log'larını açabilirsiniz:
INI:
[mysqld]
innodb_print_all_deadlocks = ON

Bu ayarı aktif ettikten sonra, MySQL error log'unda (/var/log/mysql/error.log) tüm deadlock detaylarını görebilirsiniz. Logları düzenli takip etmek çok önemli.

📊 Deadlock Log'unu Analiz Etme

Error log'unda gördüğünüz bir deadlock kaydı şuna benzer bir yapıdadır. Bakınca korkmayın, adım adım çözeceğiz:

```
(1) TRANSACTION:
TRANSACTION 123456, ACTIVE 5 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 10, OS thread handle 12345, query id 100 localhost root updating
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1
(1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 10 page no 5 n bits 72 index PRIMARY of table `test`.`accounts` trx id 123456 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
(2) TRANSACTION:
TRANSACTION 123457, ACTIVE 3 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 11, OS thread handle 12346, query id 101 localhost root updating
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2
(2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 10 page no 5 n bits 72 index PRIMARY of table `test`.`accounts` trx id 123457 lock_mode X locks rec but not gap waiting
WE ROLL BACK TRANSACTION (2)
```

Burada dikkat etmeniz gerekenler:
1. Hangi işlemler (TRANSACTION) çakışmış? (123456 ve 123457)
2. Hangi SQL sorguları çalışıyordu? (`UPDATE accounts ...`)
3. Hangi kilitler (LOCK) bekleniyordu? (`index PRIMARY of table test.accounts`)
4. Hangi işlem geri alındı (ROLL BACK)? (Transaction (2))

Bu bilgiler, hangi tablo ve hangi işlem sırasının soruna yol açtığını anlamanızı sağlar.

⚠️ Uygulama Kodunda Deadlock Önleme Stratejileri

MySQL tarafında ayar yapmak yetmez, asıl çözüm uygulama mantığınızı düzeltmektir. İşte benim sıkça uyguladığım stratejiler:

1. İşlem (Transaction) Sürelerini Kısa Tutun: Mümkün olan en kısa sürede commit veya rollback yapın. Gerekmedikçe işlemi açık bırakmayın, kullanıcı girişi gibi dış etkenleri transaction içinde bekletmeyin.

2. Erişim Sırasını (Lock Order) Standardize Edin: Bu en kritik nokta! Uygulamanızda birden fazla kaynağı (örneğin, iki farklı tablo satırını) güncellerken, her zaman aynı sırayla kilitleyin. Örneğin, her zaman önce daha küçük ID'ye sahip kullanıcıyı, sonra daha büyük ID'ye sahip kullanıcıyı işleyin. Bu, karşılıklı bekleme durumunu ortadan kaldırır.

3. SELECT ... FOR UPDATE ile Bilinçli Kilitleme: Sadece güncelleme yapacağınız kayıtları kilitleyin. Gereksiz yere tüm tabloyu kilitlemeyin. `FOR UPDATE` ifadesini dikkatli kullanın.

4. Deadlock Algılandığında Yeniden Dene (Retry Logic): Uygulama kodunuzda deadlock hatası (`ERROR 1213`) yakaladığınızda, işlemi kısa bir bekleme sonrası (örn: 50-100ms) otomatik olarak birkaç kez (örn: 3 kez) yeniden deneyen bir mekanizma kurun. Birçok framework'ün bu özelliği vardır veya siz ekleyebilirsiniz.

💎 Optimizasyon ve İndekslerin Önemi

Eksik veya yanlış indeksler, deadlock'un başlıca nedenidir! UPDATE veya DELETE sorgularınızın `WHERE` koşulunda kullandığı sütunların uygun indekslere sahip olduğundan emin olun. Full table scan yapmak daha fazla satırı kilitleyebilir ve deadlock olasılığını artırır.

Şüpheli sorgularınızı `EXPLAIN` anahtar kelimesi ile analiz edin:
SQL:
EXPLAIN UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;

Eğer `type` sütununda `ALL` (tam tablo tarama) görüyorsanız, `user_id` sütununa bir indeks eklemeyi düşünmelisiniz.

Sonuç olarak arkadaşlar, deadlock'ları tamamen sıfırlamak mümkün olmayabilir, ancak bu adımları izleyerek sayılarını kontrol edilebilir seviyelere çekebilir ve uygulamanızın dayanıklılığını büyük ölçüde artırabilirsiniz.

Peki siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Deadlock sorununu çözmek için farklı hangi yöntemleri kullanıyorsunuz? Tecrübelerinizi paylaşın veya aklınıza takılan bir şey olursa aşağıya yazmaktan çekinmeyin.
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri