1.1 บทนำ

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

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

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

ปัญหาการเข้าถึงพร้อมกันโดยใช้ธุรกรรม

เมื่อทำธุรกรรมพร้อมกัน อาจเกิดปัญหาต่อไปนี้ได้:

  • การอัปเดตที่หายไป - หากบล็อกข้อมูลหนึ่งบล็อกเปลี่ยนแปลงพร้อมกันโดยธุรกรรมที่แตกต่างกัน การเปลี่ยนแปลงทั้งหมดจะสูญหาย ยกเว้นบล็อกสุดท้าย
  • การอ่าน "สกปรก" (อังกฤษ อ่านสกปรก) - การอ่านข้อมูลที่เพิ่มหรือเปลี่ยนแปลงโดยธุรกรรมซึ่งจะไม่ได้รับการยืนยันในภายหลัง (ย้อนกลับ)
  • อ่านซ้ำไม่ได้ (อังกฤษ อ่านซ้ำไม่ได้) - เมื่ออ่านซ้ำภายในธุรกรรมเดียวกัน ข้อมูลที่อ่านก่อนหน้านี้จะเปลี่ยนไป
  • phantom อ่าน - ธุรกรรมหนึ่งระหว่างการดำเนินการหลายครั้งเลือกหลายแถวตามเกณฑ์เดียวกัน ธุรกรรมอื่นระหว่างการดึงข้อมูลเหล่านี้จะเพิ่มแถวหรือแก้ไขคอลัมน์ของแถวบางแถวที่ใช้ในเกณฑ์การดึงข้อมูลของธุรกรรมแรกและสิ้นสุดได้สำเร็จ ผลที่ได้คือการเลือกเดียวกันในธุรกรรมแรกจะให้ชุดแถวที่แตกต่างกัน

พิจารณาสถานการณ์ที่อาจเกิดปัญหาเหล่านี้

1.2 อัปเดตที่หายไป

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

สมมติว่ามีธุรกรรมสองรายการที่ทำงานพร้อมกัน:

ธุรกรรม 1 ธุรกรรม 2
อัปเดต tbl1 ตั้งค่า f2=f2+20 โดยที่ f1=1; อัปเดต tbl1 ตั้งค่า f2=f2+25 โดยที่ f1=1;

ในธุรกรรมทั้งสอง ค่าของฟิลด์ f2 จะเปลี่ยนไป เมื่อเสร็จสิ้น ค่าของฟิลด์จะต้องเพิ่มขึ้น 45 ในความเป็นจริง ลำดับของการกระทำต่อไปนี้อาจเกิดขึ้น:

  1. ธุรกรรมทั้งสองพร้อมกันอ่านสถานะปัจจุบันของฟิลด์ ไม่จำเป็นต้องมีการทำงานพร้อมกันทางกายภาพที่แน่นอนที่นี่ ก็เพียงพอแล้วที่การดำเนินการอ่านลำดับที่สองจะเสร็จสิ้นก่อนที่ธุรกรรมอื่นจะเขียนผลลัพธ์
  2. ธุรกรรมทั้งสองจะคำนวณค่าของฟิลด์ใหม่โดยการเพิ่ม 20 และ 25 ตามลำดับ ไปยังค่าที่อ่านก่อนหน้านี้
  3. ธุรกรรมพยายามเขียนผลลัพธ์ของการคำนวณกลับไปที่ฟิลด์ f2 เนื่องจากเป็นไปไม่ได้ที่จะดำเนินการเขียนสองครั้งพร้อมกัน ในความเป็นจริงแล้ว การดำเนินการเขียนอย่างใดอย่างหนึ่งจะดำเนินการก่อนหน้านี้ และอีกการดำเนินการหนึ่งจะดำเนินการในภายหลัง การดำเนินการเขียนครั้งที่สองจะเขียนทับผลลัพธ์ของการดำเนินการแรก

เป็นผลให้ค่าของฟิลด์ f2 เมื่อเสร็จสิ้นการทำธุรกรรมทั้งสองอาจเพิ่มขึ้นไม่เกิน 45 แต่เพิ่มขึ้น 20 หรือ 25 นั่นคือหนึ่งในธุรกรรมที่เปลี่ยนแปลงข้อมูลจะ "หายไป"

