dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Hata Teşhis Kütüphanesi/sqlserver-1222-lock-request-timeout
SQL Server
MSSQL 2017 - 2022Kilit & Deadlock
6 dk okuma
Error 1222: Lock request time out period exceeded.

SQL Server Error 1222: Kilit Zaman Aşımı — Kim Kilitliyor?

1222 ile 1205 ve client timeout arasındaki fark, blokaj zincirinin başını bulma sorgusu ve NOLOCK yerine doğru çözüm.

İnceleyen:Kıdemli Veritabanı Mimarı & SRE (dataiotech Labs)
Test Edilen Sürümler: SQL Server 2017 / 2019 / 2022
İlk 60 Saniye Teşhis Protokolü:

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

plaintext
Lock request time out period exceeded.

Üç farklı zaman aşımı birbiriyle karıştırılır; ayrımı yapmak işin yarısıdır:

HataKim üretirAnlamı
1222SunucuLOCK_TIMEOUT süresi doldu, kilit alınamadı
1205SunucuDeadlock — döngüsel kilitlenme var, kurban seçildi
Execution Timeout ExpiredİstemciSorgu çalışıyordu ama istemci zaman aşımı süresi bitti

1222'de döngü yoktur; sadece bir işlem diğerini beklemekten vazgeçmiştir. SQL Server'da varsayılan LOCK_TIMEOUT sınırsızdır (-1). Yani bu hatayı görüyorsanız bir yerlerde süre ayarlanmıştır — genellikle ORM veya bağlantı katmanı:

sql
SELECT @@LOCK_TIMEOUT; -- -1 ise sınırsız

▸Blokaj zincirinin başını bulma

Kritik kural: şikayet eden değil, zincirin başındaki oturum sorumludur.

sql
SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time / 1000 AS bekleme_sn, r.wait_resource, SUBSTRING(t.text, 1, 200) AS sorgu FROM sys.dm_exec_requests r OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.blocking_session_id <> 0 ORDER BY r.wait_time DESC;

Zincirin başındaki oturumu (blocking_session_id = 0 olan ve başkalarını bekleten) tespit edin:

sql
SELECT s.session_id, s.login_name, s.host_name, s.program_name, s.status, s.last_request_start_time, s.open_transaction_count FROM sys.dm_exec_sessions s WHERE s.session_id = 87; -- baş bloklayıcı oturum ID

status = 'sleeping' ve open_transaction_count > 0 ise tanı kesindir: uygulama BEGIN TRAN açmış, işi bitmiş ama COMMIT etmemiştir.


▸Çözüm adımları

1. Baş bloklayıcıyı sonlandırın.

sql
KILL 87;

KILL öncesi oturumun ne yaptığını doğrulayın; yarıda kesilen büyük bir yazma işlemi uzun bir rollback başlatabilir.

2. `NOLOCK` ile "çözmeyin". Uygulamaya rastgele WITH (NOLOCK) eklemek blokajı gizler ama yanlış sonuç üretir: okunmamış (kirli) satırlar, iki kez sayılan satırlar, eksik dönen kayıtlar. Raporlarda "sayılar tutmuyor" şikayetinin kaynağı budur. Doğru çözüm satır sürümleme (RCSI) açmaktır:

sql
ALTER DATABASE uygulama_db SET READ_COMMITTED_SNAPSHOT ON;

Bu ayar, okuyucuların yazıcıları bloklamasını engeller ve NOLOCK'ın yarattığı veri tutarsızlıklarını üretmez.

3. Şema kilitlerini ayrı değerlendirin. wait_resource değeri METADATA içeriyorsa blokaj satır değil nesne seviyesindedir (ALTER TABLE, TRUNCATE veya istatistik güncellemesi). Bu durumda READ_COMMITTED_SNAPSHOT tek başına yardımcı olmaz.

4. İşlemleri kısaltın. Uygulama kuralı: Transaction içinde asla kullanıcı girdisi beklenmez, HTTP/REST API çağrısı yapılmaz, dosya okunmaz.


▸Bunu bir daha yaşamamak için

sys.dm_exec_requests üzerinden 5 saniyeden uzun bekleyen istek sayısını izleme metriği yapın. Uygulama tarafında LOCK_TIMEOUT'u bilinçli ayarlayın (5–10 saniye çoğu OLTP iş yükü için idealdir).

Diğer Veritabanı Hata Teşhisleri

Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.

Tüm Hatalar (20)