Hiểu rõ ba loại nhật ký cốt lõi của MySQL — undo_log, redo_log và binlog — là chìa khóa để nắm bắt cơ chế giao dịch, phục hồi sau sự cố và sao chép dữ liệu. Mỗi loại nhật ký đảm nhiệm một vai trò chuyên biệt, không thể thay thế lẫn nhau, dựa trên nguyên tắc tách biệt trách nhiệm (Separation of Concerns).
1. undo_log: Hỗ trợ hoàn tác và kiểm soát đồng thời đa phiên bản (MVCC)
undo_log là nhật ký logic, lưu trữ trạng thái dữ liệu trước khi thay đổi. Nó không ghi lại hành động "làm gì", mà ghi lại "trở về trạng thái nào".
Cơ chế hoạt động
- Khi INSERT: Ghi lại bản ghi
DELETEgiả lập — dùng để xóa bản ghi mới nếu giao dịch bị hủy. - Khi UPDATE: Lưu giá trị cũ của các trường bị sửa (ví dụ: từ
'Alice'thành'Bob', thìundo_loggiữ'Alice'). - Khi DELETE: Lưu toàn bộ bản ghi gốc — để chèn lại nếu cần hoàn tác.
Trong InnoDB, các bản ghi undo được tổ chức thành chuỗi liên kết qua con trỏ roll_pointer, tạo nên "chuỗi phiên bản" cho mỗi dòng dữ liệu — nền tảng của MVCC.
Ví dụ minh họa
START TRANSACTION;
INSERT INTO accounts (id, balance) VALUES (101, 5000.00); -- undo: ghi DELETE cho id=101
UPDATE accounts SET balance = 7500.00 WHERE id = 101; -- undo: lưu balance=5000.00
ROLLBACK; -- Hệ thống dùng undo_log để khôi phục về trạng thái ban đầu
2. redo_log: Đảm bảo tính bền vững và phục hồi sau sụp đổ
redo_log là nhật ký vật lý–logic: nó mô tả chính xác thay đổi ở cấp độ trang dữ liệu — không quan tâm đến SQL, chỉ tập trung vào "trang nào, vị trí nào, thay đổi ra sao".
Cấu trúc bản ghi
Mỗi mục redo chứa:
- ID không gian bảng (
Space ID) - Số hiệu trang (
Page Number) - Độ lệch trong trang (
Offset) - Dữ liệu mới (
New Value)
Ví dụ: "Cập nhật giá trị tại offset 128 trên trang 45 của không gian bảng 3 thành '7500.00'".
Cơ chế đảm bảo độ tin cậy
Tham số then chốt innodb_flush_log_at_trx_commit kiểm soát thời điểm ghi đĩa:
| Giá trị | Hành vi | Độ an toàn |
|---|---|---|
1 |
Gọi fsync() ngay khi COMMIT |
✅ Cao nhất — mất dữ liệu gần như bằng 0 |
2 |
Ghi vào bộ đệm hệ điều hành, OS tự flush mỗi giây | ⚠️ Trung bình — có thể mất dữ liệu nếu OS crash |
0 |
Background thread flush mỗi giây | ❌ Thấp — có thể mất toàn bộ giao dịch trong 1 giây |
Ở môi trường sản xuất, giá trị 1 là bắt buộc để đảm bảo tính bền vững.
3. binlog: Nền tảng sao chép và khôi phục dữ liệu linh hoạt
binlog là nhật ký logic cấp câu lệnh hoặc hàng, do MySQL Server quản lý (không thuộc InnoDB). Nó phục vụ hai mục đích chính: sao chép chủ–tùy (replication) và khôi phục đến thời điểm cụ thể (PITR).
Các định dạng và khuyến nghị
| Định dạng | Ưu điểm | Nhược điểm | Khuyến nghị |
|---|---|---|---|
STATEMENT |
Kích thước nhỏ, dễ đọc | Không an toàn với hàm phi tất định (NOW(), RAND()) → sai lệch chủ–tùy |
❌ Không dùng trong sản xuất |
ROW |
Chính xác tuyệt đối, hỗ trợ kiểm tra tính toàn vẹn | Kích thước lớn hơn, khó debug thủ công | ✅ Mặc định và được khuyến khích |
MIXED |
Tự chọn giữa hai định dạng | Hành vi không rõ ràng, khó dự đoán | ⚠️ Chỉ dùng khi có yêu cầu đặc biệt |
Ví dụ nội dung binlog (Row format)
### UPDATE accounts
### WHERE
### @1=101 /* INT meta=0 */
### @2=5000.00 /* DECIMAL(10,2) */
### SET
### @2=7500.00 /* Cập nhật balance */
4. Sự phối hợp ba nhật ký: Giao dịch và hai giai đoạn cam kết (2PC)
Quá trình commit giao dịch không phải là một bước đơn lẻ, mà là chuỗi phối hợp chặt chẽ giữa ba thành phần:
- Giai đoạn PREPARE: InnoDB ghi bản ghi
redovới cờPREPAREvà đảm bảo nó đã được ghi đĩa (fsync). - Giai đoạn BINLOG: MySQL Server ghi bản ghi
binlog(Row) và cũng đảm bảo ghi đĩa (sync_binlog=1). - Giai đoạn COMMIT: InnoDB cập nhật cờ
redotừPREPAREsangCOMMIT.
Nếu hệ thống sập giữa giai đoạn 1 và 2, lúc khởi động lại, MySQL sẽ phát hiện bản ghi redo có PREPARE nhưng không thấy binlog tương ứng → tự động hoàn tác giao dịch đó. Ngược lại, nếu cả hai tồn tại → áp dụng thay đổi.
5. Cơ chế dọn dẹp undo_log: Purge Thread và quản lý không gian
Undo log không tự biến mất sau khi commit. Việc dọn dẹp được thực hiện bởi luồng nền Purge Thread, dựa trên khái niệm Read View của các giao dịch đang hoạt động.
Nguyên tắc dọn dẹp
Một bản ghi undo chỉ được xóa khi không còn bất kỳ Read View nào trong hệ thống cần truy cập phiên bản dữ liệu do nó đại diện.
Cấu hình tối ưu (MySQL 8.0+)
SET GLOBAL innodb_undo_log_truncate = ON;
SET GLOBAL innodb_max_undo_log_size = 1073741824; -- 1GB
SET GLOBAL innodb_purge_threads = 4;
SET GLOBAL innodb_purge_batch_size = 1000;
Việc sử dụng undo tablespace độc lập (mặc định từ MySQL 8.0) cho phép thu hồi không gian đĩa thực tế — điều không thể đạt được với ibdata1 trong các phiên bản cũ.
6. Tổng kết so sánh
| Nhật ký | Loại | Vai trò chính | Đơn vị ghi | Thành phần quản lý | Tham số then chốt |
|---|---|---|---|---|---|
undo_log |
Logic | Hoàn tác giao dịch & MVCC | Giá trị cũ của trường | InnoDB | innodb_undo_log_truncate |
redo_log |
Vật lý–Logic | Phục hồi sau sụp đổ & tính bền vững | Thay đổi trên trang dữ liệu | InnoDB | innodb_flush_log_at_trx_commit |
binlog |
Logic | Sao chép chủ–tùy & khôi phục theo thời gian | Câu lệnh SQL hoặc thay đổi từng hàng | MySQL Server | sync_binlog, binlog_format |
Việc thiết kế tách biệt ba nhật ký này không phải là sự trùng lặp, mà là một giải pháp kiến trúc tối ưu nhằm cân bằng giữa hiệu năng, độ tin cậy và khả năng mở rộng — giúp MySQL duy trì vị thế là hệ quản trị cơ sở dữ liệu quan hệ mạnh mẽ và đáng tin cậy trong môi trường sản xuất quy mô lớn.