GDB 验证MYSQL异常宕机恢复(gdb调试mysql)
 南窗  分类:IT技术  人气:143  回帖:0  发布于1年前 收藏

当用户发出commit的时候, mysql服务器宕机了, 下次启动的时候是回滚还是恢复呢.

环境准备

gdb的使用可以看上一章 https://cloud.tencent.com/developer/article/2226040

断点1:

写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

断点2:

binlog刷盘前后

break MYSQL_BIN_LOG::flush_cache_to_file

验证过程

整体流程就是 使用gdb接管mysqld,设置断点, 然后新开一个窗口执行一个事务, 在断点1,2前后(finish)的时候,kill -9 `pidof mysqld`,然后启动mysqld,查看数据是否写入成功.

注:如下测试省去打断点的重复过程.

刷redo前

使用gdb打断点

测试SQL

此时未刷redo,lsn未变化

上为内存中的LSN 下为redo日志中的lsn,不一致,表示未刷redo

kill -9 mysqld进程,然后启动

加个-9 ,不然就是正常关闭了.

kill完之后,退出gdb

启动mysqld验证数据

发现无数据,说明被回滚了

刷redo后

使用gdb打断点

测试sql

查看刷redo前后的lsn

发现刷完redo后, 内存中的lsn和磁盘上的lsn一致了

注:finish表示完成当前的栈帧(bt查看)

强制kill mysqld之后,启动验证

发现依然无数据, 说明被回滚了

刷binlog前

此时用到了第二个断点,(可以不设置第一个断点, 也可以在第一个断点之后 continue 就会到第二个断点)

启动mysqld,并使用gdb打断点

测试sql

继续第一个断点, 到第二个断点的时候强制停掉mysqld

启动mysqld验证数据

发现没得数据, 说明还是被回滚了

刷binlog后

启动mysqld 并打断点

第一个断点处continue 第二个断点处finish

测试sql

finish第二个断点(刷完binlog)

其实还可以查看下binlog的时间戳的, 辅助验证. 感兴趣的自己去试吧.

强制kill掉mysqld

启动mysqld 验证数据

发现有数据, 说明启动的时候恢复了数据

结论

说明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启动的时候是怎样恢复的. 有空了再说吧

讨论这个帖子(0)垃圾回帖将一律封号处理……