MySQL案例-初步恢复: alter引起的从库无限Crash

-------------------------------------------------------------------------------------------------正文---------------------------------------------------------------------------------------------------------------

场景 : 
Crash发生时的数据库版本: MySQL-5.7.17, 从库在同步到某一个alter语句的时候发生了Crash, 并且在重启进行Crash Recovery的时候不断触发同一个错误导致Crash;

结论 :
只读业务临时切换到另外一个只读实例, 且重新做一个从库给业务用;

重点! : 
解决问题的办法肯定不是把库恢复起来, 而是重新做一个, 所以本文记录的操作主要目的是做实践和尝试, 生产环境上请谨慎操作;

场景:
生产环境的场景, 屏蔽一些敏感信息;

首先截取Error log中比较的重要信息:

点击(此处)折叠或打开

  1. 2017-05-25 14:10:23 0x7f9b5b927700 InnoDB: Assertion failure in thread 140305232983808 in file fsp0fsp.cc line 2108
  2. InnoDB: Failing assertion: frag_n_used > 0
  3. ......
  4. /usr/sbin/mysqld(_Z14fseg_free_stepPhbP5mtr_t+0x36e)[0x11d073e]
  5. ......
  6. /usr/sbin/mysqld(_Z23trx_undo_insert_cleanupP14trx_undo_ptr_tb+0x16c)[0x1100b9c]
  7. ......
  8. /usr/sbin/mysqld(_Z19innobase_commit_lowP5trx_t+0x17)[0xf6a0e7]
  9. /usr/sbin/mysqld(_ZN15Query_log_event14do_apply_eventEPK14Relay_log_infoPKcm+0x68d)[0xdf4c1d]
  10. /usr/sbin/mysqld(_Z27slave_worker_exec_job_groupP12Slave_workerP14Relay_log_info+0x293)[0xe52353]
  11. ......
  12. /usr/sbin/mysqld(handle_slave_worker+0x363)[0xe34f73]
  13. ......
  14. Trying to get some variables.
  15. Some pointers may be invalid and cause the dump to abort.
  16. Query (xxxxxxxxx): alter table tb1 add primary key(`col1`,`col2`,`col3`)
  17. Connection ID (thread ID): 129443
  18. Status: NOT_KILLED
  19. ......
  20. 2017-05-25T14:10:24.858719+08:00 0 [Note] InnoDB: Ignoring data file './dbname/tb0.ibd' with space ID 375, since the redo log references ./dbname/tb0.ibd with space ID 280.
  21. 2017-05-25T14:10:24.860628+08:00 0 [Note] InnoDB: Ignoring data file './dbname/tb1.ibd' with space ID 374, since the redo log references ./dbname/tb1.ibd with space ID 279.
  22. ......
  23. 2017-05-25T14:10:44.635655+08:00 0 [Note] InnoDB: Ignoring data file './dbname/#sql-7b4e1_9f3a1.ibd' with space ID 375. Another data file called ./dbname/tb0.ibd exists with the same space ID.
  24. ......
  25. 2017-05-25T14:10:39.845947+08:00 0 [Note] InnoDB: Ignoring data file './dbname/#sql-7b4e1_9f3a1.ibd' with space ID 374. Another data file called ./report_gamein/t30741_hs_g47_day.ibd exists with the same space ID.
  26. ......
  27. 2017-05-25T14:11:02.972181+08:00 0 [Note] Starting crash recovery...
  28. 2017-05-25T14:11:02.972227+08:00 0 [Note] Crash recovery finished.
  29. 2017-05-25T14:11:40.547210+08:00 0 [Note] InnoDB: Rollback of trx with id 3377056858 completed
  30. 2017-05-25T14:11:40.554385+08:00 0 [Note] InnoDB: Rollback of non-prepared transactions completed
  31. ......
  32. 2017-05-25T14:11:03.752024+08:00 0 [Warning] Recovery from master pos 43851595 and file binlog.006933 for channel 'amaster'. Previous relay log pos and relay log file had been set to 43851818, /home/mysql/log/relaylog/relaylog-amaster_3537.020527 respectively.
  33. ......
  34. 2017-05-25T14:11:03.817050+08:00 0 [Warning] Recovery from master pos 789680988 and file binlog.027468 for channel 'bmaster'. Previous relay log pos and relay log file had been set to 789681243, /home/mysql/log/relaylog/relaylog-bmaster_3637.020768 respectively.
  35. ......
  36. 2017-05-25T14:11:04.353863+08:00 0 [Note] /usr/sbin/mysqld: ready for connections.
  37. Version: '5.7.17-log'  socket: '/home/mysql/data/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
  38. 2017-05-25 14:11:04 0x7f10762de700  InnoDB: Assertion failure in thread 139708678924032 in file fsp0fsp.cc line 2108
    InnoDB: Failing assertion: frag_n_used > 0
  39. ......

