reprodüksiyon
- SSMS'yi açma
Aşağıdakileri yeni bir sorgu penceresine yazın
use <YourDatabase>;
go
- Nesne Gezgini'ne (SSMS) gidin ve sağ tıklayın
<YourDatabase>
-> Tasks
->Take Offline
İkinci bir yeni sorgu penceresi açın ve aşağıdakileri yazın:
use <YourDatabase>;
go
Aşağıdaki mesajla karşılaşırsınız:
Msg 952, Seviye 16, Durum 1, Satır 1
Veritabanı 'TestDb1' geçiş aşamasında. İfadeyi daha sonra deneyin.
Bunun olmasının nedeni, aşağıdakine benzer bir teşhis sorgusundan bulunabilir:
select
l.resource_type,
l.request_mode,
l.request_status,
l.request_session_id,
r.command,
r.status,
r.blocking_session_id,
r.wait_type,
r.wait_time,
r.wait_resource,
request_sql_text = st.text,
s.program_name,
most_recent_sql_text = stc.text
from sys.dm_tran_locks l
left join sys.dm_exec_requests r
on l.request_session_id = r.session_id
left join sys.dm_exec_sessions s
on l.request_session_id = s.session_id
left join sys.dm_exec_connections c
on s.session_id = c.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
outer apply sys.dm_exec_sql_text(c.most_recent_sql_handle) stc
where l.resource_database_id = db_id('<YourDatabase>')
order by request_session_id;
Değeri ne olursa olsun, bu hatayı yeniden oluşturmak için Nesne Gezgini'ne ihtiyacınız yoktur. Yalnızca aynı işlemi deneyen engellenen bir istek gerekir (bu durumda veritabanını çevrimdışı duruma getirin). T-SQL'deki üç adım için aşağıdaki ekran görüntüsüne bakın:
Büyük olasılıkla göreceğiniz şey, Object Explorer oturumunuzun başka bir oturum tarafından engellenmesidir (ile gösterilir blocking_session_id
). Bu Nesne Gezgini oturumu X
veritabanında özel bir kilit ( ) almaya çalışacaktır . Yukarıdaki repro'nun durumunda, Object Explorer oturumuna bir güncelleme kilidi ( U
) verildi ve özel bir kilide ( X
) dönüştürülmeye çalışıldı . LCK_M_X
İlk sorgu penceresi ( veritabanında use <YourDatabase>
paylaşılan bir kilit ( S
) kapar) tarafından temsil edilen oturumumuz tarafından engellenen bir wait_type vardı .
Ve sonra bu hata , kilit almaya çalışan başka bir oturumdan kaynaklandı ve bu hata mesajı, farklı bir duruma (bu durumda çevrimiçi durum çevrimdışı geçiş).
Bir dahaki sefere ne yapmalısın?
Öncelikle panik yapmayın ve veritabanlarını düşürmeye başlamayın . Gördüklerinizi neden gördüğünüzü öğrenmek için bir sorun giderme yaklaşımı (yukarıdaki gibi benzer bir teşhis sorgusuyla) almanız gerekir. Böyle bir mesajla veya bir şey "asılı" göründüğünde, otomatik olarak eşzamanlılık eksikliğini üstlenmeli ve engellemeye kazmaya başlamalısınız ( sys.dm_tran_locks
iyi bir başlangıçtır).
Bir yan not olarak, herhangi bir rastgele işlem yapmadan önce bir sorunun kökenini bulmak için en iyisi olduğuna inanıyorum. Sadece bu işlemle değil, beklemediğiniz tüm davranışlar için de geçerlidir. Soruna gerçekten neyin sebep olduğunu bilmek , bunun gerçekten önemli olmadığı açıktır. Temelde bir engelleme zinciriniz vardı ve üst engelleyici, büyük olasılıkla bir KILL
açık bırakmış olabileceğiniz bir şeydi veya bir oturumun isteği istemiyorsanız, KILL
tamamlanana kadar bekleyebilirdiniz. Her iki durumda da, senaryonuzun (geri alma veya kesinti için bekleme) verildiğinde doğru ve ihtiyatlı bir karar verme bilginiz olurdu.
Dikkate değer başka bir şey, bu her zaman bir GUI yerine T-SQL alternatif tercih nedenlerinden biridir. T-SQL ile ne yürüttüğünüzü ve SQL Server'ın ne yaptığını tam olarak biliyorsunuz. Sonuçta, açık komutu verdiniz. Bir GUI kullandığınızda, gerçek T-SQL bir soyutlama olacaktır. Bu durumda, engellenen Object Explorer'ın veritabanını çevrimdışına alma girişimine baktım ve öyleydi ALTER DATABASE <YourDatabase> SET OFFLINE
. Geri alma girişimi olmadı, bu yüzden süresiz olarak bekliyordu. Sizin durumunuzda, bu veritabanında kilitleri olan oturumları geri almak isterseniz, geri dönmenin iyi olduğuna dair ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE
ilk belirlemeyi yapmış olsaydınız büyük olasılıkla yeterli olurdu.