การขยายคำตอบของมาร์ค ...
เมื่อไคลเอนต์เหตุการณ์หมดเวลาเกิดขึ้น (.net CommandTimeout ตัวอย่าง) ไคลเอนต์ส่ง "ABORT" ไปยัง SQL Server SQL Server เพียงแค่ละทิ้งการประมวลผลแบบสอบถาม ไม่มีธุรกรรมถูกย้อนกลับไม่มีการปลดล็อค
ตอนนี้การเชื่อมต่อจะถูกส่งกลับไปยังกลุ่มการเชื่อมต่อดังนั้นจึงไม่ได้ปิดลงใน SQL Server หากสิ่งนี้เกิดขึ้น (ผ่าน KILL หรือไคลเอนต์รีบูต ฯลฯ ) การทำธุรกรรม + การล็อคจะถูกล้าง โปรดทราบว่า sp_reset_connection จะไม่หรือไม่ล้างข้อมูลแม้ว่าจะมีการโฆษณาให้ทำก็ตาม
เศษซากจากการแท้งนี้จะบล็อกกระบวนการอื่น ๆ
วิธีที่จะทำให้การทำธุรกรรมที่ชัดเจนของ SQL Server + ล็อคในการหมดเวลาของลูกค้า (อย่างเคร่งครัดเหตุการณ์ ABORT) คือการใช้ SET XACT_ABORT ON
คุณสามารถตรวจสอบได้ว่านี่เป็นการเปิด 2 หน้าต่างแบบสอบถามใน SSMS
หน้าต่าง 1:
ในเมนู Query..Query Options ตั้งค่าการหมดเวลา 5 วินาทีจากนั้นเรียกใช้สิ่งนี้
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
หน้าต่าง 2 นี้จะรอตลอดไป (หรือหมดเวลาของคุณ)
SELECT * FROM sometable
SET XACT_ABORT ON มีผลข้างเคียงที่น่าสนใจเช่นกัน:
- @@ TRANCOUNT ถูกตั้งค่าเป็นศูนย์ในการย้อนกลับโดยปริยาย แต่ข้อผิดพลาด 266 ถูกระงับ (สิ่งนี้จะเกิดขึ้นหาก @@ TRANCOUNT แตกต่างกันเมื่อเข้าและออกจาก proc ที่จัดเก็บ)
- XACT_STATE จะเป็น -1 (เป็น "ถึงวาระ")
การรวมกันของสิ่งนี้หมายความว่าคุณไม่สามารถใช้ SAVEPOINTS (แม้ว่าฉันไม่สามารถจำพฤติกรรมที่แน่นอนได้) สำหรับการกระทำ / ย้อนกลับบางส่วน ซึ่งเหมาะกับฉัน
ลิงก์ใน SET XACT_ABORT:
บน procs ที่จัดเก็บซ้อนกัน:
บน sp_reset_connection: