สับสนเกี่ยวกับ UPDLOCK, HOLDLOCK


92

ในขณะที่ค้นคว้าการใช้Table Hintsฉันเจอคำถามสองข้อนี้:

คำตอบของทั้งสองคำถามบอกว่าเมื่อใช้(UPDLOCK, HOLDLOCK)กระบวนการอื่น ๆ จะไม่สามารถอ่านข้อมูลบนตารางนั้นได้ แต่ฉันไม่เห็นสิ่งนี้ ในการทดสอบฉันสร้างตารางและเริ่มหน้าต่าง SSMS สองหน้าต่าง จากหน้าต่างแรกฉันรันธุรกรรมที่เลือกจากตารางโดยใช้คำแนะนำตารางต่างๆ ในขณะที่ธุรกรรมกำลังทำงานอยู่จากหน้าต่างที่สองฉันเรียกใช้คำสั่งต่างๆเพื่อดูว่ารายการใดจะถูกบล็อก

ตารางทดสอบ:

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]

จาก SSMS Window 1:

BEGIN TRANSACTION

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

COMMIT TRANSACTION

จาก SSMS Window 2 (ทำงานอย่างใดอย่างหนึ่งต่อไปนี้):

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'

ผลกระทบของคำแนะนำตารางที่แตกต่างกันในคำสั่งที่เรียกใช้ในหน้าต่าง 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

ฉันเข้าใจคำตอบที่ให้ไว้ในคำถามเหล่านั้นเข้าใจผิดหรือทำผิดในการทดสอบหรือไม่? ถ้าไม่คุณจะใช้(UPDLOCK, HOLDLOCK)กับ(HOLDLOCK)คนเดียวทำไม?


คำอธิบายเพิ่มเติมเกี่ยวกับสิ่งที่ฉันพยายามทำให้สำเร็จ:

ฉันต้องการเลือกแถวจากตารางและป้องกันไม่ให้ข้อมูลในตารางนั้นถูกแก้ไขในขณะที่ฉันกำลังประมวลผล ฉันไม่ได้แก้ไขข้อมูลนั้นและต้องการอนุญาตให้มีการอ่านเกิดขึ้น

คำตอบนี้บอกอย่างชัดเจนว่า(UPDLOCK, HOLDLOCK)จะบล็อกอ่าน (ไม่ใช่สิ่งที่ฉันต้องการ) ความคิดเห็นเกี่ยวกับคำตอบนี้บ่งบอกว่าเป็นการHOLDLOCKป้องกันการอ่าน เพื่อพยายามทำความเข้าใจผลของคำแนะนำตารางให้ดีขึ้นและดูว่าUPDLOCKคนเดียวจะทำในสิ่งที่ฉันต้องการได้หรือไม่ฉันได้ทำการทดลองข้างต้นและได้ผลลัพธ์ที่ขัดแย้งกับคำตอบเหล่านั้น

ตอนนี้ฉันเชื่อว่านั่น(HOLDLOCK)คือสิ่งที่ฉันควรใช้ แต่ฉันกังวลว่าฉันอาจทำผิดพลาดหรือมองข้ามบางสิ่งที่จะกลับมากัดฉันในอนาคตดังนั้นคำถามนี้

คำตอบ:


104

ทำไม UPDLOCK block ถึงเลือก? ล็อคเข้ากันได้ของเมทริกซ์แสดงให้เห็นชัดเจนNสำหรับ S / U และ U / S ต่อสู้ในขณะที่ไม่มีความขัดแย้ง

สำหรับHOLDLOCKบอกใบ้สถานะของเอกสาร:

HOLDLOCK: เทียบเท่ากับ SERIALIZABLE สำหรับข้อมูลเพิ่มเติมโปรดดูเป็นลำดับขั้นตอนต่อไปในหัวข้อนี้

...

SERIALIZABLE: ... การสแกนจะดำเนินการด้วยความหมายเดียวกันกับธุรกรรมที่ทำงานในระดับการแยกที่เป็นอันตราย ...

และหัวข้อTransaction Isolation Levelจะอธิบายถึงความหมายของ SERIALIZABLE:

ไม่มีธุรกรรมอื่นใดที่สามารถแก้ไขข้อมูลที่อ่านโดยธุรกรรมปัจจุบันได้จนกว่าธุรกรรมปัจจุบันจะเสร็จสมบูรณ์

ธุรกรรมอื่นไม่สามารถแทรกแถวใหม่ที่มีค่าคีย์ที่จะอยู่ในช่วงของคีย์ที่อ่านโดยคำสั่งใด ๆ ในธุรกรรมปัจจุบันจนกว่าธุรกรรมปัจจุบันจะเสร็จสมบูรณ์

ดังนั้นพฤติกรรมที่คุณเห็นจึงอธิบายได้อย่างสมบูรณ์ในเอกสารผลิตภัณฑ์:

  • UPDLOCK ไม่บล็อก SELECT หรือ INSERT พร้อมกัน แต่บล็อกการอัปเดตหรือ DELETE ของแถวที่เลือกโดย T1
  • HOLDLOCK หมายถึง SERALIZABLE ดังนั้นจึงอนุญาตให้ SELECTS แต่บล็อกการอัปเดตและการลบแถวที่เลือกโดย T1 รวมถึง INSERT ใด ๆ ในช่วงที่เลือกโดย T1 (ซึ่งเป็นตารางทั้งหมดดังนั้นการแทรกใด ๆ )
  • (UPDLOCK, HOLDLOCK): การทดสอบของคุณไม่ได้แสดงสิ่งที่จะปิดกั้นนอกเหนือจากกรณีข้างต้นกล่าวคือธุรกรรมอื่นกับ UPDLOCK ใน T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX ไม่จำเป็นต้องมีคำอธิบาย

