MySQL事务持久性靠redo log刷盘机制和innodb_flush_log_at_trx_commit参数协同实现:=1时每次COMMIT强制fsync,=0时每秒刷一次,=2时仅写入OS缓存;核心是redo log落盘而非数据页刷盘。
WAL 本身不提升“安全性”,它提升的是**已提交事务的持久性保障能力**——换句话说,只要事务成功提交,就几乎不会因崩溃而丢失。这是通过 redo log 的强制落盘顺序实现的,不是靠加密或权限控制。关键不在“先写”,而在“写完才允许事务提交”。InnoDB 要求:只有当对应事务的 redo log 记录成功刷到磁盘(由 innodb_flush_log_at_trx_commit 控制),才会向客户端返回 COMMIT SUCCESS。这意味着:
redo log,把没来得及写入数据页的变更补上;buffer pool 中的脏页)是否已刷盘,不影响已提交事务的结果。这个参数直接决定“日志先行”到底有多严格:
1:每次 COMMIT 都调用 fsync() 强刷 redo log file 到磁盘 → 最强持久性,但性能开销最大;0:每秒一次 fsync(),事务提交只写入 redo log buffer → 崩溃可能丢失最多 1 秒数据;2:每次 COMMIT 写入 OS cache(write()),但不 fsync() → 依赖操作系统缓存可靠性,断电可能丢日志。0 和 2 在机械盘或未启用电池保护的 RAID 卡上,实际持久性远低于预期。很多人误以为 WAL 是“万能保险”,但它有明确边界:
binlog 是否写入——主从同步或 PITR 依赖 binlog,和 redo log 是两套机制;undo log 的职责;DROP TABLE 或误删数据——WAL 只重放合法事务日志,不区分“好操作”和“坏操作”;redo log 文件本身损坏(如磁盘坏道),重放失败,照样丢数据。innodb_flush_log_at_trx_commit=1,若宿主机未开启 cache flush 或云厂商未透传 fsync 语义,日志仍可能滞留在设备缓存中——这种“假落盘”现象,在故障时会彻底失效。