Skip to content

保证数据不丢

一、 核心保证:WAL 与双日志持久化

MySQL 依靠 Write-Ahead Logging (WAL) 机制来保证数据的持久性和崩溃安全 (Crash-Safe)。其核心在于确保两个关键日志的持久化:

  1. Redo Log (InnoDB): 物理日志,记录数据页的修改。保证事务提交后,即使数据尚未刷盘,也能通过 Redo Log 恢复。
  2. Binlog (Server 层): 逻辑日志(或行格式),用于主从复制和数据恢复。

关键原则: 只要 redo logbinlog 在事务提交时能够安全地持久化到磁盘,MySQL 就能在异常重启后恢复数据,保证不丢失。

二、 Binlog 写入机制与风险控制

  1. 流程:
    • 事务执行中 -> binlog cache (每个线程独立的内存区域)。
    • 事务提交时 -> binlog cache -> 文件系统 page cache (write) -> 磁盘 (fsync)。
  2. binlog cache:binlog_cache_size 控制大小,超出会写临时磁盘文件。事务 binlog 需一次性写入,不可拆分。
  3. sync_binlog 参数 (控制 fsync 时机):
    • 0: 每次提交只 write,不 fsync。由操作系统决定何时刷盘。
      • 风险: 主机掉电或 OS 崩溃时,会丢失部分 binlog。性能最好。
    • 1: 每次提交事务都执行 fsync
      • 风险: 无数据丢失风险(主机层面)。性能最差。"双 1" 配置之一
    • N > 1: 每次提交都 write,但累积 N 个事务后才 fsync
      • 风险: 主机掉电或 OS 崩溃时,最多丢失最近 N 个事务的 binlog。性能与风险的折中,常见设置 100-1000。
  4. Binlog 组提交 (Group Commit):
    • 目的: 减少 fsync 次数,提高并发性能。
    • 机制: 在执行 fsync 前稍作等待(由 binlog_group_commit_sync_delaybinlog_group_commit_sync_no_delay_count 控制),聚合多个事务的 binlog 一起刷盘。
    • 效果: 通常不如 Redo Log 组提交效果明显,因为 writefsync 间隔较短。

三、 Redo Log 写入机制与风险控制

  1. 流程与状态:
    • 事务执行中 -> redo log buffer (共享内存区域)。
    • redo log buffer -> 文件系统 page cache (write)。
    • page cache -> 磁盘 (fsync)。
    • 三种状态: 仅在内存 buffer (未提交事务崩溃丢失,无影响);在 page cache (MySQL 崩溃不丢,主机崩溃丢失);在磁盘 (最安全)。
  2. innodb_flush_log_at_trx_commit 参数 (控制 fsync 时机):
    • 0: 每次提交只留在 redo log buffer。后台线程大约每秒刷一次盘 (write + fsync)。
      • 风险: MySQL 进程异常崩溃也会丢失数据。性能最好,极不推荐
    • 1: 每次事务提交时都将 redo log 直接持久化 (fsync) 到磁盘
      • 风险: 无数据丢失风险(主机层面)。性能最差。"双 1" 配置之一。涉及 preparecommit 阶段的刷盘逻辑(见下文)。
    • 2: 每次提交只 writepage cache。后台线程大约每秒刷一次盘 (write + fsync)。
      • 风险: 主机掉电或 OS 崩溃时会丢失数据。但 MySQL 进程崩溃不会丢失数据。性能较好。
  3. 其他刷盘触发:
    • 后台线程每秒轮询。
    • redo log buffer 空间使用近半时 (只 write)。
    • 其他事务提交时 "搭便车" 一起刷盘 (可能是 write 或 fsync,取决于提交事务的设置)。
  4. Redo Log 组提交 (Group Commit):
    • 机制: 利用 LSN (Log Sequence Number) 标记。一个事务 (leader) 负责将某个 LSN 点之前的所有 buffer 中的 redo log 进行 fsync。其他 LSN 小于等于该点的事务 (followers) 无需自己 fsync,直接返回。
    • 优化: MySQL 将 Redo Log 的 fsync 操作延迟到 Binlog write 完成之后、Binlog fsync 之前,以增加 Redo Log 组提交的成员数量,提高效率。

四、 WAL 机制的性能优势

  1. 顺序写: redo logbinlog 主要是顺序写入,比修改数据页的随机写入效率高得多。
  2. 组提交: 大幅降低了高并发下磁盘 fsync 的次数 (IOPS 消耗)。

五、 总结

  • MySQL 的保证:
    • 客户端收到成功 -> 事务已持久化
    • 客户端收到失败 (主键冲突、回滚等) -> 事务未生效
    • 客户端收到异常 (网络断开、超时等) -> 应用需重连并查询状态。MySQL 只保证此时内部(数据、日志、主备)状态是一致的。

要点: "双 1" 配置是最安全的,但性能最差。调整 sync_binloginnodb_flush_log_at_trx_commit 可以提升性能,但必须清楚其带来的数据丢失风险,并评估业务是否能承受。