คำถามที่แท้จริงคือคุณพยายามบรรลุเป้าหมายอะไร? การเล่นโดยใช้คำแนะนำการล็อคโดยไม่มีความเข้าใจที่สมบูรณ์แบบ 110% เกี่ยวกับความหมายของการล็อคกำลังขอให้มีปัญหา ...

หลังจากแก้ไข OP:

ฉันต้องการเลือกแถวจากตารางและป้องกันไม่ให้ข้อมูลในตารางนั้นถูกแก้ไขในขณะที่ฉันกำลังประมวลผล

คุณควรใช้หนึ่งในระดับการแยกธุรกรรมที่สูงกว่า REPEATABLE READ จะป้องกันไม่ให้ข้อมูลที่คุณอ่านถูกแก้ไข SERIALIZABLE จะป้องกันไม่ให้ข้อมูลที่คุณอ่านถูกแก้ไขและข้อมูลใหม่ถูกแทรก การใช้ระดับการแยกธุรกรรมเป็นแนวทางที่ถูกต้องซึ่งต่างจากการใช้คำแนะนำการสืบค้น Kendra เล็ก ๆ น้อย ๆ มีโปสเตอร์ที่ดี exlaining ระดับแยก


+1 และขอขอบคุณสำหรับการตอบกลับโดยละเอียด ฉันจะอัปเดตคำถามเพื่อเพิ่มรายละเอียดว่าเป้าหมายของฉันคืออะไร
Jeff Ogata

1
@Remus Rusanu คุณช่วยอธิบายให้ละเอียดได้ไหมว่าเหตุใดแนวทางที่ถูกต้องจึงใช้ระดับการแยกแทนที่จะใช้คำแนะนำในการสืบค้น ฉันมีขั้นตอนที่ฉันต้องล็อคตารางสองตารางไม่ให้ถูกแก้ไขและฉันใช้ TABLOCK, HOLDLOCK ฉันควรเปลี่ยนเป็นระดับการแยกและล็อกตารางทั้งหมดในธุรกรรมของฉันหรือไม่
Steve

ฉันต้องการคำอธิบายสำหรับ TABLOCKX :)
niico

หมายเหตุ: ลิงก์สำหรับรายการบล็อกสำหรับ Kendra Little ส่งคืน 404 ฉันไม่พบรายการลงวันที่ 2 กุมภาพันธ์ 2011 ตามที่ลิงก์แนะนำ
Bacon Bits

22

UPDLOCK ใช้เมื่อคุณต้องการล็อคแถวหรือแถวระหว่างคำสั่ง select สำหรับคำสั่งอัพเดตในอนาคต การอัปเดตในอนาคตอาจเป็นคำสั่งถัดไปในธุรกรรม

เซสชันอื่น ๆ ยังคงสามารถดูข้อมูลได้ พวกเขาไม่สามารถรับล็อคที่ไม่สามารถใช้งานร่วมกับ UPDLOCK และ / หรือ HOLDLOCK ได้

คุณใช้ UPDLOCK เมื่อคุณต้องการป้องกันไม่ให้เซสชันอื่นเปลี่ยนแถวที่คุณล็อกไว้ มันจำกัดความสามารถในการอัปเดตหรือลบแถวที่ถูกล็อก

คุณใช้ HOLDLOCK เมื่อคุณต้องการป้องกันไม่ให้เซสชันอื่นเปลี่ยนแปลงข้อมูลใด ๆ ที่คุณกำลังดูอยู่ จะจำกัดความสามารถในการแทรกอัปเดตหรือลบแถวที่คุณล็อกไว้ สิ่งนี้ช่วยให้คุณสามารถเรียกใช้แบบสอบถามอีกครั้งและเห็นผลลัพธ์เดียวกัน


1
ขอบคุณ แต่ฉันคิดว่าคุณไม่ได้ตอบคำถามของฉันจริงๆ: คำตอบสำหรับคำถามเหล่านั้นผิดหรือไม่ในการระบุว่า(UPDLOCK,HOLDLOCK)บล็อกอ่านและมีเหตุผลที่จะใช้(UPDLOCK,HOLDLOCK)แทนเพียงแค่(HOLDLOCK)?
Jeff Ogata

คำพูดที่สองของฉันตอบคำถามของคุณพวกเขาผิด เซสชันอื่น ๆ ยังคงอ่านข้อมูลได้
Scott Bruns

Updlock, Holdlock ไม่เหมือนกับ Holdlock Updlock, Holdlock จะล็อกแถวสำหรับการอัปเดตและทำให้ธุรกรรมของคุณเป็นอนุกรม Holdlock เพียงแค่ทำให้ธุรกรรมของคุณเป็นอนุกรม ไม่ได้ล็อกแถวที่เลือกไว้สำหรับการเข้าถึงเพิ่มเติม
Scott Bruns

"UPDLOCK ถูกใช้เมื่อคุณต้องการล็อกแถวหรือแถวระหว่างคำสั่ง select สำหรับคำสั่งอัพเดตในอนาคต" ฉันชอบสิ่งนี้เนื่องจาก XLOCK อาจไม่ทำงานในบางครั้ง
Yiping
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.