1.1 บทนำ
และตอนนี้ความสนุกก็เริ่มต้นขึ้น - ทฤษฎีวิธีการทำงานของธุรกรรม วิธีทำให้ระบบทำงานต่อไปเมื่อคุณเปลี่ยนข้อมูลเดียวกันในเธรดต่างๆ หรือคุณต้องการทำธุรกรรมหนึ่งในรายการอื่น? เราจะเริ่มหาคำตอบสำหรับคำถามเหล่านี้โดยศึกษาการแยกธุรกรรม ...
ระดับการแยกธุรกรรมเป็นค่าเงื่อนไขที่กำหนดขอบเขต ซึ่งเป็นผลมาจากการดำเนินการธุรกรรมแบบขนานทางตรรกะใน DBMS ข้อมูลที่ไม่สอดคล้องกันจะได้รับอนุญาต สเกลของระดับการแยกธุรกรรมประกอบด้วยค่าจำนวนหนึ่ง โดยเรียงลำดับจากต่ำสุดไปสูงสุด ระดับการแยกที่สูงขึ้นสอดคล้องกับความสอดคล้องของข้อมูลที่ดีขึ้น แต่การใช้อาจลดจำนวนของธุรกรรมแบบขนานทางกายภาพ
ในทางกลับกัน ระดับการแยกที่ต่ำกว่าทำให้สามารถทำธุรกรรมแบบขนานได้มากขึ้น แต่ลดความแม่นยำของข้อมูล ดังนั้น การเลือกระดับของการแยกธุรกรรมที่ใช้ ผู้พัฒนาระบบข้อมูลในระดับหนึ่งจึงให้ทางเลือกระหว่างความเร็วของการทำงานและการรับประกันความสอดคล้องของข้อมูลที่ได้รับจากระบบ
ปัญหาการเข้าถึงพร้อมกันโดยใช้ธุรกรรม
เมื่อทำธุรกรรมพร้อมกัน อาจเกิดปัญหาต่อไปนี้ได้:
- การอัปเดตที่หายไป - หากบล็อกข้อมูลหนึ่งบล็อกเปลี่ยนแปลงพร้อมกันโดยธุรกรรมที่แตกต่างกัน การเปลี่ยนแปลงทั้งหมดจะสูญหาย ยกเว้นบล็อกสุดท้าย
- การอ่าน "สกปรก" (อังกฤษ อ่านสกปรก) - การอ่านข้อมูลที่เพิ่มหรือเปลี่ยนแปลงโดยธุรกรรมซึ่งจะไม่ได้รับการยืนยันในภายหลัง (ย้อนกลับ)
- อ่านซ้ำไม่ได้ (อังกฤษ อ่านซ้ำไม่ได้) - เมื่ออ่านซ้ำภายในธุรกรรมเดียวกัน ข้อมูลที่อ่านก่อนหน้านี้จะเปลี่ยนไป
- phantom อ่าน - ธุรกรรมหนึ่งระหว่างการดำเนินการหลายครั้งเลือกหลายแถวตามเกณฑ์เดียวกัน ธุรกรรมอื่นระหว่างการดึงข้อมูลเหล่านี้จะเพิ่มแถวหรือแก้ไขคอลัมน์ของแถวบางแถวที่ใช้ในเกณฑ์การดึงข้อมูลของธุรกรรมแรกและสิ้นสุดได้สำเร็จ ผลที่ได้คือการเลือกเดียวกันในธุรกรรมแรกจะให้ชุดแถวที่แตกต่างกัน
พิจารณาสถานการณ์ที่อาจเกิดปัญหาเหล่านี้
1.2 อัปเดตที่หายไป
สถานการณ์เมื่อบล็อกข้อมูลหนึ่งถูกเปลี่ยนแปลงพร้อมกันโดยธุรกรรมที่แตกต่างกัน การเปลี่ยนแปลงอย่างใดอย่างหนึ่งจะหายไป
สมมติว่ามีธุรกรรมสองรายการที่ทำงานพร้อมกัน:
ธุรกรรม 1 | ธุรกรรม 2 |
---|---|
อัปเดต tbl1 ตั้งค่า f2=f2+20 โดยที่ f1=1; | อัปเดต tbl1 ตั้งค่า f2=f2+25 โดยที่ f1=1; |
ในธุรกรรมทั้งสอง ค่าของฟิลด์ f2 จะเปลี่ยนไป เมื่อเสร็จสิ้น ค่าของฟิลด์จะต้องเพิ่มขึ้น 45 ในความเป็นจริง ลำดับของการกระทำต่อไปนี้อาจเกิดขึ้น:
- ธุรกรรมทั้งสองพร้อมกันอ่านสถานะปัจจุบันของฟิลด์ ไม่จำเป็นต้องมีการทำงานพร้อมกันทางกายภาพที่แน่นอนที่นี่ ก็เพียงพอแล้วที่การดำเนินการอ่านลำดับที่สองจะเสร็จสิ้นก่อนที่ธุรกรรมอื่นจะเขียนผลลัพธ์
- ธุรกรรมทั้งสองจะคำนวณค่าของฟิลด์ใหม่โดยการเพิ่ม 20 และ 25 ตามลำดับ ไปยังค่าที่อ่านก่อนหน้านี้
- ธุรกรรมพยายามเขียนผลลัพธ์ของการคำนวณกลับไปที่ฟิลด์ 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 ให้ผลลัพธ์ที่แตกต่างกัน สถานการณ์นี้เรียกว่าการอ่านผี (การอ่านผี) แตกต่างจากการอ่านซ้ำซึ่งผลลัพธ์ของการเข้าถึงข้อมูลซ้ำไม่ได้เปลี่ยนไปเนื่องจากการเปลี่ยนแปลง/การลบข้อมูล แต่เกิดจากการปรากฏของข้อมูลใหม่ (แฟนทอม)