ตัวเลือกการล็อคของฉันสำหรับคำสั่งผสานคืออะไร


13

ฉันมีขั้นตอนการจัดเก็บที่ดำเนินการคำสั่งMERGE

ดูเหมือนว่าจะล็อกทั้งตารางตามค่าเริ่มต้นเมื่อดำเนินการผสาน

ฉันกำลังเรียกขั้นตอนการจัดเก็บนี้ภายในธุรกรรมที่ฉันกำลังทำสิ่งอื่นอยู่ด้วยและฉันหวังว่ามันจะล็อคแถวที่ได้รับผลกระทบเท่านั้น

ฉันลองคำใบ้MERGE INTO myTable WITH (READPAST)และดูเหมือนจะล็อคน้อยลง แต่มีคำเตือนในเอกสาร ms ที่บอกว่าสามารถแทรกคีย์ที่ซ้ำกันได้แม้จะข้ามคีย์หลัก

นี่คือคีตารางของฉัน:

CREATE TABLE StudentDetails
(
StudentID INTEGER PRIMARY KEY,
StudentName VARCHAR(15)
)
GO
INSERT INTO StudentDetails
VALUES(1,'WANG')
INSERT INTO StudentDetails
VALUES(2,'JOHNSON')
GO

CREATE TABLE StudentTotalMarks
(
Id INT IDENTITY PRIMARY KEY,
StudentID INTEGER REFERENCES StudentDetails,
StudentMarks INTEGER
)
GO
INSERT INTO StudentTotalMarks
VALUES(1,230)
INSERT INTO StudentTotalMarks
VALUES(2,255)
GO

นี่คือขั้นตอนการจัดเก็บของฉัน:

CREATE PROCEDURE MergeTest 
    @StudentId int,
    @Mark int
AS  

WITH Params
AS
(
    SELECT @StudentId as StudentId,
        @Mark as Mark
)
    MERGE StudentTotalMarks AS stm
    USING Params p
    ON stm.StudentID = p.StudentId
    WHEN MATCHED AND stm.StudentMarks > 250 THEN DELETE
    WHEN MATCHED THEN UPDATE SET stm.StudentMarks = p.Mark
    WHEN NOT MATCHED THEN
        INSERT(StudentID,StudentMarks)
        VALUES(p.StudentId, p.Mark);
GO

นี่คือวิธีที่ฉันสังเกตการล็อก:

begin tran
EXEC MergeTest 1, 1

แล้วในเซสชั่นอื่น:

EXEC MergeTest 2, 2

เซสชั่นที่สองรอก่อนที่จะเสร็จสมบูรณ์ก่อนที่จะดำเนินการต่อไป


1
WITH (READPAST)สั่งให้ SQL Server เพียงข้ามแถวที่ถูกล็อกโดยเซสชันอื่น คุณแน่ใจหรือว่าต้องการทำเช่นนั้น? นอกจากนี้คุณมีการปรับเปลี่ยนกี่แถวในตารางนี้ แสดง schema ของตาราง (รวมถึงดัชนี) และMERGEคำสั่งที่คุณกำลังใช้
Nick Chammas

@NickChammas ขอบคุณสำหรับความช่วยเหลือฉันได้อัปเดตคำถามพร้อมรายละเอียดแล้ว ฉันจินตนาการว่า READPAST จะไม่ดี ...
John Buchanan

คำตอบ:


12

คุณต้องให้ทางเข้าถึงโปรเซสเซอร์ที่มีประสิทธิภาพมากขึ้นเพื่อค้นหาStudentTotalMarksระเบียน ตามที่เขียนไว้เคียวรีต้องการการสแกนแบบเต็มของตารางโดยใช้เพรดิเคตส่วนที่เหลือ[StudentID] = [@StudentId]นำไปใช้กับแต่ละแถว:

สแกนแผน

เอ็นจิ้นจะUล็อก (อัพเดต) เมื่ออ่านเพื่อป้องกันพื้นฐานจากสาเหตุทั่วไปของการหยุดชะงักของการแปลง ลักษณะการทำงานนี้หมายถึงการบล็อกการเรียกใช้งานครั้งที่สองเมื่อพยายามรับการUล็อกในแถวที่ถูกล็อคด้วยการล็อคแบบXเอกสิทธิ์จากการดำเนินการครั้งแรก

ดัชนีต่อไปนี้ให้เส้นทางการเข้าถึงที่ดีขึ้นหลีกเลี่ยงการUล็อคที่ไม่จำเป็น:

CREATE UNIQUE INDEX uq1 
ON dbo.StudentTotalMarks (StudentID) 
INCLUDE (StudentMarks);

ขณะนี้แผนแบบสอบถามรวมถึงการดำเนินการค้นหาStudentID = [@StudentId]ดังนั้นการUล็อกจะถูกร้องขอเฉพาะในแถวเป้าหมาย:

แสวงหาแผน

ดัชนีไม่จำเป็นต้องใช้เพื่อUNIQUEแก้ไขปัญหาในมือ (แม้ว่าINCLUDEจะต้องทำให้ดัชนีครอบคลุมสำหรับแบบสอบถามนี้)

ทำของตารางยังจะแก้ปัญหาเส้นทางการเข้าถึง (และซ้ำซ้อนเห็นได้ชัดคอลัมน์อาจถูกลบออก) คุณควรบังคับใช้คีย์สำรองด้วยหรือจำกัด (และหลีกเลี่ยงการเพิ่มคีย์ตัวแทนที่ไม่มีความหมายโดยไม่มีเหตุผลที่ดี)StudentIDPRIMARY KEYStudentTotalMarksIdUNIQUEPRIMARY KEY

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