Categories
Database Backup

**

สำหรับผู้ดูแลระบบฐานข้อมูล (DBA) และวิศวกร DevOps ที่จัดการ PostgreSQL ในสภาพแวดล้อมการทำงานจริง (Production) การบรรลุเป้าหมาย Recovery Point Objective (RPO) ที่ใกล้ศูนย์ถือเป็นภารกิจหลัก หัวใจสำคัญของความสามารถในการกู้คืนระบบจากภัยพิบัติและการกู้คืนข้อมูล ณ จุดเวลาใดเวลาหนึ่ง (Point-in-Time Recovery หรือ PITR) ของ PostgreSQL คือ Write-Ahead Logging (WAL) ในขณะที่ WAL ช่วยให้มั่นใจได้ถึงการปฏิบัติตามมาตรฐาน ACID โดยการบันทึกธุรกรรมก่อนที่จะเขียนลงในไฟล์ข้อมูล แต่การ ทำสำรองข้อมูล WAL (WAL archiving) คือกลไกที่เก็บรักษาบันทึกเหล่านี้ไว้สำหรับการสำรองข้อมูลและการทำสำเนา (Replication) ในระยะยาว

อย่างไรก็ตาม การกำหนดค่าการทำสำรองข้อมูล WAL ไม่ใช่การตั้งค่าเพียงครั้งเดียวแล้วจบไป การกำหนดค่าที่ผิดพลาด ความล้มเหลวที่ตรวจไม่พบ และความเข้าใจที่คลาดเคลื่อนเกี่ยวกับสถาปัตยกรรม อาจนำไปสู่การสูญเสียข้อมูลครั้งใหญ่ สถานการณ์ Split-brain หรือฐานข้อมูลล่มโดยสมบูรณ์

ในคู่มือฉบับสมบูรณ์นี้ เราจะสำรวจสถาปัตยกรรมของการทำสำรองข้อมูล WAL ใน PostgreSQL ระบุข้อผิดพลาดทั่วไปที่นำไปสู่การสูญเสียข้อมูล และสรุปแนวทางปฏิบัติที่ดีที่สุดระดับองค์กรเพื่อให้แน่ใจว่าฐานข้อมูลของคุณยังคงมีความยืดหยุ่นและพร้อมใช้งาน

ทำความเข้าใจสถาปัตยกรรม WAL ของ PostgreSQL

ก่อนที่จะเจาะลึกถึงข้อผิดพลาด สิ่งสำคัญคือต้องเข้าใจว่า PostgreSQL จัดการกับบันทึกธุรกรรมอย่างไร

PostgreSQL จะเขียนการแก้ไขทั้งหมดลงในส่วนของ WAL (โดยปกติจะมีขนาดไฟล์ละ 16MB) ซึ่งอยู่ในไดเรกทอรี pg_wal (เดิมคือ pg_xlog ในเวอร์ชันก่อนหน้า 10) ทุกธุรกรรมจะถูกบันทึกตามลำดับ โดยมี Log Sequence Number (LSN) กำกับไว้

เมื่อส่วนของ WAL เต็ม PostgreSQL จะสลับไปใช้ส่วนใหม่ เพื่อป้องกันไม่ให้ไดเรกทอรี pg_wal ขยายขนาดขึ้นเรื่อยๆ PostgreSQL จะนำส่วน WAL เก่ากลับมาใช้ใหม่หรือลบออกเมื่อไม่จำเป็นสำหรับการกู้คืนจากความผิดพลาด (Crash Recovery) หรือการทำสำเนา (Replication) อีกต่อไป

การทำสำรองข้อมูล WAL (WAL Archiving) จะเข้ามาแทรกแซงกระบวนการนำกลับมาใช้ใหม่นี้ เมื่อเปิดใช้งาน archive_mode แล้ว PostgreSQL จะดำเนินการตาม archive_command ที่ผู้ใช้กำหนด (หรือใช้ archive_library ใน PostgreSQL 15 ขึ้นไป) เพื่อคัดลอกส่วน WAL ที่เสร็จสมบูรณ์ไปยังตำแหน่งสำรองที่ปลอดภัยก่อนที่จะถูกลบหรือเขียนทับ

