- PostgreSQL 18 สามารถโคลนฐานข้อมูลได้แทบจะทันที โดยผสาน กลยุทธ์การคัดลอกไฟล์ (FILE_COPY) กับ ความสามารถในการโคลนของระบบไฟล์
- เมื่อใช้ค่าตั้งใหม่
file_copy_method = clone จะสามารถใช้ ความสามารถโคลนของระบบไฟล์สมัยใหม่ (FICLONE) เช่น XFS, ZFS, APFS ได้
- จากผลเบนช์มาร์ก การโคลนฐานข้อมูลขนาด 6GB วิธีเดิมแบบ WAL_LOG ใช้เวลาราว 67 วินาที ขณะที่แบบโคลนลดเหลือเพียง ประมาณ 0.2 วินาที
- ฐานข้อมูลที่ถูกโคลนจะ ใช้บล็อกกายภาพเดียวกันร่วมกันในช่วงแรก แต่เมื่อมีการเขียนข้อมูลจะถูกแยกออกด้วย copy-on-write
- อย่างไรก็ตาม จะโคลนได้เฉพาะตอนที่ไม่มีการเชื่อมต่อใช้งานอยู่ และมีข้อจำกัดว่า ทำงานได้ภายในระบบไฟล์เดียวกันเท่านั้น
โครงสร้างการโคลนแบบอิงเทมเพลตของ PostgreSQL
- ใน PostgreSQL เมื่อรันคำสั่ง
CREATE DATABASE dbname ภายในระบบจะ โคลนฐานข้อมูล template1 เพื่อสร้างฐานข้อมูลใหม่
- พฤติกรรมนี้เหมือนกับ
CREATE DATABASE dbname TEMPLATE template1
- สามารถระบุฐานข้อมูลอื่นแทน
template1 ได้ จึงรองรับการโคลนโดยใช้ เทมเพลตที่ผู้ใช้กำหนดเอง
- ใน PostgreSQL 18 ระบบเทมเพลตนี้ถูกขยายให้เป็น โครงสร้างที่รองรับการโคลนแบบเกือบทันที
CREATE DATABASE ... STRATEGY
- ตั้งแต่ PostgreSQL 15 มีการเพิ่มพารามิเตอร์
CREATE DATABASE ... STRATEGY เพื่อให้ เลือกวิธีการโคลน ได้
- ค่าเริ่มต้นคือ
WAL_LOG ซึ่งทำ การโคลนระดับบล็อกผ่าน Write-Ahead Log
- วิธีนี้ช่วย ลดภาระ I/O และปรับปรุงการรองรับการทำงานพร้อมกัน แต่จะช้าเมื่อโคลนข้อมูลขนาดใหญ่
- หากระบุ
STRATEGY=FILE_COPY จะย้อนกลับไปใช้ วิธีคัดลอกไฟล์แบบเดิม และใน PostgreSQL 18 ก็ได้เพิ่ม ตัวเลือกการโคลนใหม่ บนพื้นฐานนี้
FILE_COPY และ file_copy_method
- การตั้งค่า
file_copy_method ใน PostgreSQL 18 ใช้ควบคุม วิธีโคลนไฟล์ในระดับระบบปฏิบัติการ
- ค่าเริ่มต้นคือ
copy ซึ่งจะอ่านทุกไบต์แล้วเขียนไปยังตำแหน่งใหม่
- หากเปลี่ยนเป็น
clone จะใช้ ความสามารถโคลนของระบบไฟล์ (FICLONE) ทำให้ โคลนได้แทบจะทันทีและไม่ใช้พื้นที่เพิ่ม
- ระบบไฟล์ที่รองรับ: XFS, ZFS, APFS, FreeBSD ZFS
- ขั้นตอนการตั้งค่า
- ติดตั้ง PostgreSQL cluster บนระบบไฟล์ที่รองรับ
- ตั้งค่า
file_copy_method = clone แล้ว reload
ผลเบนช์มาร์ก
- หลังสร้างฐานข้อมูลทดสอบขนาดประมาณ 6GB (
source_db) ได้มีการเปรียบเทียบสองวิธี
- วิธี
WAL_LOG: 67,000ms (ประมาณ 67 วินาที)
- วิธี
FILE_COPY + clone: 212ms
- ยืนยันได้ว่าที่ขนาดข้อมูลเท่ากัน ความเร็วเพิ่มขึ้นมากกว่า 300 เท่า
- ฐานข้อมูลที่ถูกโคลน (
fast_clone) แทบไม่ใช้พื้นที่ดิสก์เพิ่ม
หลักการทำงานของข้อมูลที่ถูกโคลน
- เมื่อใช้
file_copy_method = clone จะมีการโคลนเฉพาะ metadata ของระบบไฟล์ ทำให้ทั้งสองฐานข้อมูล ใช้บล็อกกายภาพเดียวกันร่วมกัน
- ขนาดฐานข้อมูลที่ PostgreSQL รายงานยังคงเป็นขนาดเชิงตรรกะเท่าเดิม (ประมาณ 6GB)
- เมื่อมีการเขียนข้อมูล copy-on-write (COW) จะทำงานและแยกเพจนั้นออก
- เพจที่มีแถวข้อมูลที่ถูกแก้ไข
- เพจที่มีการเขียนทูเพิลใหม่
- เพจดัชนี รวมถึง FSM และ visibility map เป็นต้น
- แม้แต่การรัน VACUUM ก็ทำให้เกิดการแยกเพจเพิ่มเติมได้
การตรวจสอบบล็อกร่วมกันบน XFS
- สามารถใช้คำสั่ง
filefrag -v เพื่อตรวจสอบว่า สองฐานข้อมูลใช้บล็อกกายภาพร่วมกันหรือไม่
- ในสถานะเริ่มต้น extents ทั้งหมดจะแสดงเป็น
shared
- เมื่ออัปเดตบางแถว บล็อก 40 แรก (ประมาณ 160KB) จะถูกแยกออกและ เปลี่ยนเป็นที่อยู่กายภาพคนละตำแหน่ง
- extents ที่เหลือยังคงอยู่ในสถานะแชร์ร่วมกัน
ข้อควรระวังและข้อจำกัด
- ขณะโคลน ฐานข้อมูลต้นทางต้องไม่มีการเชื่อมต่อใช้งานอยู่
- นี่เป็นข้อจำกัดของ PostgreSQL ไม่ใช่ปัญหาของระบบไฟล์
- ในสภาพแวดล้อมโปรดักชัน มักนิยมใช้ ฐานข้อมูลเทมเพลตแยกต่างหาก
- โคลนได้ภายในระบบไฟล์เดียวกันเท่านั้น
- หากมีหลาย tablespace อยู่บน mount point คนละแห่ง ระบบจะกลับไปใช้การคัดลอกแบบปกติ
- ใน บริการคลาวด์แบบ managed (AWS RDS, Google Cloud SQL เป็นต้น) ไม่สามารถใช้ฟีเจอร์นี้ได้ เพราะเข้าถึงระบบไฟล์ไม่ได้
- แต่บน VM หรือ bare metal ที่ดูแลเองจะควบคุมได้เต็มรูปแบบ
สรุป
- ฟีเจอร์
file_copy_method = clone ใน PostgreSQL 18 ใช้ ความสามารถโคลนระดับระบบปฏิบัติการโดยตรง เพื่อ
ลดเวลาในการโคลนฐานข้อมูลขนาดใหญ่ได้อย่างมาก
- ช่วยให้สร้างเวิร์กโฟลว์ฐานข้อมูลที่ โคลนได้ทันทีและรีเซ็ตได้ง่าย สำหรับงานทดสอบ พัฒนา และการเรียนรู้
- แต่ก็ต้องออกแบบการใช้งานโดยคำนึงถึง ข้อจำกัดเรื่องการเชื่อมต่อที่ยังใช้งานอยู่และการต้องอยู่ในระบบไฟล์เดียวกัน
1 ความคิดเห็น
ความเห็นจาก Hacker News
สำหรับคนที่รอไม่ไหวหรือต้องการการแยกอินสแตนซ์แบบสมบูรณ์ของ PG18 ฉันได้สร้างเครื่องมือสำหรับแตกกิ่งได้ทันทีด้วย ZFS snapshot ชื่อ Velo
มันทำงานได้กับ PostgreSQL ทุกเวอร์ชัน และแต่ละกิ่งจะมีคอนเทนเนอร์กับพอร์ตที่แยกอิสระ
สำหรับฐานข้อมูลขนาด 100GB ใช้เวลาสร้างราว 2~5 วินาที
ความต่างจากแนวทางของ PG18 คือมันไม่ได้แชร์อินสแตนซ์เดียวกัน แต่ให้การแยกระดับเซิร์ฟเวอร์อย่างสมบูรณ์
ลิงก์ GitHub
ตอนบริษัทเก่ากำลังย้ายไป RDS ฉันเคยสร้างระบบคล้าย ๆ กันขึ้นมาเอง
ระหว่างการย้ายโปรดักชันมักมีปัญหาเกิดขึ้นบ่อย เลยทำขั้นตอนต่อไปนี้ให้เป็นอัตโนมัติเพื่อป้องกัน
ด้วยกระบวนการนี้ เราจับ บั๊กเฉพาะโปรดักชัน ได้จำนวนมากที่ไม่เคยเจอในเครื่อง local หรือ CI
หลังจากนั้นก็ทำให้เป็นอัตโนมัติด้วย Ruby script ง่าย ๆ และได้ยินมาว่ายังใช้งานสคริปต์นั้นอยู่จนถึงตอนนี้
นี่เป็นครั้งแรกที่ฉันรู้ว่าสามารถตั้งค่ากลยุทธ์ template cloning ได้
ฉันใช้ Neon เพื่อสร้างสภาพแวดล้อม integration แบบเรียลไทม์ และใน โปรเจกต์ Golang pgtestdb ของฉัน จะสร้าง Postgres DB ที่ผ่าน schema migration ครบถ้วนสำหรับแต่ละเทสต์
ฉันเคยเห็นสตาร์ตอัปแห่งหนึ่งใช้ btrfs เพื่อสร้าง staging DB ได้ทันทีมาก่อน เลยรู้สึกน่าสนใจที่ไอเดียแบบนี้วนกลับมาเรื่อย ๆ
การโคลนและทดสอบอย่างรวดเร็ว แบบนี้เป็นจุดแข็งสำคัญของ Postgres และ Sqlite และก็ดีถ้า Clickhouse หรือ MySQL ทำได้แบบเดียวกัน
ช่วงนี้ PostgreSQL ดูเหมือนจะกลายเป็น DB สารพัดประโยชน์ที่ครอบคลุมงาน SQL แทบทุกแบบ
แถมยัง ฟรี อีกด้วย
เลยสงสัยว่าตอนนี้ยังมีเหตุผลอะไรให้ต้องใช้ SQL DB ตัวอื่นอยู่อีกไหม
Clickhouse เร็วกว่ามากสำหรับงานวิเคราะห์ และ DB อย่าง Cassandra ก็เหมาะกับ workload ที่เน้นการเขียน
พูดอีกอย่างคือ แต่ละ DB ก็ยังมีจุดแข็งของตัวเอง
พอข้อมูลเยอะขึ้นก็จะมีปัญหาอย่าง ประสิทธิภาพตก หรือ ปัญหา migration
ในกรณีของฉัน ประสิทธิภาพของการแบ่งพาร์ทิชันแบบพื้นฐานไม่ดีพอ จนต้องทำ custom partition เอง
การเลือกแบบนี้ส่งผลลบหลายอย่างเมื่อโหลดสูงขึ้น
เป็นประเด็นที่พูดถึงใน บทความบล็อกของ Uber เช่นกัน
ถึงอย่างนั้นในสภาพแวดล้อมคลาวด์ ฉันก็ยังเชื่อถือ Postgres มากที่สุด
เพราะงั้นใน การติดตั้ง OLTP ขนาดใหญ่ MySQL ก็ยังถูกใช้เป็นหลักอยู่ดี (เช่น YouTube, Uber)
ถ้าใช้ โครงสร้างข้อมูลแบบ immutable (HAMT) ก็สามารถสร้าง DB ที่โคลนได้ทันทีโดยไม่ขึ้นกับชนิดของไฟล์ซิสเต็ม
แม้จะบอกว่าเป็นแค่ทฤษฎี แต่ฉันได้ลองทำจริงมาแล้ว
เลยไม่เข้าใจว่าทำไมถึงไม่มี HAMT-based DB แบบนี้มากกว่านี้
ลิงก์เอกสารที่เกี่ยวข้อง
ฉันไม่เคยรู้มาก่อนว่าใน Postgres v15 ค่าเริ่มต้นเปลี่ยนเป็น WAL_LOG แล้ว
สำหรับสภาพแวดล้อม CI test แบบขนาน การย้อนกลับไปใช้กลยุทธ์ FILE_COPY ดูสมเหตุสมผลกว่า
ฉันเคยเปิด issue ที่เกี่ยวข้องไว้ในโปรเจกต์เก่า integresql
ฉันเคยสร้าง เครื่องมือ GUI ง่าย ๆ pgtt สำหรับทดสอบแอปที่ใช้ Postgres บนเครื่อง local
มันช่วยให้การตั้งค่าสภาพแวดล้อมพัฒนาง่ายขึ้นมาก
น่าจะช่วยงานที่ต้องรัน SQL migration ซ้ำ ๆ ได้
ฉันลองอ่านโพสต์อื่น ๆ ในบล็อกนี้ด้วย และโดยรวมยอดเยี่ยมมาก
โดยเฉพาะอย่างยิ่ง ฉันเพิ่งรู้จัก range type ของ Postgres เป็นครั้งแรก
สงสัยว่า MariaDB มีฟีเจอร์แบบนี้ไหม
ตอนนี้ฉันกังวลเพราะการรีเซ็ต DB กลับสู่สถานะเริ่มต้นในแต่ละเทสต์ทำได้ช้า
โปรดักชันใช้ MariaDB อยู่แล้ว เลยเปลี่ยน DB ได้ยาก
ถึงอย่างนั้นฝั่ง Postgres ก็ดูดีกว่า
วิธีนี้ค่อนข้างมีประสิทธิภาพ
AWS ก็รองรับฟีเจอร์คล้ายกัน
เอกสาร Aurora clone
สำหรับ integration test ถือว่าไม่สมจริงนัก