DB Recovery: Log-Based Recovery

Log is a widely used structure for recording database modifications.

โดย ปกติ แล้วการที่เราสั่ง commit บน DB ใดๆ ไม่ได้หมายถึงว่า ข้อมูลนั้นๆ จะไม่ถูกเขียนลงบน disk ทันที แค่เป็นการส่งข้อมูลให้ DB ซึ่ง DBMS ก็จะสัญญาว่า ข้อมูลเหล่านี้จะ้ต้องถูกเก็บลงบน disk ไม่ว่า ต่อไปจะมี system crash หรือกรณีใดๆ ก็ตาม

ซึ่ง log-based recovery เป็นวิธีการหนึ่งของ DBMS ที่ใช้ในการทำให้ข้อมูลที่ commit ไปแล้ว สามารถแสดงได้ถูกต้องหลังจากมี system crash แม้ว่าข้อมูลเหล่านั้นจะยังไม่ได้ถูกเขียนบน disk ก็ตาม

วิธีการ คือ ทุกครั้งที่มีการแก้ไขข้อมูลใน DB ข้อมูลนั้นๆ จะถูกเขียนลงบน log buffer บน memory และ log file ด้วย โดยข้อมูลที่เขียนไปลง log จะประกอบไปด้วย transaction id, data-item id, old value, new value และเมื่อมีคำสั่ง commit ก็จะมีการเขียนไปลง log ด้วยว่า transaction id ใด commit

เมื่อมี system crash เกิดขึ้น และเมื่อมีการ restart DBMS หรือใดๆ DBMS จะมีการทำงานตามลำดับคือ
1. อ่าน log file ย้อนกลับจากข้างท้าย และ ดูว่า transaction ใด commit
2. แยก transaction ที่ commit ใส่ไว้ที่ redo list นอกนั้นแยกลง undo list
3. หลังจากนั้น DBMS จะอ่าน old value ใน undo list มาแก้ไขข้อมูลใน DB
4. อ่าน new value ใน redo list ในแก้ไขใน DB

เมื่อทำเสร็จเรียบร้อย เราก็จะได้ข้อมูลที่ถูกต้องใน DB
หมายเหตุ: Oracle ไม่ได้เก็บ log file ไว้เป็น file เหมือนอย่าง file บน disk ทั่วๆ ไป แต่เก็บเป็นเนื้อที่ส่วนหนึ่งของ DB

log file ในปัจจุบันมีการแยกออกเป็น 2 แบบ คือ

  1. After Image Journal (AIJ) หรือ Redo log file ซึ่ง จะเก็บเฉพาะ new value ไม่เก็บ old value

  2. Before Image Journal (BIJ) หรือ Undo log file หรือ Undo จะตรงกันข้ามคือ เก็บ old value ไม่มี new value


ซึ่ง BIJ จะใช้สำหรับการ transaction ที่ยังไม่ได้ commit เท่านั้น เพื่อที่จะ rollback ข้อมูลกลับมาเมื่อมี system crash ระหว่างทาง ดังนั้น BIJ สามารถ recycle ตัวเองได้เมื่อ transaction commit ไปแล้ว BIJ จึงอาจจะกำหนดขนาดไว้คงที่ค่าหนึ่ง ให้เพียงพอกับขนาดของ transaction ในกรณีที่ BIJ เต็ม ซึ่งเกิดจากมีการ update หรือ delete ข้อมูลจำนวนมากๆ transaction ที่เป็นต้นเหตุจะ roll back สำหรับวิธีแก้ไข คือ
- ขยายขนาด BIJ ให้ใหญ่พอ
- ยกเลิก BIJ ชั่วคราว หรือ bypass BIJ เฉพาะ transaction ใหญ่ๆ
- หาวิธีแบ่ง transaction ใหญ่ๆ ให้เป็น transaction ย่อยๆ

