MySQL数据库基本概念入门:事务持久性保障与崩溃恢复机制

来源:这里教程网 时间:2026-02-28 20:51:23 作者:

事务提交后数据真的不会丢吗?

会丢,但可以控制到“最多丢 1 个事务”——前提是

innodb_flush_log_at_trx_commit = 1
且磁盘本身不掉电、不静默损坏。MySQL 的持久性不是靠“写完数据页”来保证的,而是靠
redo log
落盘:只要事务提交时这条日志已同步写入磁盘,哪怕 MySQL 瞬间断电、进程崩溃,重启后也能把这行修改“重放”回来。

为什么改完数据不立刻刷盘,还能保证不丢?

因为 InnoDB 用的是预写式日志(WAL)机制:

事务修改 Buffer Pool 中的数据页 → 同时生成一条物理修改记录(比如“page 123 offset 48 处写入 4 字节 0x00000001”)→ 写入
redo log buffer
执行
COMMIT
时,强制将该记录刷到磁盘上的
ib_logfile0
等文件中 → 此时事务才算真正提交成功
数据页刷盘(
flush list
)由后台线程异步完成,慢一点没关系,
redo log
已经兜底

这个设计换来两个关键好处:顺序写日志比随机写数据页快得多;崩溃恢复时只需重放日志,不用扫描全库。

崩溃后 MySQL 是怎么“自己爬起来”的?

启动时自动触发崩溃恢复(crash recovery),全过程不依赖

binlog
,纯靠
redo log

读取
ib_logfile0
ib_logfile1
,定位到最近一次
checkpoint
(由
innodb_checkpoint_lsn
记录)
从 checkpoint 开始,逐条重放所有已
commit
但尚未刷入数据文件的 redo 日志
如果遇到只有
prepare
没有
commit
的日志,则查
binlog
:有完整对应事务就提交,没有就回滚(这是两阶段提交 2PC 的作用)

你不需要手动执行任何命令,只要 MySQL 能正常启动,这个过程就已在后台完成。

最容易被忽略的配置陷阱

很多线上库看似开了持久性,实则形同虚设,问题常出在这些地方:

innodb_flush_log_at_trx_commit = 2
:日志只写进操作系统缓存,主机断电就丢 —— 这是默认值为 1 的最大“温柔陷阱”
sync_binlog = 0
100
:主从一致性或基于 binlog 的恢复可能失效,尤其在启用 GTID 时
RAID 卡/SSD 关闭了写缓存持久化(如未配 BBU 或 capacitor):
fsync
命令实际没落盘,等于白设
误删或自动清理了
ib_logfile*
:崩溃恢复直接失败,只能靠备份回退

验证是否生效最简单的方法:查变量

SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
,必须是
1
;再看错误日志里有没有 “InnoDB: Doing recovery” 字样 —— 那就是它真正在干活。

相关推荐