ในการทำ Point-in-Time Recovery (PITR) คุณต้องมีส่วนประกอบสองอย่าง:
1. ข้อมูลสำรองพื้นฐาน (Base backup) ที่ถูกต้อง
2. ห่วงโซ่ของไฟล์ WAL ที่สำรองไว้ซึ่งต่อเนื่องกันตั้งแต่เวลาที่ทำ Base backup จนถึงเวลาที่คุณต้องการกู้คืน

หากห่วงโซ่ WAL ขาดช่วง การทำ PITR ของคุณจะล้มเหลว

การกำหนดค่า WAL Archiving สำหรับ Production

ในการเปิดใช้งาน WAL Archiving คุณต้องแก้ไขไฟล์ postgresql.conf ของคุณ การกำหนดค่าพื้นฐานจำเป็นต้องตั้งค่า wal_level, เปิดใช้งาน archive_mode และกำหนด archive_command

# postgresql.conf
wal_level = replica             # จำเป็นต้องใช้ 'replica' หรือ 'logical' สำหรับการทำ archiving
archive_mode = on               # เปิดใช้งานกระบวนการ archiver
archive_command = 'test ! -f /mnt/nfs/archive/%f && cp %p /mnt/nfs/archive/%f'
archive_timeout = 600           # บังคับให้สลับ WAL ทุกๆ 10 นาที

ใน archive_command:
* %p หมายถึงพาธแบบเต็มไปยังไฟล์ WAL ที่จะทำสำรองข้อมูล
* %f หมายถึงชื่อไฟล์ของไฟล์ WAL

แม้ว่าการกำหนดค่าข้างต้นจะดูตรงไปตรงมา แต่การพึ่งพาคำสั่งเชลล์ง่ายๆ ในสภาพแวดล้อมระดับองค์กรนั้นมีความเสี่ยงที่สำคัญ

ข้อผิดพลาดทั่วไปในการทำ WAL Archiving

ข้อผิดพลาดที่ 1: “ความสำเร็จที่เงียบเชียบ” ของ archive_command

PostgreSQL พึ่งพา exit code ของ archive_command ทั้งหมด หากคำสั่งส่งค่ากลับเป็น 0 PostgreSQL จะถือว่าไฟล์ WAL ถูกสำรองไว้อย่างปลอดภัยแล้วและดำเนินการลบไฟล์ต้นฉบับทิ้ง

ข้อผิดพลาดทั่วไปคือการใช้คำสั่งที่ส่งค่ากลับเป็น 0 แม้ว่าข้อมูลจะยังไม่ได้ถูกเขียนลงในที่จัดเก็บถาวรอย่างปลอดภัย ตัวอย่างเช่น คำสั่ง cp แบบง่ายอาจส่งค่าความสำเร็จทันทีที่ข้อมูลเข้าสู่ OS page cache บนเซิร์ฟเวอร์ปลายทาง หากเซิร์ฟเวอร์ปลายทางไฟฟ้าดับก่อนที่แคชจะถูกเขียนลงดิสก์ ไฟล์ WAL จะสูญหาย แต่ PostgreSQL ได้ลบไฟล์ต้นฉบับในเครื่องไปแล้ว

ความเสี่ยง: ห่วงโซ่ WAL ขาดช่วงและไม่สามารถทำ PITR ได้ ซึ่งมักจะตรวจพบก็ต่อเมื่อเกิดสถานการณ์ที่ต้องกู้คืนระบบจากภัยพิบัติเท่านั้น

การป้องกัน: ตรวจสอบให้แน่ใจว่าสคริปต์การสำรองข้อมูลของคุณบังคับให้มีการเขียนแบบซิงโครนัส (Synchronous writes) หากใช้คำสั่งเชลล์มาตรฐาน ให้ใช้เครื่องมือที่รับประกันว่าข้อมูลถูกเขียนลงดิสก์จริง หรือเขียนสคริปต์ครอบ (Wrapper script) ที่ตรวจสอบขนาดไฟล์และ checksum หลังการถ่ายโอน

ข้อผิดพลาดที่ 2: พื้นที่พาร์ทิชัน pg_wal เต็ม (WAL Bloat)

