หมดเวลาธุรกรรม SQL Server


9

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

คำตอบ:


20

การขยายคำตอบของมาร์ค ...

เมื่อไคลเอนต์เหตุการณ์หมดเวลาเกิดขึ้น (.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:


อนาคตกล่าวสวัสดี! "โปรดทราบว่า sp_reset_connection จะไม่ล้างข้อมูลหรือไม่แม้ว่าจะมีการโฆษณาให้ทำก็ตาม" - ฉันไม่เชื่อว่านี่เป็นเรื่องจริงอีกต่อไปใน SQL Server เวอร์ชันล่าสุดหรือไม่
คามิลค์

11

ฉันตอบด้วยความลังเลเพราะไม่มีข้อมูลเพียงพอในคำอธิบายปัญหาของคุณที่จะเป็น 100% แน่นอนว่านี่เป็นคำแนะนำที่ดีที่สุด "แฮงค์หรือโยนข้อยกเว้น" แนะนำแหล่งที่มาของปัญหาที่ไม่เข้าใจอย่างเหมาะสมดังนั้นโปรดดำเนินการด้วยความระมัดระวัง

SET XACT_ABORT ONทางออกที่ง่ายที่สุดในการนี้น่าจะเป็น

XACT_ABORTกำหนดว่า SQL Server จะย้อนกลับธุรกรรมในกรณีที่เกิดข้อผิดพลาดรันไทม์ ค่าเริ่มต้นSET XACT_ABORT OFFจะย้อนกลับเฉพาะคำสั่งที่ทำให้เกิดข้อผิดพลาดโดยไม่เปิดธุรกรรมหลัก

ผลข้างเคียง "gotcha" ของการตั้งค่าเริ่มต้นคือการหมดเวลาอาจทำให้เกิดปัญหาเดียวกันธุรกรรมเปิดที่เป็นความรับผิดชอบของลูกค้าในการจัดการและย้อนกลับ หากลูกค้าไม่ได้ลอง / จับ / ย้อนกลับการทำธุรกรรมจะยังคงเปิดให้บริการจนถึงเข้าร่วมด้วย (และฉันอ้าง @gbn) KILL <spid>อัลตร้าความรุนแรงของ

บทความที่ยกมาErland Sommarskog ของบทความเกี่ยวกับการจัดการข้อผิดพลาดใน SQL Serverประกอบด้วยพื้นหลังและกลยุทธ์ทั้งหมดที่คุณต้องการสำหรับจัดการกับสถานการณ์เหล่านี้และอื่น ๆ

แก้ไข (ตามความเห็น): ในการระบุธุรกรรมที่เปิดอยู่sp_whoisactiveอาจเป็นคุณลักษณะที่สมบูรณ์ที่สุด


ฉันค้นพบกับ Googling แล้ววิธีหาธุรกรรมเปิดเมื่อแฮงค์เกิดขึ้นบางทีนี่อาจเป็นทางออกที่ดีที่สุด นั่นคือการค้นหาสิ่งที่ทำให้เกิดการทำธุรกรรม unclosed ในรหัสและแก้ไขหลุมในรหัส เพื่อการอ้างอิงสำหรับผู้อื่น DBCC OPENTRAN ส่งคืนธุรกรรมที่แอ็คทีฟที่เก่าแก่ที่สุด -> msdn.microsoft.com/en-us/library/ms182792.aspxหรืออะไรทำนองนี้? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/…
David Gray Wright

ฉันคิดเสมอว่า Erland ไม่ยุติธรรมกับ SET XACT_ABORT sommarskog.se/error-handling-I.html#XACT_ABORT
gbn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.