当用户发出commit
的时候, mysql服务器宕机了, 下次启动的时候是回滚还是恢复呢.
gdb的使用可以看上一章 https://cloud.tencent.com/developer/article/2226040
写redo(查看lsn变化的)
注: log_sys->lsn表示内存中的lsn log_sys->flushed_to_disk_lsn表示已经刷到redo上的lsn (可使用show engine innodb status
查看)
break MYSQL_BIN_LOG::process_flush_stage_queue
binlog刷盘前后
break MYSQL_BIN_LOG::flush_cache_to_file
整体流程就是 使用gdb接管mysqld,设置断点, 然后新开一个窗口执行一个事务, 在断点1,2前后(finish)的时候,kill -9 `pidof mysqld`
,然后启动mysqld,查看数据是否写入成功.
注:如下测试省去打断点的重复过程.
使用gdb打断点
加个-9 ,不然就是正常关闭了.
发现无数据,说明被回滚了
使用gdb打断点
发现刷完redo后, 内存中的lsn和磁盘上的lsn一致了
注:finish表示完成当前的栈帧(bt查看)
发现依然无数据, 说明被回滚了
此时用到了第二个断点,(可以不设置第一个断点, 也可以在第一个断点之后 continue 就会到第二个断点)
启动mysqld,并使用gdb打断点
发现没得数据, 说明还是被回滚了
启动mysqld 并打断点
第一个断点处continue 第二个断点处finish
其实还可以查看下binlog的时间戳的, 辅助验证. 感兴趣的自己去试吧.
发现有数据, 说明启动的时候恢复了数据
说明binlog写完之后宕机, 下次启动就能正常恢复. binlog未写宕机,下次启动就会回滚.
主要是因为binlog要用来做主从,一但写了binlog,那么从库就可能已经有数据了, 此时回滚的话,主从数据就不一致了, 所有得提交.
其实还可以模拟下binlog写一半的时候宕机会咋样, 有兴趣的自己去试试吧.
下面的刷redo时间均指的在刷binlog前
宕机点 | 相关代码 | 下次重启回滚还是提交 |
---|---|---|
刷redo前 | MYSQL_BIN_LOG::process_flush_stage_queue | 回滚 |
刷redo后 | MYSQL_BIN_LOG::process_flush_stage_queue | 回滚 |
刷binlog前 | MYSQL_BIN_LOG::flush_cache_to_file | 回滚 |
刷binlog后 | MYSQL_BIN_LOG::flush_cache_to_file | 提交 |
其实还可以使用gdb看下mysqld启动的时候是怎样恢复的. 有空了再说吧