หาก archive_command ล้มเหลว (ส่งค่า exit code ที่ไม่ใช่ 0) เนื่องจากเครือข่ายขัดข้อง สิทธิ์ไม่ถูกต้อง หรือดิสก์ปลายทางเต็ม PostgreSQL จะเก็บไฟล์ WAL ไว้ในไดเรกทอรี pg_wal และพยายามรันคำสั่งซ้ำไปเรื่อยๆ

แม้ว่าสิ่งนี้จะช่วยป้องกันการสูญเสียข้อมูลโดยไม่ลบ WAL ที่ยังไม่ได้สำรอง แต่ก็นำมาซึ่งความเสี่ยงร้ายแรงต่อความพร้อมใช้งาน หากไดเรกทอรี pg_wal อยู่บนพาร์ทิชันที่เต็ม 100% PostgreSQL จะออกคำสั่ง PANIC และหยุดทำงาน ฐานข้อมูลจะไม่สามารถเริ่มทำงานได้อีกจนกว่าจะมีการเคลียร์พื้นที่

ความเสี่ยง: ฐานข้อมูลหยุดทำงานโดยสมบูรณ์เนื่องจากพาร์ทิชัน pg_wal เต็ม

การป้องกัน:
1. จัดวาง pg_wal ไว้บนพาร์ทิชันดิสก์แยกต่างหากเสมอ
2. ใช้การตรวจสอบขนาดไดเรกทอรี pg_wal อย่างเข้มงวด
3. ตรวจสอบมุมมอง pg_stat_archiver เพื่อตรวจหาคำสั่งสำรองข้อมูลที่ล้มเหลวทันที

ข้อผิดพลาดที่ 3: การทำ Base Backup ไม่สมบูรณ์

Base backup จะไม่มีประโยชน์หากไม่มีไฟล์ WAL ที่สร้างขึ้น ระหว่าง กระบวนการสำรองข้อมูล หากคุณทำ Snapshot ระดับไฟล์ระบบหรือใช้ pg_basebackup โดยไม่สตรีม WAL (-X stream) คุณต้องตรวจสอบให้แน่ใจว่าไฟล์ WAL ที่สร้างขึ้นระหว่างจุดเริ่มต้นและจุดสิ้นสุดของการสำรองข้อมูลได้รับการสำรองไว้อย่างสำเร็จ

หากตัวสำรองข้อมูลของคุณล่าช้าหรือล้มเหลว และไฟล์ WAL เหล่านั้นสูญหาย Base backup จะไม่สามารถนำมาสู่สถานะที่สอดคล้องกันได้

ความเสี่ยง: ข้อมูลสำรองพื้นฐานเสียหายหรือไม่สามารถกู้คืนได้

การป้องกัน: ใช้ pg_basebackup -X stream เพื่อรวมไฟล์ WAL ที่จำเป็นไว้ในชุดข้อมูลสำรอง หรือใช้โซลูชันการสำรองข้อมูลระดับองค์กรที่จัดการความสัมพันธ์ระหว่าง Base backup และ WAL segments โดยอัตโนมัติ

ข้อผิดพลาดที่ 4: ความสับสนเรื่อง Timeline และสถานการณ์ Split-Brain

เมื่อเซิร์ฟเวอร์สำรอง (Standby) ถูกเลื่อนระดับเป็นเซิร์ฟเวอร์หลัก (Primary) PostgreSQL จะเพิ่ม “Timeline ID” (ส่วนแรกของชื่อไฟล์ WAL เช่น 0000000200000001000000A4) สิ่งนี้ช่วยป้องกันไม่ให้เซิร์ฟเวอร์หลักตัวใหม่เขียนทับประวัติ WAL ของเซิร์ฟเวอร์หลักตัวเก่า

อย่างไรก็ตาม หากเซิร์ฟเวอร์หลักตัวเก่าถูกเริ่มทำงานโดยไม่ได้ป้องกันอย่างเหมาะสม (สถานการณ์ Split-brain) มันอาจพยายามส่งไฟล์ WAL ไปยังตำแหน่งสำรองเดียวกันโดยใช้ Timeline เดิม หาก archive_command ของคุณเขียนทับไฟล์โดยไม่ตรวจสอบ คุณอาจทำให้ที่เก็บข้อมูลสำรองของคุณเสียหายได้

