在一个专门搭建的一次性MySQL实例上,真实kill -9制造一次崩溃,验证已提交和未提交的数据在重启恢复后各自真实的命运。
本机跑着的生产MySQL实例上还有别的真实业务库,不能拿它做崩溃测试,所以本文另起了一个独立的disposable实例。
代码mysqld --initialize-insecure --datadir=./data mysqld --datadir=./data --port=19306 --socket=./mysql.sock & CREATE TABLE ledger (id INT PRIMARY KEY AUTO_INCREMENT, note VARCHAR(50)); INSERT INTO ledger (note) VALUES ('committed-1'),('committed-2'),('committed-3'); -- 三条数据真实提交
代码-- 另一个会话,开一个事务但故意不提交 START TRANSACTION; INSERT INTO ledger (note) VALUES ('UNCOMMITTED-should-vanish'); SELECT SLEEP(15); -- 事务真实还开着 -- 这时候真实kill -9掉整个mysqld进程
kill -9 <mysqld真实的pid> 之后 ps 真实查不到这个进程了——没有任何"Shutdown complete"的日志, 这是一次真实的、没有优雅关闭的崩溃,不是正常停止服务
2026-09-28T09:26:05 [System] Starting XA crash recovery... 2026-09-28T09:26:05 [System] XA crash recovery finished.
SELECT * FROM ledger; 1 committed-1 2 committed-2 3 committed-3 (第4条 'UNCOMMITTED-should-vanish' 真实不见了)
这次真实测试完整验证了InnoDB崩溃安全的核心承诺:已提交的数据不会丢,未提交的数据不会露——前者靠redo log在COMMIT时就已经真实落盘、重启后重放;后者靠InnoDB在重放之后真实扫一遍还处于活跃状态、但从未提交的事务,把它们的改动用undo log回滚掉。测试完成后,本文真实清理了这个一次性实例的全部文件,全程没有碰共享的生产MySQL实例一下。
每一步都是本文上面在一次性独立实例上跑出来的原始结果。
kill -9模拟断电式崩溃,对照重启后的错误日志和查询结果