1 điểm bởi GN⁺ 2025-12-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • PostgreSQL 18 có thể nhân bản cơ sở dữ liệu gần như tức thì bằng cách kết hợp chiến lược sao chép tệp (FILE_COPY) với tính năng clone của hệ thống tệp
  • Khi dùng thiết lập mới file_copy_method = clone, có thể tận dụng tính năng clone của các hệ thống tệp hiện đại (FICLONE) như XFS, ZFS, APFS
  • Theo kết quả benchmark, khi nhân bản cơ sở dữ liệu 6GB, phương thức WAL_LOG hiện có mất khoảng 67 giây, còn phương thức clone được rút xuống mức khoảng 0,2 giây
  • Cơ sở dữ liệu được nhân bản ban đầu sẽ chia sẻ cùng các khối vật lý, nhưng khi có thao tác ghi sẽ được tách ra bằng copy-on-write
  • Tuy nhiên, chỉ có thể nhân bản khi không có kết nối đang hoạt động, và có ràng buộc là chỉ hoạt động trong một hệ thống tệp duy nhất

Cấu trúc nhân bản dựa trên template của PostgreSQL

  • Trong PostgreSQL, khi chạy lệnh CREATE DATABASE dbname, hệ thống nội bộ sẽ nhân bản cơ sở dữ liệu template1 để tạo cơ sở dữ liệu mới
    • Điều này tương đương với CREATE DATABASE dbname TEMPLATE template1
  • Có thể chỉ định một cơ sở dữ liệu khác thay cho template1, nên cũng có thể nhân bản bằng template do người dùng tự định nghĩa
  • Trong PostgreSQL 18, hệ thống template này được mở rộng thành cấu trúc có thể nhân bản tức thì

CREATE DATABASE ... STRATEGY

  • Từ PostgreSQL 15, tham số CREATE DATABASE ... STRATEGY đã được giới thiệu, cho phép chọn phương thức nhân bản
    • Giá trị mặc định là WAL_LOG, thực hiện nhân bản theo đơn vị khối thông qua Write-Ahead Log
    • Cách này giảm tải I/O và cải thiện hỗ trợ đồng thời, nhưng chậm khi nhân bản dữ liệu lớn
  • Nếu chỉ định STRATEGY=FILE_COPY, có thể quay lại cách sao chép tệp truyền thống, và trong PostgreSQL 18, dựa trên đó đã có thêm tùy chọn nhân bản mới

FILE_COPY và file_copy_method

  • Thiết lập file_copy_method trong PostgreSQL 18 điều khiển cách sao chép tệp ở cấp hệ điều hành
    • Mặc định là copy, đọc toàn bộ byte và ghi sang vị trí mới
    • Nếu đổi sang clone, hệ thống sẽ dùng tính năng clone của hệ thống tệp (FICLONE) để nhân bản tức thì mà không tốn thêm dung lượng ngay lập tức
  • Hệ thống tệp được hỗ trợ: XFS, ZFS, APFS, FreeBSD ZFS
  • Quy trình cấu hình
    • Triển khai PostgreSQL cluster trên hệ thống tệp tương ứng
    • Thiết lập file_copy_method = clone rồi reload

Kết quả benchmark

  • Sau khi tạo cơ sở dữ liệu thử nghiệm khoảng 6GB (source_db), tiến hành so sánh hai phương thức
    • Phương thức WAL_LOG: 67.000ms (khoảng 67 giây)
    • Phương thức FILE_COPY + clone: 212ms
  • Với cùng kích thước dữ liệu, xác nhận tăng tốc hơn khoảng 300 lần
  • Cơ sở dữ liệu được nhân bản (fast_clone) gần như không sử dụng thêm dung lượng đĩa

Nguyên lý hoạt động của dữ liệu được nhân bản

  • Khi dùng file_copy_method = clone, chỉ metadata của hệ thống tệp được sao chép, nên hai cơ sở dữ liệu chia sẻ cùng các khối vật lý
  • Kích thước cơ sở dữ liệu mà PostgreSQL báo cáo vẫn là kích thước logic giống nhau (khoảng 6GB)
  • Khi phát sinh thao tác ghi, copy-on-write (COW) sẽ hoạt động và tách các trang liên quan
    • Trang chứa các hàng đã sửa đổi
    • Trang nơi tuple mới được ghi
    • Các trang chỉ mục, FSM, visibility map và các trang tương tự
  • Ngay cả khi chạy VACUUM, cũng sẽ phát sinh thêm việc tách trang