ความเสี่ยง: ไฟล์ WAL ถูกเขียนทับ, ข้อมูลสำรองเสียหาย และฐานข้อมูลไม่สามารถกู้คืนได้

การป้องกัน: archive_command ของคุณต้อง ไม่ เขียนทับไฟล์ที่มีอยู่เดิม สังเกตในการกำหนดค่าพื้นฐานก่อนหน้านี้ เราใช้ test ! -f /mnt/nfs/archive/%f เพื่อให้คำสั่งล้มเหลวอย่างชัดเจนหากไฟล์นั้นมีอยู่แล้ว

การลดความเสี่ยงจากการสูญเสียข้อมูล: แนวทางปฏิบัติที่ดีที่สุดสำหรับ Production

เพื่อเสริมความแข็งแกร่งให้กับกลยุทธ์การสำรองข้อมูล PostgreSQL ของคุณ ให้ปฏิบัติตามแนวทางที่ดีที่สุดดังต่อไปนี้

1. ตรวจสอบกระบวนการ Archiver ผ่านระบบ Native

PostgreSQL มีมุมมองในตัวคือ pg_stat_archiver ซึ่งติดตามความสำเร็จและความล้มเหลวของกระบวนการสำรองข้อมูลของคุณ คุณควรบูรณาการมุมมองนี้เข้ากับระบบ Observability ของคุณ (เช่น Prometheus, Datadog หรือ Zabbix)

SELECT 
    archived_count,
    last_archived_wal,
    last_archived_time,
    failed_count,
    last_failed_wal,
    last_failed_time,
    stats_reset
FROM pg_stat_archiver;

เกณฑ์การแจ้งเตือนที่ควรตั้งค่า:
* แจ้งเตือนหาก failed_count เพิ่มขึ้น
* แจ้งเตือนหากความแตกต่างของเวลาระหว่าง now() และ last_archived_time เกินเกณฑ์ RPO ของคุณ (เช่น 15 นาที) โดยคำนึงว่าฐานข้อมูลที่มีการใช้งานน้อยอาจมีความล่าช้าตามธรรมชาติ เว้นแต่จะมีการตั้งค่า archive_timeout

2. ใช้ประโยชน์จาก archive_timeout

ในฐานข้อมูลที่มีปริมาณการเขียนน้อย ไฟล์ WAL ขนาด 16MB อาจใช้เวลาหลายชั่วโมงกว่าจะเต็ม จนกว่าจะเต็ม ไฟล์นั้นจะไม่ถูกสำรอง หากเซิร์ฟเวอร์ล่มและดิสก์ในเครื่องสูญหาย คุณจะสูญเสียธุรกรรมที่เกิดขึ้นในช่วงหลายชั่วโมงนั้น

การตั้งค่า archive_timeout = 600 (10 นาที) จะบังคับให้ PostgreSQL สลับไปใช้ไฟล์ WAL ใหม่และสำรองไฟล์ปัจจุบัน แม้ว่าจะยังไม่เต็มก็ตาม สิ่งนี้รับประกันว่า RPO ของคุณจะไม่เกิน 10 นาที โดยแลกกับการใช้พื้นที่จัดเก็บเพิ่มขึ้นเล็กน้อยเนื่องจากไฟล์ WAL ที่เต็มไม่สมบูรณ์

3. เปลี่ยนไปใช้ archive_library (PostgreSQL 15+)

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

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

4. ทดสอบ Point-in-Time Recovery อย่างสม่ำเสมอ

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

ลองสร้างอินสแตนซ์ชั่วคราว กู้คืน Base backup กำหนดค่า restore_command ให้ดึงข้อมูลจากที่เก็บสำรองของคุณ และกู้คืนไปยังช่วงเวลาที่กำหนด ตรวจสอบว่าฐานข้อมูลเข้าสู่สถานะที่สอดคล้องกันและเปิดให้เชื่อมต่อได้

การสำรองข้อมูลและกู้คืนระดับองค์กรด้วย CloudSave

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

นี่คือจุดที่ CloudSave มอบมูลค่าที่สำคัญสำหรับสภาพแวดล้อม PostgreSQL ระดับองค์กร CloudSave บูรณาการโดยตรงกับ API การสำรองข้อมูลและ WAL Archiving ของ PostgreSQL เพื่อขจัดข้อผิดพลาดที่กล่าวถึงข้างต้น

