it-swarm-id.com

Bingung tentang UPDLOCK, HOLDLOCK

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

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

Tabel tes:

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 Window 1:

BEGIN TRANSACTION

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

COMMIT TRANSACTION

Dari SSMS Window 2 (jalankan salah satu dari yang berikut):

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 itu, atau membuat kesalahan dalam pengujian saya? Jika tidak, mengapa Anda menggunakan (UPDLOCK, HOLDLOCK) vs. (HOLDLOCK) sendiri?


Penjelasan lebih lanjut tentang apa yang ingin saya capai:

Saya ingin memilih baris dari tabel dan mencegah data dalam tabel tersebut dari modifikasi saat saya memprosesnya. Saya tidak mengubah data itu, dan ingin memungkinkan pembacaan terjadi.

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

Saat ini, saya percaya bahwa (HOLDLOCK) adalah apa yang harus saya gunakan, tetapi saya khawatir bahwa saya mungkin telah membuat kesalahan atau mengabaikan sesuatu yang akan kembali menggigit saya di masa depan, maka pertanyaan ini.

78
Jeff Ogata

Mengapa blok UPDLOCK akan dipilih? The Lock Compatibility Matrix dengan jelas menunjukkan N untuk pertentangan S/U dan U/S, seperti pada Tanpa Konflik .

Adapun HOLDLOCK memberi petunjuk status dokumentasi:

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

...

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

dan topik Tingkat Isolasi Transaksi menjelaskan arti 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 menyisipkan baris baru dengan nilai-nilai kunci yang akan jatuh dalam kisaran kunci yang dibaca oleh pernyataan apa pun dalam transaksi saat ini sampai transaksi saat ini selesai.

Karena itu perilaku yang Anda lihat dijelaskan dengan sempurna oleh dokumentasi produk:

  • UPDLOCK tidak memblokir SELECT atau INSERT bersamaan, tetapi memblokir UPDATE atau DELETE dari baris yang dipilih oleh T1
  • HOLDLOCK berarti SERALISABLE dan karenanya memungkinkan SELECTS, tetapi memblokir UPDATE dan DELET dari baris yang dipilih oleh T1, juga karena INSERT dalam rentang yang dipilih oleh T1 (yang merupakan seluruh tabel, oleh karena itu setiap sisipan ).
  • (UPDLOCK, HOLDLOCK): percobaan Anda tidak menunjukkan apa yang akan memblokir selain kasus di atas, yaitu transaksi lain dengan UPDLOCK di T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX tidak perlu penjelasan

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

Setelah diedit OP:

Saya ingin memilih baris dari tabel dan mencegah data dalam tabel tersebut dari modifikasi saat saya memprosesnya.

Anda harus menggunakan salah satu level isolasi transaksi yang lebih tinggi. REPEATABLE READ akan mencegah data yang Anda baca tidak dimodifikasi. SERIALIZABLE akan mencegah data yang Anda baca tidak termodifikasi dan data baru dimasukkan. Menggunakan tingkat isolasi transaksi adalah pendekatan yang tepat, bukan menggunakan petunjuk permintaan. Kendra Little memiliki poster yang bagus menjelaskan tingkat isolasi .

93
Remus Rusanu

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

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

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

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

20
Scott Bruns