แต่สำหรับ AIJ ซึ่งใช้เก็บข้อมูล new value ดังนั้นจึงไม่สามารถ recycle ข้อมูลได้ จะต้องเก็บไปเรื่อยๆ ถ้าี่ AIJ เต็ม จะมีผลให้ DBMS หยุดทำงาน หรือบาง DBMS ยังคงทำงานต่อไป แต่ว่า user จะต้องรับความเสี่ยงในกรณีมี system crash แต่ในปัจจุบันมีวิธีแก้ปัญหานี้อย่างถาวร คือ มีชุด AIJ เป็นไฟล์ชุดหนึ่ง เมื่อตัวแรกเต็ม ก็จะเก็บต่อในตัวถัดไป ซึ่งเปิดโอกาสให้ dba หรือ operator archive AIJ ตัวที่เต็มไปแล้ว และสามารถวนกลับมาให้เก็บข้อมูลต่อไป

Log-based Recovery classification

  1. ประเภทที่เก็บแต่ BIJ (สำหรับ DBMS ตัวเก่าๆ) ซึ่งเลี่ยงปัญหา AIJ เต็ม ซึ่ง DBMS พวกนี้การ commit แต่ละครั้งจะหมายถึงการถูกเก็บลง DB space เสมอ (แต่ไม่ไ้ด้หมายความว่า เมื่อเราสั่ง commit DBMS จะเขียนข้อมูลกลับลง disk ทันที) ดังนั้น เมื่อมี system crash จึงทำเฉพาะในส่วนของ redo list เท่านั้นได้
    ข้อดี: ตอน recovery ทำไ้ด้เร็ว ไม่ต้องเปลืองเนื้อที่ในการเก็บ AIJ
    ข้อเสีย: การ commit ทำได้ช้า อาจจะเกิดปัญหาเรื่อง performance ต่อไป

  2. Deferred DB Modification ประเภทนี้เก็บแต่ AIJ ซึ่งกรณีนี้จะมีผลต่อ transaction ที่ fail แต่มีการเขียนข้อมูลที่ update ไประหว่างกลาง transaction ดังนั้นกรณีที่ DBMS ทำงานในแบบนี้จะไม่มีการเขียนข้อมูลกลับจนกว่าจะมีคำสั่ง commit เท่านั้น DB พวกนี้ได้แก่พวก workgroup DBMS
    ข้อดี: DBMS แบบนี้บางครั้งเรียกว่า fast commit server หรือ fast commit option เนื่องจาก DBMS พวกนี้จะ commit ข้อมูลใช้เวลาน้อย เหมาะกับ OLTP
    ข้อเสีย: ไม่เหมาะกับการทำงานกับ transaction ขนาดใหญ่ เพราะว่า อาจทำให้ DB Buffer เต็มก่อนการ commit ดังนั้น DBMS พวกนี้จะต้องมี swap area ที่ใช้ขยายขนาด DB Buffer ที่เต็มให้สามารถรองรับการทำงานกับ transaction ใหญ่ๆ ได้

  3. Immediate DB Modification แบบนี้จะต้องมี BIJ แต่อาจจะมีหรือไม่มี AIJ ก็ได้ ซึ่งแบบนี้จะสามารถเขียนลง disk ได้ทันที จะทำก่อนหรือหลัง commit ก็ได้


Checkpoint คือจุดที่กำหนดไ้ว้ว่า ณ.จุดก่อนหน้านั้นข้อมูลนั้นๆ ได้มีการ write ลง DB space แล้ว เมื่อมีการ recovery จึงสามารถทำหลังจากจุด checkpoint ได้ ซึ่งจะทำให้ประหยัดเวลาในการทำ recovery ได้มาก ณ.จุด checkpoint จะมีการทำงานดังนี้
1. เขียนข้อมูลทั้งหมดจาก log buffer ลง log file (บน stable storage)
2. เขียนข้อมูลทั้งหมดจาก DB buffer ลง disk หรือ DB space
3. mark จุด ลงบน log file

No comments:

Post a Comment