แทนที่จะเขียนสคริปต์ bash ที่เปราะบาง CloudSave มอบการบูรณาการที่แข็งแกร่งทั้งแบบมี Agent หรือไม่มี Agent ซึ่ง:
* รับประกันการส่งข้อมูล: แทนที่คำสั่งเชลล์มาตรฐานด้วยการถ่ายโอนที่ผ่านการตรวจสอบและยืนยัน checksum ไปยังที่จัดเก็บข้อมูลภายนอกหรือคลาวด์ที่ปลอดภัย
* ป้องกัน WAL Bloat: ตรวจสอบไดเรกทอรี pg_wal อย่างแข็งขันและแจ้งเตือนผู้ดูแลระบบก่อนที่พาร์ทิชันจะเต็ม
* ทำ PITR อัตโนมัติ: ทำให้การกู้คืนข้อมูล ณ จุดเวลาใดเวลาหนึ่งง่ายขึ้นผ่านอินเทอร์เฟซที่ใช้งานง่าย คุณเลือกนาทีที่ต้องการกู้คืน และ CloudSave จะดึง Base backup ที่ถูกต้องและสตรีมลำดับไฟล์ WAL ที่จำเป็นทั้งหมดเพื่อไปสู่สถานะนั้นโดยอัตโนมัติ
* จัดการ Timelines: จัดการประวัติ Timeline ของ PostgreSQL อย่างชาญฉลาด เพื่อให้แน่ใจว่าการทำ Failover และสถานการณ์ Split-brain จะไม่ทำให้ที่เก็บข้อมูลสำรองของคุณเสียหาย

ด้วยการโอนภาระงานหนักของการจัดการ WAL ไปยัง CloudSave ผู้ดูแลระบบฐานข้อมูลสามารถมุ่งเน้นไปที่การเพิ่มประสิทธิภาพคิวรีและประสิทธิภาพของฐานข้อมูล โดยมั่นใจได้ว่า SLA ของ RPO และ RTO ของพวกเขาได้รับการปกป้องโดยแพลตฟอร์มระดับองค์กร

บทสรุป

การทำ WAL Archiving ของ PostgreSQL คือกระดูกสันหลังของการกู้คืนฐานข้อมูลจากภัยพิบัติ แม้ว่าแนวคิดในการคัดลอกไฟล์จากไดเรกทอรีหนึ่งไปยังอีกที่หนึ่งจะดูเรียบง่าย แต่กรณีขอบเขต (Edge cases) เช่น ความล้มเหลวที่ตรวจไม่พบ, ดิสก์เต็ม และความคลาดเคลื่อนของ Timeline ล้วนก่อให้เกิดความเสี่ยงร้ายแรงต่อความสมบูรณ์ของข้อมูล

ด้วยการทำความเข้าใจสถาปัตยกรรมของ pg_wal, การหลีกเลี่ยงการกำหนดค่า archive_command ที่ทำลายข้อมูลอย่างเคร่งครัด, การตรวจสอบ pg_stat_archiver และการใช้ประโยชน์จากแพลตฟอร์มการสำรองข้อมูลระดับองค์กรอย่าง CloudSave คุณสามารถสร้างโครงสร้างพื้นฐาน PostgreSQL ที่ยืดหยุ่นและสามารถอยู่รอดจากความล้มเหลวของฮาร์ดแวร์ ความผิดพลาดของมนุษย์ และเหตุการณ์ล่มสลายครั้งใหญ่ได้โดยไม่สูญเสียธุรกรรมที่ยืนยันแล้วแม้แต่รายการเดียว

ค้นพบข้อผิดพลาดทั่วไปของการทำ PostgreSQL WAL Archiving ที่นำไปสู่การสูญเสียข้อมูล เรียนรู้แนวทางปฏิบัติที่ดีที่สุดจากผู้เชี่ยวชาญ DBA เคล็ดลับการกำหนดค่า และวิธีรับรองการกู้คืนข้อมูล ณ จุดเวลาใดเวลาหนึ่ง (PITR) ที่เชื่อถือได้สำหรับฐานข้อมูลระดับองค์กร

หมวดหมู่