การหยุดชะงักในการทำธุรกรรมที่มีหลายตาราง

สถานการณ์ของฉันเป็นเรื่องปกติ: ฉันมีขั้นตอนการจัดเก็บที่ต้องอัปเดตหลายตาราง หากการอัปเดตรายการใดรายการหนึ่งล้มเหลว - การอัปเดตทั้งหมดควรถูกย้อนกลับ คำตอบที่ตรงไปตรงมาคือการรวมการอัปเดตทั้งหมดไว้ในธุรกรรมเดียวแล้วย้อนกลับ อย่างไรก็ตาม ในระบบเช่นเรา สิ่งนี้จะทำให้เกิดปัญหาการทำงานพร้อมกัน เมื่อเราแยกการอัปเดตออกเป็นธุรกรรมสั้นๆ หลายรายการ เราได้รับปริมาณการประมวลผลประมาณ 30 รายการต่อวินาทีก่อนหน้านั้น และปัญหาการหยุดชะงักเริ่มปรากฏขึ้น ถ้าเรารวมไว้ในธุรกรรมเดียวที่ครอบคลุมทั้งหมด - เราจะเกิดขึ้นพร้อมกัน ~2 ต่อวินาทีก่อนที่การหยุดชะงักจะปรากฏขึ้น

ในกรณีของเรา เราจะวางบล็อก try-catch ไว้หลังธุรกรรมสั้นๆ ทุกครั้ง และลบ/อัปเดตการเปลี่ยนแปลงจากรายการก่อนหน้าด้วยตนเอง โดยพื้นฐานแล้วเราเลียนแบบพฤติกรรมการทำธุรกรรมด้วยวิธีที่มีราคาแพงมาก... มันใช้งานได้ดีเนื่องจากมีการเขียนมาอย่างดีและไม่ได้รับการ "ย้อนกลับ" มากนัก... สิ่งหนึ่งที่วิธีนี้ไม่สามารถแก้ไขได้เลยคือกรณีการหมดเวลาของคำสั่งจากเว็บ เซิร์ฟเวอร์ / ไคลเอนต์

ฉันได้อ่านแบบฟอร์มและบล็อกต่างๆ อย่างกว้างขวาง และสแกนผ่าน MSDN แล้ว แต่ยังไม่พบวิธีแก้ปัญหาที่ดี หลายคนได้นำเสนอปัญหาแล้ว แต่ฉันยังไม่เห็นวิธีแก้ปัญหาที่ดี

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

สมมติว่า ไม่ใช่ปัญหาการปรับให้เหมาะสม ตารางเกือบจะถึงการปรับให้เหมาะสมสูงสุดแล้ว และสามารถให้ปริมาณงานที่สูงมากตราบใดที่ไม่เกิดการหยุดชะงัก ไม่มีการล็อคตาราง/การล็อคหน้า ฯลฯ การล็อคแถวทั้งหมดในการอัปเดต - แต่เมื่อคุณมีเซสชันที่เกิดขึ้นพร้อมกันจำนวนมาก บางเซสชันจำเป็นต้องอัปเดตแถวเดียวกัน...

มันสามารถผ่านทาง SQL, ฝั่งไคลเอ็นต์ C#, ฝั่งเซิร์ฟเวอร์ C# (ขยายเซิร์ฟเวอร์ SQL?) มีวิธีแก้ไขปัญหาดังกล่าวในหนังสือ/บล็อกที่ฉันไม่พบหรือไม่

เรากำลังใช้ SQL Server 2008 R2 โดยมีไคลเอ็นต์ .NET/เว็บเซิร์ฟเวอร์เชื่อมต่ออยู่ ตัวอย่างรหัส:

สร้างขั้นตอน sptest เริ่มต้นธุรกรรม อัพเดต table1 อัพเดต table2 ยอมรับธุรกรรม

ในกรณีนี้ ถ้ารัน sptest สองครั้ง อินสแตนซ์ที่สองจะไม่สามารถอัปเดตตาราง 1 ได้จนกว่าอินสแตนซ์ 1 จะคอมมิต เมื่อเทียบกับสิ่งนี้

