Bingung tentang UPDLOCK, HOLDLOCK

89

Saat meneliti penggunaan Petunjuk Tabel , saya menemukan dua pertanyaan ini:

Jawaban untuk kedua pertanyaan tersebut mengatakan bahwa saat menggunakan (UPDLOCK, HOLDLOCK), proses lain tidak akan dapat membaca data di tabel itu, tetapi saya tidak melihatnya. Untuk mengujinya, saya membuat tabel dan memulai dua jendela SSMS. Dari jendela pertama, saya menjalankan transaksi yang dipilih dari tabel menggunakan berbagai petunjuk tabel. Saat transaksi sedang berjalan, dari jendela kedua saya menjalankan berbagai pernyataan untuk melihat mana yang akan diblokir.

Tabel uji:

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Dari SSMS Jendela 1:

BEGIN TRANSACTION

SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'

COMMIT TRANSACTION

Dari SSMS Jendela 2 (menjalankan salah satu dari berikut ini):

SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'

Pengaruh petunjuk tabel yang berbeda pada pernyataan yang dijalankan di Jendela 2:

           (UPDLOCK)       (HOLDLOCK)    (UPDLOCK, HOLDLOCK)    (TABLOCKX)
---------------------------------------------------------------------------
SELECT    not blocked      not blocked       not blocked         blocked
INSERT    not blocked        blocked           blocked           blocked
UPDATE      blocked          blocked           blocked           blocked
DELETE      blocked          blocked           blocked           blocked

Apakah saya salah memahami jawaban yang diberikan dalam pertanyaan tersebut, atau membuat kesalahan dalam pengujian saya? Jika tidak, mengapa Anda menggunakan (UPDLOCK, HOLDLOCK)vs. (HOLDLOCK)sendirian?


Penjelasan lebih lanjut tentang apa yang saya coba capai:

Saya ingin memilih baris dari tabel dan mencegah data dalam tabel itu dimodifikasi saat saya memprosesnya. Saya tidak mengubah data itu, dan ingin mengizinkan terjadinya pembacaan.

Jawaban ini dengan jelas mengatakan bahwa (UPDLOCK, HOLDLOCK)akan memblokir pembacaan (bukan yang saya inginkan). Komentar pada jawaban ini menyiratkan bahwa hal HOLDLOCKitu mencegah pembacaan. Untuk mencoba dan lebih memahami efek petunjuk tabel dan melihat apakah UPDLOCKsendirian akan melakukan apa yang saya inginkan, saya melakukan percobaan di atas dan mendapatkan hasil yang bertentangan dengan jawaban tersebut.

Saat ini, saya percaya bahwa (HOLDLOCK)itulah yang harus saya gunakan, tetapi saya khawatir bahwa saya mungkin telah melakukan kesalahan atau melewatkan sesuatu yang akan kembali menggigit saya di masa depan, oleh karena itu pertanyaan ini.

Jeff Ogata
sumber

Jawaban:

102

Mengapa UPDLOCK memblokir pilihan? The Lock Kompatibilitas Matrix jelas menunjukkan Nuntuk S / U dan U / S pertentangan, seperti dalam No Konflik .

Adapun petunjuk HOLDLOCK menyatakan dokumentasi:

HOLDLOCK: Setara dengan SERIALIZABLE. Untuk informasi lebih lanjut, lihat DAPAT DITERIMA nanti dalam topik ini.

...

SERIALIZABLE: ... Pemindaian dilakukan dengan semantik yang sama dengan transaksi yang berjalan pada tingkat isolasi SERIALIZABLE ...

dan topik Transaction Isolation Level menjelaskan apa yang dimaksud SERIALIZABLE:

Tidak ada transaksi lain yang dapat mengubah data yang telah dibaca oleh transaksi saat ini hingga transaksi saat ini selesai.

Transaksi lain tidak dapat memasukkan baris baru dengan nilai kunci yang akan berada dalam kisaran kunci yang dibaca oleh pernyataan mana pun dalam transaksi saat ini hingga transaksi saat ini selesai.