1.3 การอ่าน "สกปรก"

การอ่านข้อมูลที่เพิ่มหรือแก้ไขโดยธุรกรรมที่จะล้มเหลวในภายหลัง (ย้อนกลับ)

สมมติว่าเรามีธุรกรรมสองรายการที่เปิดโดยแอปพลิเคชันต่างๆ ที่เรียกใช้คำสั่ง SQL ต่อไปนี้:

ธุรกรรม 1 ธุรกรรม 2
อัปเดต tbl1 SET f2=f2+1 โดยที่ f1=1;
เลือก f2 จาก tbl1 โดยที่ f1=1;
งานย้อนกลับ;

ในรายการ 1 ค่าของฟิลด์ f2 มีการเปลี่ยนแปลง และจากนั้น ในรายการ 2 ค่าของฟิลด์นี้จะถูกเลือก หลังจากนั้น ธุรกรรมที่ 1 จะถูกย้อนกลับ ดังนั้น ค่าที่ได้รับจากธุรกรรมที่สองจะแตกต่างจากค่าที่จัดเก็บไว้ในฐานข้อมูล

1.4 อ่านซ้ำไม่ได้

สถานการณ์เมื่ออ่านซ้ำภายในธุรกรรมเดียวกัน ข้อมูลที่อ่านก่อนหน้านี้จะเปลี่ยนไป

สมมติว่าเรามีธุรกรรมสองรายการที่เปิดโดยแอปพลิเคชันต่างๆ ที่เรียกใช้คำสั่ง SQL ต่อไปนี้:

ธุรกรรม 1 ธุรกรรม 2
เลือก f2 จาก tbl1 โดยที่ f1=1;
อัปเดต tbl1 ตั้งค่า f2=f2+3 โดยที่ f1=1;
ให้สัญญา;
เลือก f2 จาก tbl1 โดยที่ f1=1;

ในรายการ 2 ค่าของช่อง f2 จะถูกเลือก จากนั้นในรายการ 1 ค่าของช่อง f2 จะเปลี่ยนไป หากคุณลองอีกครั้งเพื่อเลือกค่าจากฟิลด์ f2 ในรายการ 2 จะได้ผลลัพธ์ที่แตกต่างกัน สถานการณ์นี้ยอมรับไม่ได้โดยเฉพาะอย่างยิ่งเมื่อมีการอ่านข้อมูลเพื่อแก้ไขบางส่วนและเขียนกลับไปยังฐานข้อมูล

1.5 การอ่าน "ภูตผี"

สถานการณ์เมื่อระหว่างการอ่านซ้ำภายในธุรกรรมเดียวกัน การเลือกเดียวกันจะให้แถวที่แตกต่างกัน

สมมติว่ามีธุรกรรมสองรายการที่เปิดโดยแอปพลิเคชันต่างๆ ที่เรียกใช้คำสั่ง SQL ต่อไปนี้:

ธุรกรรม 1 ธุรกรรม 2
เลือกผลรวม (f2) จาก tbl1;
INSERT INTO tbl1 (f1,f2) ค่า (15,20);
ให้สัญญา;
เลือกผลรวม (f2) จาก tbl1;

ธุรกรรม 2 ดำเนินการคำสั่ง SQL ที่ใช้ค่าทั้งหมดของฟิลด์ f2 จากนั้นแถวใหม่จะถูกแทรกในรายการที่ 1 ทำให้การดำเนินการคำสั่ง SQL อีกครั้งในรายการที่ 2 ให้ผลลัพธ์ที่แตกต่างกัน สถานการณ์นี้เรียกว่าการอ่านผี (การอ่านผี) แตกต่างจากการอ่านซ้ำซึ่งผลลัพธ์ของการเข้าถึงข้อมูลซ้ำไม่ได้เปลี่ยนไปเนื่องจากการเปลี่ยนแปลง/การลบข้อมูล แต่เกิดจากการปรากฏของข้อมูลใหม่ (แฟนทอม)