截取出来的是第一次遇到问题, mysql重启进行Crash Recovery的日志;

可以从红色标记的地方看到, 其实第一次重启的时候, crash recovery就已经完成了, 而且mysqld进程也已经ready for connections,
但是马上就触发了同样的问题, 导致mysql又发生了Crash, 而且mysqld_safe也跟着"消失"了;

在之后的重启尝试中, 每次在Crash之前, 都有这么一行信息:

点击(此处)折叠或打开

  1. 2017-05-25T15:25:33.025244+08:00 0 [Note] InnoDB: Cleaning up trx with id 3377057419

结合堆栈信息中显示出来的fsp0fsp.cc line 2108, 在源代码中找到这一行(红色标注),

点击(此处)折叠或打开

  1. fsp_free_page(
            const page_id_t&        page_id,
            const page_size_t&      page_size,
            mtr_t*                  mtr)
  2. ......
  3. if (state == XDES_FULL_FRAG) {
  4.                 /* The fragment was full: move it to another list */
  5.                 flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
  6.                             mtr);
  7.                 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
  8.                 flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
  9.                               mtr);
  10.                 mlog_write_ulint(header + FSP_FRAG_N_USED,
  11.                                  frag_n_used + FSP_EXTENT_SIZE - 1,
  12.                                  MLOG_4BYTES, mtr);
  13.         } else {
  14.                 ut_a(frag_n_used > 0);
  15.                 mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1,
  16.                                  MLOG_4BYTES, mtr);
  17.         }

结合日志中的cleanup阶段的log和阿里的mysql内核月报中对innodb的分析可以知道, alter语句在drop 索引的时候会调用到这个方法的, 用来回收数据页/返还表空间;

所以问题基本确定就是alter语句引起了这次mysql的Crash, 且每次重启的时候都在同样一个位置报错说明这个alter ... drop index的数据页并没有完成cleanup, 每次重启的时候都在尝试, 然后触发Crash;

由于触发Crash的阶段始终都处于Crash Recovery之后,  所以推断mysql可能是在处于rollback阶段, 所以设置了innodb_force_recovery = 3,
发现跳过rollback以后数据库正常的起来了~\(≧▽≦)/~

那么事情就好办了, innodb_force_recovery = 3的时候是可以对表进行操作的, 比如说.....drop.....

在第一次Crash的日志里面, 可以看到tb0和tb1的alter可能都有问题, 因为alter产生的中间结果表还在data目录下;
所以为了不再让rollback触发alter语句cleanup的问题, 最简单的办法就是......drop掉这两个表~\(≧▽≦)/~

_(:з」∠)_ 当然不能直接drop...先dump出来.....
不过实际操作之前, 先确认一下当前数据库的状态:

从库复现主库的事务, 停留在这个阶段: 8fc6463a-f9b1-11e6-b218-ce0e1b052154:1-2241902370:2241902372-2241902383;
通过查看relaylog, 找到遗漏的2241902371事务, 正好是alter语句

这里面有几个比较重要的信息, 除了GTID和SQL以外, 还有一个: last_committed=91691

再看看2241902383之后的事务是什么

那么就基本确认了, 当前的状态是91692的事务组中, 除了2241902371以外全部提交成功, 而下一个事务组91693还没有开始;

再查一下有问题的tb0和tb1, 确认2241902371事务对应的表结构确实是没有主键, 那么说明这个语句确实没有执行, 所以目前的库应该是处于一致的状态的(Crash Recovery成功了是大前提)
我们开始着手让mysql启动起来~

_(:з」∠)_ 先把tb0和tb1都dump出来.....
~\(≧▽≦)/~ 然后drop掉~(如果之后需要重建同步的话, 记得关掉sql_log_bin, 不要把drop语句写到binlog)
(⊙﹏⊙)再去掉配置文件的innodb_force_recovery, 重启mysql.....

done, 数据库正常起来了~

之后就简单了, 重新把这两张表导入到数据库, 再开启同步, 看看同步的状态:

可以看到缺少的2241902371事务已经重新拉取下来了, 而且2241902384和之后的事务也正常的拉取和执行了~

等到同步同步跟上的时候, 就可以验证一下数据是不是真的一致了~

