保证数据不丢
一、 核心保证:WAL 与双日志持久化
MySQL 依靠 Write-Ahead Logging (WAL) 机制来保证数据的持久性和崩溃安全 (Crash-Safe)。其核心在于确保两个关键日志的持久化:
- Redo Log (InnoDB): 物理日志,记录数据页的修改。保证事务提交后,即使数据尚未刷盘,也能通过 Redo Log 恢复。
- Binlog (Server 层): 逻辑日志(或行格式),用于主从复制和数据恢复。
关键原则: 只要 redo log
和 binlog
在事务提交时能够安全地持久化到磁盘,MySQL 就能在异常重启后恢复数据,保证不丢失。
二、 Binlog 写入机制与风险控制
- 流程:
- 事务执行中 ->
binlog cache
(每个线程独立的内存区域)。 - 事务提交时 ->
binlog cache
-> 文件系统page cache
(write) -> 磁盘 (fsync)。
- 事务执行中 ->
binlog cache
: 由binlog_cache_size
控制大小,超出会写临时磁盘文件。事务 binlog 需一次性写入,不可拆分。sync_binlog
参数 (控制fsync
时机):0
: 每次提交只write
,不fsync
。由操作系统决定何时刷盘。- 风险: 主机掉电或 OS 崩溃时,会丢失部分
binlog
。性能最好。
- 风险: 主机掉电或 OS 崩溃时,会丢失部分
1
: 每次提交事务都执行fsync
。- 风险: 无数据丢失风险(主机层面)。性能最差。"双 1" 配置之一。
N > 1
: 每次提交都write
,但累积 N 个事务后才fsync
。- 风险: 主机掉电或 OS 崩溃时,最多丢失最近 N 个事务的
binlog
。性能与风险的折中,常见设置 100-1000。
- 风险: 主机掉电或 OS 崩溃时,最多丢失最近 N 个事务的
- Binlog 组提交 (Group Commit):
- 目的: 减少
fsync
次数,提高并发性能。 - 机制: 在执行
fsync
前稍作等待(由binlog_group_commit_sync_delay
和binlog_group_commit_sync_no_delay_count
控制),聚合多个事务的binlog
一起刷盘。 - 效果: 通常不如 Redo Log 组提交效果明显,因为
write
和fsync
间隔较短。
- 目的: 减少
三、 Redo Log 写入机制与风险控制
- 流程与状态:
- 事务执行中 ->
redo log buffer
(共享内存区域)。 redo log buffer
-> 文件系统page cache
(write)。page cache
-> 磁盘 (fsync)。- 三种状态: 仅在内存 buffer (未提交事务崩溃丢失,无影响);在 page cache (MySQL 崩溃不丢,主机崩溃丢失);在磁盘 (最安全)。
- 事务执行中 ->
innodb_flush_log_at_trx_commit
参数 (控制fsync
时机):0
: 每次提交只留在redo log buffer
。后台线程大约每秒刷一次盘 (write + fsync)。- 风险: MySQL 进程异常崩溃也会丢失数据。性能最好,极不推荐。
1
: 每次事务提交时都将redo log
直接持久化 (fsync) 到磁盘。- 风险: 无数据丢失风险(主机层面)。性能最差。"双 1" 配置之一。涉及
prepare
和commit
阶段的刷盘逻辑(见下文)。
- 风险: 无数据丢失风险(主机层面)。性能最差。"双 1" 配置之一。涉及
2
: 每次提交只write
到page cache
。后台线程大约每秒刷一次盘 (write + fsync)。- 风险: 主机掉电或 OS 崩溃时会丢失数据。但 MySQL 进程崩溃不会丢失数据。性能较好。
- 其他刷盘触发:
- 后台线程每秒轮询。
redo log buffer
空间使用近半时 (只 write)。- 其他事务提交时 "搭便车" 一起刷盘 (可能是 write 或 fsync,取决于提交事务的设置)。
- Redo Log 组提交 (Group Commit):
- 机制: 利用 LSN (Log Sequence Number) 标记。一个事务 (leader) 负责将某个 LSN 点之前的所有 buffer 中的 redo log 进行
fsync
。其他 LSN 小于等于该点的事务 (followers) 无需自己fsync
,直接返回。 - 优化: MySQL 将 Redo Log 的
fsync
操作延迟到 Binlogwrite
完成之后、Binlogfsync
之前,以增加 Redo Log 组提交的成员数量,提高效率。
- 机制: 利用 LSN (Log Sequence Number) 标记。一个事务 (leader) 负责将某个 LSN 点之前的所有 buffer 中的 redo log 进行
四、 WAL 机制的性能优势
- 顺序写:
redo log
和binlog
主要是顺序写入,比修改数据页的随机写入效率高得多。 - 组提交: 大幅降低了高并发下磁盘
fsync
的次数 (IOPS 消耗)。
五、 总结
- MySQL 的保证:
- 客户端收到成功 -> 事务已持久化。
- 客户端收到失败 (主键冲突、回滚等) -> 事务未生效。
- 客户端收到异常 (网络断开、超时等) -> 应用需重连并查询状态。MySQL 只保证此时内部(数据、日志、主备)状态是一致的。
要点: "双 1" 配置是最安全的,但性能最差。调整 sync_binlog
和innodb_flush_log_at_trx_commit
可以提升性能,但必须清楚其带来的数据丢失风险,并评估业务是否能承受。