Xác minh khối chia sẻ trên XFS

  • Dùng lệnh filefrag -v để kiểm tra xem hai cơ sở dữ liệu có chia sẻ cùng khối vật lý hay không
    • Ở trạng thái ban đầu, tất cả extents đều được hiển thị là shared
    • Khi cập nhật một số hàng, 40 khối đầu tiên (khoảng 160KB) sẽ bị tách và chuyển sang địa chỉ vật lý khác nhau
    • Các extents còn lại vẫn tiếp tục ở trạng thái chia sẻ

Lưu ý và ràng buộc

  • Cơ sở dữ liệu nguồn không được có kết nối đang hoạt động tại thời điểm nhân bản
    • Đây là ràng buộc của PostgreSQL, không phải vấn đề của hệ thống tệp
    • Trong môi trường production, thông thường sẽ dùng một cơ sở dữ liệu template riêng biệt
  • Chỉ có thể nhân bản trong cùng một hệ thống tệp
    • Nếu nhiều tablespace nằm trên các mount point khác nhau, hệ thống sẽ quay về sao chép thông thường
  • Trên dịch vụ cloud managed (AWS RDS, Google Cloud SQL, v.v.), không thể dùng tính năng này vì không có quyền truy cập hệ thống tệp
    • Trong môi trường VM tự quản hoặc bare metal, có thể kiểm soát hoàn toàn

Kết luận

  • Tính năng file_copy_method = clone của PostgreSQL 18 tận dụng trực tiếp khả năng clone ở cấp hệ điều hành để
    rút ngắn mạnh thời gian nhân bản cơ sở dữ liệu dung lượng lớn
  • Có thể triển khai workflow cơ sở dữ liệu có thể nhân bản tức thì và reset dễ dàng trong các môi trường test, phát triển và học tập
  • Tuy nhiên, cần thiết kế vận hành có cân nhắc đến ràng buộc kết nối đang hoạt động và tính đơn nhất của hệ thống tệp

