Saya memiliki database pengembangan yang sering digunakan kembali dari proyek Database Visual Studio (melalui TFS Auto Build).
Terkadang ketika saya menjalankan build saya, saya mendapatkan kesalahan ini:
ALTER DATABASE failed because a lock could not be placed on database 'MyDB'. Try again later.
ALTER DATABASE statement failed.
Cannot drop database "MyDB" because it is currently in use.
Saya mencoba ini:
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE
tapi saya masih tidak bisa drop database. (Dugaan saya adalah bahwa sebagian besar pengembang memiliki dbo
akses.)
Saya dapat secara manual menjalankan SP_WHO
dan mulai mematikan koneksi, tetapi saya perlu cara otomatis untuk melakukan ini di auto build. (Meskipun kali ini koneksi saya adalah satu-satunya di db yang saya coba hilangkan.)
Apakah ada skrip yang dapat menjatuhkan basis data saya terlepas dari siapa yang terhubung?
sql
sql-server
tsql
sql-server-2008
sql-server-2008-r2
Gunung berapi
sumber
sumber
kill
semua pernyataan. Saya akan menggunakan kursor untuk membunuh setiap proses, yang tentu saja tidak efisien sama sekali. Teknik yang digunakan dalam jawaban ini sangat brilian.USE [Master]
Ref: http://msdn.microsoft.com/en-us/library/bb522682%28v=sql.105%29.aspx
sumber
USE master
itulah kuncinya. Saya mencoba untuk menjatuhkan db saat terhubung ke sana (Duh!). Terima kasih!SET OFFLINE
Anda harus menghapus file db secara manual.alter database YourDatabaseName set SINGLE_USER with rollback immediate
akan lebih baik? Jika Anda mengaturnya keOFFLINE
(sebagai status @mattalxndr) file akan dibiarkan di disk, tetapi denganSINGLE_USER
koneksi Anda akan dibiarkan sebagai satu-satunya, dandrop database YourDatabaseName
masih akan menghapus file.set offline
, Anda dapat mengeluarkanset online
untuk menghindari masalah file sisa (ya, ada kemungkinan kondisi ras).Anda bisa mendapatkan skrip yang disediakan SSMS dengan melakukan hal berikut:
Script akan terlihat seperti ini:
sumber
Sedikit diketahui: pernyataan GO sql dapat mengambil bilangan bulat untuk berapa kali mengulangi perintah sebelumnya.
Jadi jika kamu:
Kemudian:
Ini akan mengulangi perintah USE 2000 kali, memaksakan kebuntuan pada semua koneksi lain, dan mengambil kepemilikan koneksi tunggal. (Memberi Anda akses tunggal jendela permintaan untuk melakukan yang Anda inginkan.)
sumber
Untuk pengalaman saya, menggunakan SINGLE_USER membantu sebagian besar waktu, bagaimanapun, kita harus berhati-hati: Saya pernah mengalami saat-saat di mana antara saat saya memulai perintah SINGLE_USER dan waktu selesai ... tampaknya 'pengguna' lain telah mendapatkan SINGLE_USER akses, bukan saya. Jika itu terjadi, Anda berada dalam pekerjaan berat yang berusaha mendapatkan akses kembali ke basis data (dalam kasus saya, itu adalah layanan khusus yang berjalan untuk perangkat lunak dengan database SQL yang mendapatkan akses SINGLE_USER sebelum saya melakukannya). Apa yang saya pikir harus menjadi cara yang paling dapat diandalkan (tidak dapat menjaminnya, tetapi ini adalah apa yang akan saya uji di masa mendatang), sebenarnya:
- menghentikan layanan yang dapat mengganggu akses Anda (jika ada)
- gunakan skrip 'bunuh' di atas untuk menutup semua koneksi
- atur database ke single_user segera setelah itu
- lalu lakukan restore
sumber
Skrip Matthew yang sangat efisien diperbarui untuk menggunakan DMV dm_exec_sessions, menggantikan tabel sistem sysprocess yang sudah usang:
Alternatif menggunakan loop WHILE (jika Anda ingin memproses operasi lain per eksekusi):
sumber
Jawaban yang diterima memiliki kelemahan yang tidak mempertimbangkan bahwa database dapat dikunci oleh koneksi yang mengeksekusi kueri yang melibatkan tabel dalam database selain yang terhubung ke.
Ini dapat menjadi kasus jika instance server memiliki lebih dari satu database dan permintaan secara langsung atau tidak langsung (misalnya melalui sinonim) menggunakan tabel di lebih dari satu database dll.
Karena itu saya menemukan bahwa kadang-kadang lebih baik menggunakan syslockinfo untuk menemukan koneksi untuk mematikan.
Karenanya saran saya adalah menggunakan variasi jawaban yang diterima dari AlexK di bawah ini:
sumber
sys.dm_tran_locks
tabel sebagaimanasyslockinfo
ditandai sudah usang, Anda juga mungkin ingin mengecualikan @@ SPID Anda untuk berjaga-jaga.Anda harus berhati-hati tentang pengecualian selama proses pembunuhan. Jadi, Anda dapat menggunakan skrip ini:
sumber
@AlexK menulis jawaban yang bagus . Saya hanya ingin menambahkan dua sen saya. Kode di bawah ini sepenuhnya didasarkan pada jawaban @ AlexK, perbedaannya adalah Anda dapat menentukan pengguna dan waktu sejak batch terakhir dieksekusi (perhatikan bahwa kode menggunakan sys.dm_exec_sessions alih-alih master..sysprocess):
Dalam contoh ini hanya proses pengguna usrDBTest yang batch terakhir dieksekusi lebih dari 1 jam yang lalu akan dibunuh.
sumber
Anda dapat menggunakan kursor seperti itu:
Saya menulis tentang itu di blog saya di sini: http://www.pigeonsql.com/single-post/2016/12/13/Kill-all-connections-on-DB-by-Cursor
sumber
sumber
Saya telah berhasil menguji dengan kode sederhana di bawah ini
sumber
set SINGLE_USER
ketika sudah ada satu koneksi aktif.