Saya memiliki prosedur tersimpan yang pada dasarnya memilih nilai dari satu tabel dan menyisipkannya ke yang lain, semacam pengarsipan. Saya ingin menghindari banyak orang melakukan itu pada saat yang sama.
Ketika prosedur ini sedang berjalan, saya tidak ingin orang lain dapat memulainya, namun saya tidak ingin serialisasi, orang lain akan menjalankan prosedur setelah saya selesai.
Yang saya inginkan adalah orang lain yang mencoba memulainya untuk mendapatkan kesalahan, sementara saya menjalankan prosedur.
Saya sudah mencoba menggunakan sp_getapplock, namun saya tidak bisa menghentikan orang tersebut untuk menjalankan prosedur.
Saya juga mencoba menemukan prosedur dengan sys.dm_exec_requests dan memblokir prosedur, sementara ini berhasil, saya pikir itu tidak optimal karena pada beberapa server saya tidak memiliki izin untuk menjalankan sys.dm_exec_sql_text (sql_handle).
Apa cara terbaik bagi saya untuk melakukan ini?
sumber
Jawaban:
Untuk menambahkan jawaban @ Tibor-Karaszi, menetapkan batas waktu penguncian sebenarnya tidak menghasilkan kesalahan (saya telah mengirimkan PR terhadap dokumen). sp_getapplock hanya mengembalikan -1, jadi Anda harus memeriksa nilai kembali. Jadi seperti ini:
sumber
Gunakan sp_getapplock di awal proc, dan atur timeout kunci ke nilai yang sangat rendah. Dengan cara ini Anda mendapatkan kesalahan saat Anda diblokir.
sumber
Pilihan lain adalah membuat tabel untuk mengontrol akses ke prosedur. contoh di bawah ini menunjukkan tabel yang memungkinkan serta prosedur yang dapat menggunakannya.
sumber
IsLocked
status ke 0 dalam kasus itu? Saya juga ingin tahu tentang penggunaan Anda diCOALESCE
sini. Dapat@@ROWCOUNT
berupa null setelah pernyataan sukaUPDATE
? Akhirnya, hanya nitpick kecil, mengapa meletakkan tanda koma di depanTHROW
pernyataan dalam kasus khusus itu?Saya pikir Anda mencoba menyelesaikan masalah dengan cara yang salah. Apa yang Anda inginkan adalah perlindungan terbaik terhadap konsistensi basis data. Jika dua orang menjalankan prosedur tersimpan pada saat yang sama, konsistensi basis data dapat dilanggar.
Untuk melindungi dari berbagai jenis ketidakkonsistenan basis data, standar SQL memiliki empat tingkat isolasi transaksi:
Namun, standar SQL memiliki pendekatan berbasis penguncian untuk inkonsistensi basis data ini, dan untuk alasan kinerja banyak basis data mengambil pendekatan berbasis isolasi snapshot yang pada dasarnya memiliki level-level ini:
Pembatalan transaksi dalam database berbasis isolasi snapshot ini mungkin terdengar mengkhawatirkan, tetapi sekali lagi setiap database tunggal akan membatalkan transaksi karena jalan buntu, jadi aplikasi apa pun yang masuk akal tetap harus dapat mencoba kembali suatu transaksi.
Apa yang Anda inginkan adalah tingkat isolasi SERIALISASI : memastikan bahwa jika transaksi yang dilakukan secara independen satu sama lain menghasilkan keadaan yang baik, setiap eksekusi paralel dari transaksi juga menghasilkan keadaan yang baik. Untungnya, Michael Cahill dalam disertasi doktoralnya menemukan bagaimana tingkat isolasi SERIALIZABLE dapat didukung oleh database terisolasi snapshot dengan sedikit usaha.
Jika menggunakan tingkat isolasi SERIALIZABLE dalam database snapshot terisolasi, jika dua orang mencoba menjalankan prosedur yang tersimpan secara bersamaan dan mereka akan menginjak kaki masing-masing, salah satu transaksi akan dibatalkan.
Sekarang, apakah SQL Server benar-benar mendukung tingkat isolasi SERIALIZABLE (alih-alih menyamarkan isolasi snapshot di balik kata kunci SERIALIZABLE )? Sejujurnya, saya tidak tahu: satu-satunya database yang saya tahu yang mendukungnya adalah PostgreSQL.
Meskipun saya gagal memberikan saran khusus untuk SQL Server, saya tetap memposting jawaban ini, karena pengguna PostgreSQL dan pengguna database lain yang dapat mempertimbangkan beralih ke PostgreSQL dapat mengambil manfaat dari jawaban saya. Selain itu, pengguna basis data non-PostgreSQL yang tidak dapat beralih ke PostgreSQL dapat menekan vendor database favorit mereka untuk menawarkan tingkat isolasi asli SERIALIZABLE .
sumber
Saya menyadari masalah 'nyata' mungkin lebih kompleks.
Jika tidak: jika Anda melakukan pengarsipan dengan memasukkan dan / atau memperbarui pemicu, Anda dapat menghindari masalah yang Anda coba selesaikan.
Semoga itu bisa membantu,
-Chris C.
sumber
the 'real' problem may be more complex
. Jika tidak, pemicu adalah solusi yang baik. Plus itu mungkin akan lebih mudah untuk menguji dan memelihara karena itu adalah fitur dari database daripada solusi khusus.