PS: 由于在重启的过程中, MTR和Crash Recovery都成功了, 而且同步状态正常, GTID的事务号也保持了连续, 从个人角度来看, 更加倾向于数据是一致的~
PPS: 这个库能交付给用户继续使用么? 虽然不推荐就这么交付回去, 不过用户说能用, 那就能用~

时间: 2024-09-26 20:51:56

MySQL案例-初步恢复: alter引起的从库无限Crash的相关文章

mysql案例:mysql5.6.14配置my.cnf多实例

mysql案例:mysql5.6.14配置my.cnf多实例,mysql_install_db初始化不读取my.cnf配置文件 1.1.1. mysql5.6.14多实例my.cnf时,初始化不读取my.cnf配置文件 [环境描述] 在多实例配置的/etc/my.cnf环境中,执行mysql_install_db后,启动Mysql报错. [操作步骤] /etc/my.cnf配置文件: [mysqld3307] innodb_data_file_path =ibdata1:1G:autoexten

mysql案例:Java程序访问Mysql报错

mysql案例:Java程序访问Mysql报错'OPTION SQL_SELECT_LIMIT=XXX' [环境描述] mysql版本: 5.6.14-56-log Percona Server (GPL) 程序: 使用JDBC驱动mysql-connector-java访问mysql数据库 [报错信息] 程序访问mysql执行SQL语句的时候报错: You have an error in your SQL syntax; check the manual that corresponds t

两台MYSQL服务器 主库坏挂掉后 备库启动,应用不更改设置

问题描述 两台MYSQL服务器 主库坏挂掉后 备库启动,应用不更改设置 我有两台mysql数据库服务器,服务器A 192.168.46.128 备库B 192.168.30.129 现在想做主主或者主备复制,另外想实现当主库A挂掉之后,备库B接管继续工作.正常情况应用程序连接数据库是通过IP连接的,假如我之前连了192.168.46.128,那它挂了之后,备用数据库启动IP就变成了192.168.30.129 请教大神,我改如何设置做到,主库挂了,应用不做修改的情况下,可以自动连到192.168

MySQL案例-Semaphore wait与undo log

-------------------------------------------------------------------------------------------------正文---------------------------------------------------------------------------------------------------------------场景:MySQL-5.7.17, 主从架构, 业务读写分离, 只读从库不定期出现

mysql主键的缺少导致备库hang

最近线上频繁的出现slave延时的情况,经排查发现为用户在删除数据的时候,由于表主键的主键的缺少,同时删除条件没有索引,或或者删除的条件过滤性极差,导致slave出现hang住,严重的影响了生产环境的稳定性,也希望通过这篇博客,来加深主键在innodb引擎中的重要性,希望用户在使用RDS,设计自己的表的时候,一定要为表加上主键,主键可以认为是innodb存储引擎的生命,下面我们就来分析一下这个案例(本案例的生产环境的binlog为row模式,对于myisam存储引擎也有同样的问题): (1).现

mysql主键的缺少导致备库hang住_Mysql

最近线上频繁的出现slave延时的情况,经排查发现为用户在删除数据的时候,由于表主键的主键的缺少,同时删除条件没有索引,或或者删除的条件过滤性极差,导致slave出现hang住,严重的影响了生产环境的稳定性,也希望通过这篇博客,来加深主键在innodb引擎中的重要性,希望用户在使用RDS,设计自己的表的时候,一定要为表加上主键,主键可以认为是innodb存储引擎的生命,下面我们就来分析一下这个案例(本案例的生产环境的binlog为row模式,对于myisam存储引擎也有同样的问题):(1).现象

Linux环境中MySQL主从同步--添加新的从库

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dgd2010.blog.51cto.com/1539422/1689171 当前我认为数据库主从有两大应用价值: 1.从库相当于主库的备份.虽然数据库的主从并不能代替/取代备份,例如错误的数据可能毁掉所有的数据库,但主从也是在一种可读的状态下保持备份的一种实现方式. 2.从库可以缓解主库的压力,能提高性能.由于从库是只读的,因此在读取查询方面,从库可以代替主库,承担一定的压力,

MySQL案例分析--QueryCache

QueryCache联动内容:http://blog.itpub.net/29510932/viewspace-1694922/ -------------------------------------------------------------------------------------------------正文--------------------------------------------------------------------------------------

MySQL案例-GTID同步失败:master has purged binary logs

GTID工具联动:http://blog.itpub.net/29510932/viewspace-1736132/ -------------------------------------------------------------------------------------------------正文--------------------------------------------------------------------------------------------