TL: DR:คำถามด้านล่างนี้ลดลงเหลือ: เมื่อแทรกแถวจะมีหน้าต่างของโอกาสระหว่างการสร้างIdentity
ค่าใหม่และการล็อคกุญแจแถวที่สอดคล้องกันในดัชนีคลัสเตอร์ซึ่งผู้สังเกตการณ์ภายนอกจะเห็นที่ใหม่กว่า Identity
มูลค่าแทรกโดยการทำธุรกรรมพร้อมกันหรือไม่ (ใน SQL Server)
รุ่นโดยละเอียด
ฉันมีตาราง SQL Server พร้อมIdentity
คอลัมน์ที่เรียกว่าCheckpointSequence
ซึ่งเป็นกุญแจสำคัญของดัชนีคลัสเตอร์ของตาราง (ซึ่งยังมีดัชนี nonclustered เพิ่มเติมอีกจำนวนหนึ่ง) แถวถูกแทรกเข้าไปในตารางโดยกระบวนการและเธรดพร้อมกันจำนวนมาก (ที่ระดับการแยกREAD COMMITTED
และไม่มีIDENTITY_INSERT
) ในเวลาเดียวกันมีกระบวนการที่อ่านแถวจากดัชนีคลัสเตอร์เป็นระยะโดยเรียงลำดับตามCheckpointSequence
คอลัมน์นั้น(เช่นเดียวกับที่ระดับการแยกREAD COMMITTED
ด้วยREAD COMMITTED SNAPSHOT
ตัวเลือกที่ถูกปิด)
ขณะนี้ฉันพึ่งพาข้อเท็จจริงที่ว่ากระบวนการอ่านไม่สามารถ "ข้าม" จุดตรวจสอบได้ คำถามของฉันคือ: ฉันสามารถพึ่งพาอสังหาริมทรัพย์นี้ได้หรือไม่? และถ้าไม่ฉันจะทำอย่างไรเพื่อทำให้เป็นจริง
ตัวอย่าง: เมื่อแทรกแถวที่มีค่าเอกลักษณ์ 1, 2, 3, 4 และ 5 ผู้อ่านจะต้องไม่เห็นแถวที่มีค่า 5 ก่อนที่จะเห็นแถวที่มีค่า 4 การทดสอบแสดงให้เห็นว่าแบบสอบถามซึ่งมีORDER BY CheckpointSequence
ข้อ ( และWHERE CheckpointSequence > -1
ประโยค) บล็อกได้อย่างน่าเชื่อถือเมื่อใดก็ตามที่ต้องอ่านแถว 4 แต่ยังไม่ได้ยืนยันแม้ว่าแถวที่ 5 ได้รับการยืนยันแล้ว
ฉันเชื่อว่าอย่างน้อยในทางทฤษฎีอาจมีสภาพการแข่งขันที่นี่ซึ่งอาจทำให้สมมติฐานนี้แตก น่าเสียดายที่เอกสารเกี่ยวกับIdentity
ไม่ได้พูดมากเกี่ยวกับวิธีการIdentity
ทำงานในบริบทของการทำธุรกรรมหลาย ๆ อย่างพร้อมกันเพียง แต่บอกว่า "แต่ละค่าใหม่จะถูกสร้างขึ้นบนพื้นฐานของการเพาะเมล็ด & การเพิ่มขึ้น" และ "แต่ละค่าใหม่สำหรับการทำธุรกรรมเฉพาะนั้นแตกต่างจากการทำธุรกรรมพร้อมกันอื่น ๆ ในตาราง" ( MSDN )
เหตุผลของฉันคือมันต้องทำงานอย่างนี้:
- ธุรกรรมเริ่มต้น (ไม่ว่าจะโดยชัดแจ้งหรือโดยนัย)
- สร้างค่าเอกลักษณ์ (X)
- การล็อคแถวที่เกี่ยวข้องถูกนำมาใช้กับดัชนีคลัสเตอร์ตามค่าข้อมูลประจำตัว (ยกเว้นกรณีที่การเลื่อนระดับการล็อคเริ่มขึ้นซึ่งในกรณีนี้ทั้งตารางถูกล็อค)
- แถวถูกแทรก
- ธุรกรรมมีความมุ่งมั่น (อาจเป็นจำนวนมากในเวลาต่อมา) ดังนั้นการล็อคจะถูกลบอีกครั้ง
ฉันคิดว่าระหว่างขั้นตอนที่ 2 ถึง 3 มีหน้าต่างเล็ก ๆ
- เซสชันที่เกิดขึ้นพร้อมกันสามารถสร้างค่าเอกลักษณ์ถัดไป (X + 1) และดำเนินการตามขั้นตอนที่เหลือทั้งหมด
- ดังนั้นการอนุญาตให้ผู้อ่านเข้ามาถึงจุดนั้นในเวลานั้นเพื่ออ่านค่า X + 1 ซึ่งไม่มีค่าของ X
แน่นอนความน่าจะเป็นของเรื่องนี้ดูต่ำมาก แต่ยัง - มันอาจเกิดขึ้น หรือมันได้หรือไม่
(หากคุณสนใจในบริบท: นี่คือการใช้งานSQL Persistence Engineของ NEventStore NEventStore จะใช้ที่เก็บเหตุการณ์แบบผนวกเท่านั้นที่ทุกเหตุการณ์จะได้รับหมายเลขลำดับจุดตรวจใหม่จากน้อยไปมากลูกค้าอ่านเหตุการณ์จากที่เก็บเหตุการณ์ที่สั่งโดยจุดตรวจ เพื่อทำการคำนวณทุกประเภทเมื่อเหตุการณ์ที่มีจุดตรวจถูกประมวลผลแล้วลูกค้าจะพิจารณาเฉพาะเหตุการณ์ที่ "ใหม่กว่า" เช่นเหตุการณ์ที่มีจุดตรวจสอบ X + 1 ขึ้นไปดังนั้นจึงเป็นสิ่งสำคัญที่เหตุการณ์จะไม่ถูกข้ามไป อย่างที่ไม่เคยได้รับการพิจารณาอีกครั้งในขณะนี้ฉันกำลังพยายามตรวจสอบว่าการIdentity
ใช้งานจุดตรวจสอบแบบพื้นฐานตรงตามข้อกำหนดนี้หรือไม่นี่คือคำสั่ง SQL ที่แน่นอนที่ใช้ : Schema , แบบสอบถามของนักเขียน ,ข้อความค้นหาของผู้อ่าน )
หากฉันพูดถูกและสถานการณ์ที่อธิบายไว้ข้างต้นอาจเกิดขึ้นฉันเห็นเพียงสองตัวเลือกในการจัดการกับพวกเขาซึ่งทั้งสองอย่างนั้นไม่น่าพึงพอใจ:
- เมื่อเห็นค่าลำดับจุดตรวจสอบ X + 1 ก่อนที่จะเห็น X ให้ปิด X + 1 แล้วลองอีกครั้งในภายหลัง อย่างไรก็ตามเนื่องจาก
Identity
แน่นอนสามารถสร้างช่องว่าง (เช่นเมื่อธุรกรรมถูกย้อนกลับ) X อาจไม่เคยมา - ดังนั้นวิธีการเดียวกัน แต่ยอมรับช่องว่างหลังจาก n มิลลิวินาที อย่างไรก็ตามฉันควรถือว่าค่าของ n คืออะไร?
มีความคิดที่ดีกว่านี้ไหม?