Implementation of replication logs
Bốn kiểu log nhân bảnFour ways to build a replication log
“Log nhân bản” không phải một thứ duy nhất; Kleppmann trình bày bốn cách hiện thực, mỗi cách hỏng theo một kiểu riêng1. Statement-based gửi chính câu lệnh ghi — gọn nhưng vỡ khi câu lệnh không tất định (NOW(), RAND()), khi có cột tự tăng, hay khi có side effect. WAL shipping gửi nguyên nhật ký ghi-trước mức byte — chính xác nhưng gắn chặt vào định dạng lưu trữ, nên rất khó nâng cấp phiên bản mà không dừng dịch vụ. Logical (row-based) gửi mô tả thay đổi ở mức hàng, tách khỏi nội bộ động cơ lưu trữ — nhờ đó leader và follower có thể chạy phiên bản khác nhau, và hệ ngoài có thể tiêu thụ được. Trigger-based đẩy việc lên tầng ứng dụng bằng trigger — linh hoạt nhất, nhưng nhiều lỗi và tốn kém nhất.
Có bốn cách để “kể lại” một thay đổi. Một: đọc lại nguyên câu lệnh (“cộng thêm 1 điểm cho bạn nào ngồi bàn đầu”) — nhưng nếu hôm nay bàn đầu ngồi khác thì kết quả ra khác. Hai: chép từng nét chữ y hệt — chính xác nhưng phải cùng loại vở. Ba: nói rõ kết quả (“ô điểm của Lan đổi từ 7 thành 8”) — cách này ai cũng hiểu được. Bốn: nhờ một bạn ngồi ghi hộ theo cách riêng. Nhớ nhé: kể lại kết quả thì an toàn hơn kể lại câu lệnh.
A “replication log” is not one thing; Kleppmann presents four implementations, each broken in its own way1. Statement-based ships the write statements themselves — compact, but it breaks on nondeterminism (NOW(), RAND()), auto-increment columns and side effects. WAL shipping ships the byte-level write-ahead log — exact, but coupled to the storage format, which makes zero-downtime version upgrades very hard. Logical (row-based) ships a row-level description of the change, decoupled from storage internals — so leader and follower can run different versions, and external systems can consume it. Trigger-based pushes the work up into the application via triggers — the most flexible, and the most error-prone and expensive.
Đọc thế nàoCách bạn nhân bản quyết định bạn nâng cấp được tới đâu. Log mức hàng là thứ mở cửa cho change data capture: cùng một dòng đó nuôi chỉ mục tìm kiếm, cache và kho phân tích — chủ đề Kleppmann quay lại ở Chương 11.
Ý chínhKể lại kết quả cụ thể thì ai nghe cũng hiểu, kể lại mệnh lệnh thì dễ ra kết quả khác.
How to read itHow you replicate decides how far you can upgrade. A row-level log is what opens the door to change data capture: the same stream feeds search indexes, caches and analytics — a thread Kleppmann picks up again in Chapter 11.
Trong sản phẩm thật
MySQL hiện đặt binlog_format mặc định là ROW và mô tả ba định dạng — statement-based, row-based, mixed — cùng những hạn chế của từng cái11. PostgreSQL đi theo hướng khác: nhân bản vật lý truyền WAL, còn logical decoding giải mã WAL thành dòng thay đổi mức hàng cho những consumer bên ngoài10. Hai lộ trình khác nhau dẫn tới cùng một kết luận của sách: log mức logic là cái tách được nhân bản khỏi nội bộ động cơ lưu trữ.
Vì sao trigger-based vẫn tồn tại
Vì đôi khi bạn cần nhân bản một phần dữ liệu, nhân bản sang một loại cơ sở dữ liệu khác, hoặc cần logic hóa giải xung đột riêng — những thứ mà log dựng sẵn của động cơ không làm được. Kleppmann nói thẳng cái giá: overhead cao hơn và nhiều lỗi hơn so với nhân bản dựng sẵn, nên đây là lựa chọn khi bạn thật sự cần sự linh hoạt đó, không phải lựa chọn mặc định.