สร้าง sptest2 อัปเดต table1 อัปเดต table2

Sptest2 มีปริมาณงานที่สูงกว่ามาก - แต่มีโอกาสที่จะทำให้ข้อมูลเสียหายได้ นี่คือสิ่งที่เราพยายามแก้ไข มีวิธีแก้ทางทฤษฎีสำหรับเรื่องนี้หรือไม่?

ขอบคุณ เจส


person user2995891    schedule 19.03.2014    source แหล่งที่มา
comment
การพยายามใช้ธุรกรรมที่บำรุงรักษาแอปพลิเคชันจะล้มเหลว (ฉันเคยทำงานบนระบบที่พยายาม) สิ่งที่ดีเกี่ยวกับระดับฐานข้อมูลคือสามารถรอดพ้นจากสิ่งต่างๆ เช่น ไฟฟ้าดับกะทันหันและเซิร์ฟเวอร์ล่ม - คุณสามารถพูดแบบเดียวกันเกี่ยวกับแอปพลิเคชันของคุณได้หรือไม่ DB ได้รับการทดสอบล่วงหน้า ดีมาก และอาจเร็วกว่าระบบโดยรวมใดๆ ที่คุณสามารถนำไปใช้ในแอปพลิเคชันได้ เราขอรายละเอียดเพิ่มเติมได้ไหม? เหตุใดคุณจึงมีหลายเธรดที่อัปเดตแถวเดียวกัน ธุรกรรมมีไว้เพื่อป้องกันข้อผิดพลาด แต่ควรหลีกเลี่ยงความขัดแย้งตั้งแต่แรก...   -  person Clockwork-Muse    schedule 21.03.2014


คำตอบ (2)


ฉันจะบอกว่าคุณควรเจาะลึกเพื่อค้นหาสาเหตุที่ทำให้เกิดการหยุดชะงัก เป็นไปได้ว่าคุณควรเปลี่ยนลำดับการอัปเดตเพื่อหลีกเลี่ยง บางทีดัชนีบางตัวอาจเป็น "ความผิด"

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

person Jānis    schedule 21.03.2014

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

INNER JOIN LookupTable (with NOLOCK) lut on lut.ID=SomeOtherTableID

สิ่งนี้จะบอกแบบสอบถามว่าฉันไม่สนใจการอัปเดตที่ทำกับ SomeOtherTable

วิธีนี้สามารถลดปัญหาของคุณได้ในกรณีส่วนใหญ่ สำหรับการหยุดชะงักที่ยากขึ้น ฉันได้ใช้กราฟการหยุดชะงักที่ถูกสร้างขึ้นและส่งอีเมลเมื่อเกิดการหยุดชะงักซึ่งมีข้อมูลรายละเอียดทั้งหมดสำหรับการหยุดชะงัก

person Ross Bush    schedule 20.03.2014
comment
ขอบคุณสำหรับคำตอบ. จริงๆ แล้วเราใช้ with(nolock) ยิ่งไปกว่านั้น เราพยายามที่จะไม่เลือกรายการทั้งหมดออกจากธุรกรรมโดยสิ้นเชิง ฉันรู้ว่ามีวิธีแก้ไขปัญหาต่างๆ สำหรับการจัดการการหยุดชะงัก แต่เรากำลังใช้อยู่ คำถามของฉันคือวิธีแก้ปัญหาทางโปรแกรมใดๆ ที่สามารถแก้ปัญหาได้ ไม่ใช่จัดการมัน - person user2995891; 20.03.2014
comment
คุณมีกระบวนการที่ใช้เวลานานซึ่งทำงานควบคู่ไปกับการอัปเดตของคุณซึ่งอาจทำการล็อคแบบเอกสิทธิ์เฉพาะบุคคลบนทรัพยากรของคุณ เช่น รายงาน ตัวแทนบริการ การอัปเดตแบบแบตช์ ฯลฯ เป็นต้น - person Ross Bush; 20.03.2014