1 bình luận

 
GN⁺ 2025-12-24
Ý kiến Hacker News
  • Với những ai không thể chờ hoặc cần khả năng cô lập instance hoàn toàn của PG18, tôi đã tạo ra Velo, một công cụ phân nhánh tức thì dùng ZFS snapshot
    Nó hoạt động với mọi phiên bản PostgreSQL, và mỗi nhánh có container cùng cổng riêng biệt
    Với DB 100GB, có thể tạo trong khoảng 2~5 giây
    Khác với cách của PG18 ở chỗ nó không chia sẻ một instance duy nhất mà cung cấp khả năng cô lập máy chủ hoàn toàn
    Liên kết GitHub

    • Có bình luận khác phàn nàn về việc dùng Claude Code, nhưng tôi thấy hứng thú sau khi xem video demo trên trang GitHub
    • Dạo này phần lớn phần mềm đều được viết với sự hỗ trợ của AI agent, nên tôi không hiểu vì sao lại có lời phàn nàn. Cách tiếp cận này khá thú vị
    • Tôi cũng đang định prototype thứ gì đó tương tự bằng btrfs
    • Tôi thấy cách xưng hô “bạn” khá thú vị, nên hơi bất ngờ khi có người nói là đạo văn
  • Trước đây khi công ty chuyển sang RDS, chúng tôi đã tự xây một hệ thống tương tự
    Vì trong quá trình migration production thường xuyên xảy ra sự cố, nên để ngăn điều đó, chúng tôi đã tự động hóa các bước sau

    1. Nhân bản DB RDS hoặc tạo instance mới từ bản backup
    2. Trích xuất CNAME hoặc public IP từ ARN
    3. Áp dụng vào cấu hình kết nối DB của ứng dụng
    4. Chạy migration trong môi trường production giả lập
      Nhờ quy trình này, chúng tôi bắt được nhiều bug chỉ xuất hiện riêng ở production mà local hay CI không phát hiện ra
      Sau đó chúng tôi tự động hóa bằng một script Ruby đơn giản, và tôi nghe nói đến giờ họ vẫn còn dùng script đó
    • Tôi cũng cực ghét những bug kiểu “migration chỉ fail ở production vì tính đặc thù của dữ liệu”. Đã có vài lần tôi phải hủy release vì chuyện đó
  • Đây là lần đầu tôi biết chiến lược template cloning có thể cấu hình được
    Tôi đã dùng Neon để tạo môi trường tích hợp thời gian thực, và trong dự án Golang pgtestdb của mình, mỗi test sẽ tạo một DB Postgres riêng với toàn bộ schema migration đã được áp dụng
    Trước đây tôi từng thấy ở một startup họ dùng btrfs để tạo DB staging tức thì, nên thật thú vị khi thấy ý tưởng tương tự cứ lặp lại
    Kiểu nhân bản và kiểm thử nhanh này là một ưu điểm lớn của Postgres và Sqlite, và tôi ước Clickhouse hay MySQL cũng làm được như vậy

  • Dạo này PostgreSQL có vẻ đã trở thành DB vạn năng bao phủ gần như mọi nhu cầu SQL
    Lại còn miễn phí
    Giờ tôi tự hỏi liệu còn lý do gì để dùng một SQL DB khác nữa không

    • Postgres rất tuyệt, nhưng MySQL có replication master-master dễ hơn, còn MongoDB thì đơn giản hơn cho phân tán địa lý và sharding
      Clickhouse nhanh hơn rất nhiều cho analytics, và những DB như Cassandra lại có lợi thế với workload thiên về ghi
      Nói cách khác, mỗi DB vẫn có điểm mạnh riêng
    • Cách nói “làm tốt mọi thứ” là hơi cường điệu
      Khi dữ liệu tăng lớn, sẽ xuất hiện suy giảm hiệu năng hoặc vấn đề migration
      Trường hợp của tôi là performance của partitioning mặc định quá kém nên tôi phải tự triển khai partition tùy chỉnh
    • Postgres vẫn còn cách triển khai MVCC (copy-on-write) kém hiệu quả
      Lựa chọn này gây ra nhiều tác động tiêu cực khi tải tăng cao
    • Trước đây MySQL/InnoDB tốt hơn trong workload thiên về cập nhật
      Bài viết blog của Uber cũng từng đề cập đến chủ đề này
      Dù vậy, trong môi trường cloud thì tôi vẫn tin tưởng Postgres nhất
    • Postgres vẫn chưa có lựa chọn thay thế trưởng thành ở mức Vitess
      Vì thế trong các triển khai OLTP quy mô lớn, MySQL vẫn thường được dùng nhiều hơn (ví dụ: YouTube, Uber)
  • Dùng cấu trúc dữ liệu bất biến (HAMT) thì có thể tạo DB clone tức thì bất kể loại filesystem nào
    Tôi nói là lý thuyết, nhưng thực ra đã từng tự triển khai rồi
    Tôi không hiểu vì sao lại không có nhiều DB dựa trên HAMT hơn

    • Tôi là tác giả của ClickHouse, và ClickHouse cũng hỗ trợ nhân bản bảng bằng cách dùng các phần dữ liệu bất biến
      Liên kết tài liệu liên quan
    • Tôi tự hỏi liệu Datomic có tích hợp sẵn kiểu cloning này không. Tôi đã muốn thử nó từ lâu, nhưng vẫn chưa sẵn sàng về mặt tinh thần để làm ứng dụng thực tế bằng nó
  • Tôi không biết rằng trong Postgres v15, WAL_LOG đã trở thành mặc định
    Trong môi trường CI test song song, quay lại chiến lược FILE_COPY có vẻ hợp lý hơn
    Tôi đã mở issue liên quan trong dự án cũ integresql

  • Tôi từng tạo một công cụ GUI đơn giản pgtt để test ứng dụng dựa trên Postgres ở local
    Nó giúp đơn giản hóa việc thiết lập môi trường dev rất nhiều

    • Chỉ đọc README thì tôi vẫn chưa rõ, không biết cấu trúc của nó có coi template như snapshot hay không
      Có vẻ điều này sẽ hữu ích cho công việc lặp đi lặp lại với SQL migration
    • Sẽ tốt hơn nếu README có ảnh chụp màn hình GUI, và liên kết Docker hiện đang bị hỏng
  • Tôi cũng đọc các bài viết khác trên blog này và nhìn chung thấy rất xuất sắc
    Đặc biệt là lần đầu tôi biết tới range type của Postgres

    • range type thực sự rất hữu ích cho những việc như tính toán phần chồng lấp giữa các khoảng thời gian/ngày tháng
  • Tôi tự hỏi liệu MariaDB có tính năng như vậy không
    Tôi đang đau đầu vì việc đưa DB về trạng thái ban đầu sau mỗi test quá chậm
    Vì production đang dùng MariaDB nên rất khó đổi DB
    Dù vậy, phía Postgres trông vẫn hấp dẫn hơn

    • Có thể chạy từng test trong một transaction session rồi rollback ở cuối để khôi phục nhanh về trạng thái ban đầu
      Cách này khá hiệu quả
    • Nếu việc restart DB không thành vấn đề thì dùng LVM hoặc btrfs snapshot ở cấp filesystem cũng là một cách
  • AWS cũng hỗ trợ tính năng tương tự
    Tài liệu Aurora clone

    • Clone của Aurora hoạt động theo kiểu copy-on-write ở cấp storage, nhưng vẫn phải provision một cluster mới nên mất khoảng 10 phút
      Điều này không thực tế cho integration test
    • Aurora là replication ở cấp cluster, còn thứ đang được bàn ở đây là replication ở cấp cơ sở dữ liệu