-- Binlog 中记录的内容 UPDATE users SET balance = balance +100WHERE id =1;
2. ROW 格式
记录每行数据的变化,文件大,但能保证主从一致性。
1 2 3
-- Binlog 中记录的内容(伪代码) UPDATE users SET balance =200WHERE id =1; -- 实际记录:id=1 的行,balance 从 100 变为 200
3. MIXED 格式
混合模式,对于可能引起不一致的语句使用 ROW 格式,其他使用 STATEMENT 格式。
实现原理
Binlog 由 MySQL 服务器层实现,不依赖存储引擎。写入流程:
flowchart TD
A["事务执行"] --> B["写入 Binlog 缓存 内存"]
B --> C["事务提交"]
C --> D{"sync_binlog 配置"}
D -->|sync_binlog=1| E["立即刷盘"]
D -->|sync_binlog=0| F["由 OS 决定"]
D -->|sync_binlog=N| G["每 N 个事务刷盘"]
E --> H["写入 Binlog 文件"]
F --> H
G --> H
H --> I{"文件大小 > max_binlog_size?"}
I -->|是| J["切换新文件"]
I -->|否| K["继续写入"]
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style H fill:#f3e5f5
style J fill:#fce4ec
graph LR
A["ib_logfile0 (256MB)"] --> B["ib_logfile1 (256MB)"]
B --> A
A --> C["写入位置"]
B --> D["循环使用"]
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style D fill:#f3e5f5
写入流程
flowchart TD
A["事务执行 修改数据页"] --> B["写入 Redo Log Buffer 内存"]
B --> C["事务提交"]
C --> D{"innodb_flush_log_at_trx_commit"}
D -->|值为 0| E["每秒刷盘一次"]
D -->|值为 1| F["每次提交都刷盘"]
D -->|值为 2| G["写入 OS 缓存"]
E --> H["Redo Log 文件 磁盘"]
F --> H
G --> H
I["后台线程"] --> H
I -.->|定期刷盘| B
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style H fill:#f3e5f5
style I fill:#fce4ec
WAL 机制
Redo Log 实现了 Write-Ahead Logging(WAL) 机制:
sequenceDiagram
participant T as 事务
participant R as Redo Log
participant D as 数据页
participant C as 崩溃恢复
Note over T: 修改数据
T->>R: 1. 先写 Redo Log (已刷盘)
T->>D: 2. 后写数据页 (可能未刷盘)
Note over T,C: 如果此时崩溃
C->>R: 读取 Redo Log
R->>D: 恢复数据页
Note over C: 数据恢复完成
Redo Log 与 Binlog 的区别
特性
Redo Log
Binlog
所属层级
InnoDB 存储引擎
MySQL 服务器层
记录内容
物理日志(数据页的修改)
逻辑日志(SQL 语句或行数据变化)
用途
崩溃恢复、保证持久性
主从复制、数据恢复、审计
文件格式
固定大小,循环写入
追加写入,可配置大小
事务性
支持事务
不支持事务
两阶段提交(2PC)
为了保证 Redo Log 和 Binlog 的一致性,InnoDB 使用两阶段提交:
sequenceDiagram
participant T as 事务
participant R as Redo Log
participant B as Binlog
Note over T: 阶段1: Prepare
T->>R: 写入 Redo Log 标记为 Prepare 状态
T->>B: 写入 Binlog
Note over T: 阶段2: Commit
T->>R: 提交事务 标记为 Commit 状态
Note over T,B: 如果阶段2崩溃
alt Binlog 完整
T->>R: 提交事务
else Binlog 不完整
T->>R: 回滚事务
end
graph TD
A["Undo Segment"] --> B["Insert Undo Log INSERT 操作"]
A --> C["Update Undo Log UPDATE/DELETE 操作"]
B --> D["记录插入的主键 用于回滚"]
C --> E["记录修改前的数据 用于回滚和 MVCC"]
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#fce4ec
写入流程
flowchart TD
A["SQL 操作"] --> B{"操作类型"}
B -->|INSERT| C["记录插入行的主键值 Insert Undo Log"]
B -->|UPDATE| D["记录修改前的完整行数据 Update Undo Log"]
B -->|DELETE| E["标记为删除 记录完整行数据 Update Undo Log"]
C --> F["写入 Undo Log"]
D --> F
E --> F
F --> G["Undo 表空间"]
style A fill:#e1f5ff
style C fill:#e8f5e9
style D fill:#fff3e0
style E fill:#f3e5f5
style G fill:#fce4ec
MVCC 实现
Undo Log 通过版本链实现 MVCC:
graph TD
A["当前版本 最新数据"] -->|roll_ptr 指针| B["历史版本 1 Undo Log"]
B -->|roll_ptr 指针| C["历史版本 2 Undo Log"]
C -->|roll_ptr 指针| D["历史版本 3 Undo Log"]
D -->|...| E["更早版本"]
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#fce4ec
读操作通过 Undo Log 构建历史版本,实现快照读。
Undo Log 清理
Undo Log 在以下情况会被清理:
事务提交后:Insert Undo Log 可以立即清理
没有活跃事务使用:Update Undo Log 需要等待没有事务使用该版本
Purge 线程:后台线程定期清理不再需要的 Undo Log
六、通用查询日志(General Query Log)
功能说明
通用查询日志记录了所有到达 MySQL 服务器的 SQL 语句,包括 SELECT、INSERT、UPDATE、DELETE 等所有操作。由于记录所有操作,会产生大量日志,通常只在调试时开启。
配置方法
1 2 3 4 5 6 7 8 9 10 11
-- 查看通用查询日志是否开启 SHOW VARIABLES LIKE'general_log';
-- 开启通用查询日志 SETGLOBAL general_log ='ON';
-- 查看通用查询日志文件位置 SHOW VARIABLES LIKE'general_log_file';
sequenceDiagram
participant M as 主库 (Master)
participant B as Binlog
participant IO as IO 线程
participant R as Relay Log
participant SQL as SQL 线程
participant S as 从库 (Slave)
M->>B: 写入 Binlog
B->>IO: IO 线程读取 Binlog
IO->>R: 写入 Relay Log
R->>SQL: SQL 线程读取 Relay Log
SQL->>S: 应用数据变更
Note over M,S: 主从复制完成
Relay Log 结构
Relay Log 的结构和 Binlog 类似,采用追加写入的方式:
graph LR
A["relay-bin.000001"] --> B["relay-bin.000002"]
B --> C["relay-bin.000003"]
C --> D["relay-bin.000004"]
D --> E["..."]
style A fill:#e1f5ff
style B fill:#e8f5e9
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#fce4ec