Repro
- Buka SSMS
Ketik yang berikut ke dalam jendela permintaan baru
use <YourDatabase>;
go
- Pergi ke Object Explorer (SSMS) dan klik kanan pada
<YourDatabase>
-> Tasks
->Take Offline
Buka jendela permintaan baru kedua dan ketikkan yang berikut:
use <YourDatabase>;
go
Anda akan diminta dengan pesan berikut:
Msg 952, Level 16,
Status 1, Baris 1, Basis Data 'TestDb1' sedang dalam transisi. Coba pernyataannya nanti.
Alasan ini terjadi dapat ditemukan dari permintaan diagnostik yang mirip dengan yang di bawah ini:
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;
Untuk apa nilainya, Anda tidak perlu Object Explorer untuk mereproduksi kesalahan ini. Anda hanya perlu permintaan yang diblokir yang mencoba operasi yang sama (dalam hal ini, buat database menjadi offline). Lihat screenshot di bawah ini untuk tiga langkah dalam T-SQL:
Apa yang kemungkinan besar akan Anda lihat adalah sesi Object Explorer Anda diblokir oleh sesi lain (ditunjukkan oleh blocking_session_id
). Sesi Object Explorer itu akan mencoba untuk mendapatkan kunci eksklusif ( X
) pada database. Dalam kasus repro di atas, sesi Object Explorer diberikan kunci pembaruan ( U
) dan mencoba untuk mengkonversi ke kunci eksklusif ( X
). Itu memiliki wait_type LCK_M_X
, diblokir oleh sesi kami yang diwakili oleh jendela kueri pertama ( use <YourDatabase>
ambil kunci bersama ( S
) pada database).
Dan kemudian kesalahan ini muncul dari sesi lain mencoba untuk mendapatkan kunci, dan pesan kesalahan ini menghasilkan penolakan sesi untuk mendapatkan akses ke database yang mencoba untuk transisi ke keadaan yang berbeda (dalam hal ini, keadaan online ke transisi offline).
Apa yang harus Anda lakukan lain kali?
Pertama, jangan panik dan jangan mulai menjatuhkan basis data . Anda perlu mengambil pendekatan pemecahan masalah (dengan permintaan diagnostik serupa seperti yang di atas) untuk mencari tahu mengapa Anda melihat apa yang Anda lihat. Dengan pesan seperti itu, atau ketika sesuatu muncul "hang", Anda harus secara otomatis menganggap kurangnya konkurensi dan mulai menggali untuk memblokir ( sys.dm_tran_locks
adalah awal yang baik).
Sebagai catatan tambahan, saya benar-benar yakin bahwa Anda yang terbaik untuk mengetahui akar masalah sebelum mengambil tindakan acak apa pun. Tidak hanya dengan operasi ini, tetapi itu berlaku untuk semua perilaku yang tidak Anda harapkan. Mengetahui apa yang sebenarnya menyebabkan masalah Anda, sudah jelas itu bukan masalah besar. Pada dasarnya Anda memiliki rantai pemblokiran, dan pemblokir induk adalah sesuatu yang kemungkinan besar baru saja Anda keluarkan KILL
, atau jika itu adalah permintaan sesi yang tidak Anda inginkan KILL
maka Anda bisa menunggu sampai selesai. Either way, Anda akan memiliki pengetahuan untuk membuat keputusan yang tepat dan bijaksana mengingat skenario khusus Anda (kembalikan atau tunggu komitmen).
Hal lain yang patut dicatat, ini adalah salah satu alasan mengapa saya selalu memilih alternatif T-SQL daripada GUI. Anda tahu persis apa yang Anda jalankan dengan T-SQL dan apa yang dilakukan SQL Server. Bagaimanapun, Anda mengeluarkan perintah eksplisit. Ketika Anda menggunakan GUI, T-SQL yang sebenarnya akan menjadi abstraksi. Dalam hal ini, saya melihat upaya Object Explorer yang diblokir untuk membuat database offline dan itu ALTER DATABASE <YourDatabase> SET OFFLINE
. Tidak ada upaya untuk mengembalikan, itulah sebabnya ia menunggu tanpa batas. Dalam kasus Anda, jika Anda ingin mengembalikan sesi yang memiliki kunci pada basis data itu, ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATE
kemungkinan besar Anda sudah mencukupi jika Anda telah membuat keputusan awal bahwa rollback baik-baik saja.