Oleh karena itu, perilaku yang Anda lihat dijelaskan dengan sempurna oleh dokumentasi produk:

  • UPDLOCK tidak memblokir SELECT atau INSERT bersamaan, tetapi memblokir setiap UPDATE atau DELETE dari baris yang dipilih oleh T1
  • HOLDLOCK berarti SERALISASI dan oleh karena itu memungkinkan PILIHAN, tetapi memblokir PEMBARUAN dan PENGHAPUSAN baris yang dipilih oleh T1, serta SISIP apa pun dalam rentang yang dipilih oleh T1 (yang merupakan seluruh tabel, oleh karena itu setiap sisipan).
  • (UPDLOCK, HOLDLOCK): percobaan Anda tidak menunjukkan apa yang akan diblokir selain kasus di atas, yaitu transaksi lain dengan UPDLOCK di T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX tidak membutuhkan penjelasan

Pertanyaan sebenarnya adalah apa yang ingin Anda capai ? Bermain dengan petunjuk kunci tanpa pemahaman 110% lengkap mutlak tentang semantik penguncian memohon masalah ...

Setelah OP edit:

Saya ingin memilih baris dari tabel dan mencegah data dalam tabel itu dimodifikasi saat saya memprosesnya.

Anda harus menggunakan salah satu tingkat isolasi transaksi yang lebih tinggi. BACA BERULANG akan mencegah perubahan data yang Anda baca. SERIALIZABLE akan mencegah data yang Anda baca diubah dan data baru dimasukkan. Menggunakan tingkat isolasi transaksi adalah pendekatan yang tepat, bukan menggunakan petunjuk kueri. Kendra Little memiliki poster bagus yang menjelaskan tingkat isolasi .

Remus Rusanu
sumber
+1, dan terima kasih atas tanggapan mendetail. Saya akan memperbarui pertanyaan saya untuk menambahkan detail tentang apa tujuan saya.
Jeff Ogata
1
@Remus Rusanu Bisakah Anda menjelaskan mengapa pendekatan yang tepat menggunakan tingkat isolasi daripada menggunakan petunjuk kueri? Saya memiliki prosedur di mana saya hanya perlu mengunci dua tabel agar tidak dimodifikasi dan saya menggunakan TABLOCK, HOLDLOCK, haruskah saya benar-benar mengubah ke level isolasi dan mengunci semua tabel dalam transaksi saya?
Steve
Saya ingin penjelasan untuk TABLOCKX :)
niico
Catatan: Tautan untuk entri blog Kendra Little mengembalikan 404. Saya tidak menemukan entri tertanggal 2 Feb 2011, seperti yang disarankan tautan tersebut.
Bacon Bits
22

UPDLOCK digunakan saat Anda ingin mengunci baris atau baris selama pernyataan pilih untuk pernyataan pembaruan di masa mendatang. Pembaruan di masa mendatang mungkin merupakan pernyataan berikutnya dalam transaksi.

Sesi lain masih dapat melihat data. Mereka tidak bisa mendapatkan kunci yang tidak cocok dengan UPDLOCK dan / atau HOLDLOCK.

Anda menggunakan UPDLOCK saat Anda ingin mencegah sesi lain mengubah baris yang telah Anda kunci. Ini membatasi kemampuan mereka untuk memperbarui atau menghapus baris yang terkunci.

Anda menggunakan HOLDLOCK saat Anda ingin mencegah sesi lain mengubah data apa pun yang Anda lihat. Ini membatasi kemampuan mereka untuk memasukkan, memperbarui, atau menghapus baris yang telah Anda kunci. Ini memungkinkan Anda menjalankan kueri lagi dan melihat hasil yang sama.

Scott Bruns
sumber
1
Terima kasih, tetapi saya rasa Anda belum benar-benar menjawab pertanyaan saya: apakah jawaban atas pertanyaan itu salah dalam menyatakan bahwa (UPDLOCK,HOLDLOCK)blok dibaca, dan adakah alasan untuk menggunakan (UPDLOCK,HOLDLOCK)alih-alih hanya (HOLDLOCK)?
Jeff Ogata
Pernyataan kedua saya menjawab pertanyaan Anda, mereka salah. Sesi lain masih bisa membaca data.
Scott Bruns
Updlock, Holdlock tidak sama dengan holdlock. Updlock, holdlock mengunci baris untuk memperbarui dan membuat serial transaksi Anda. Holdlock dengan sendirinya hanya membuat serial transaksi Anda. Itu tidak mengunci baris yang dipilih untuk akses lebih lanjut.
Scott Bruns
"UPDLOCK digunakan saat Anda ingin mengunci baris atau baris selama pernyataan pilih untuk pernyataan pembaruan di masa mendatang." Saya suka ini, karena XLOCK mungkin tidak berfungsi kapan
Yiping