前些日子,一个客户跟我说有一台服务器掉电重启后 MySQL 实例无法启动了,他把 error log 拍照给我后发现是数据页损坏,然后 innodb_flush_log_at_trx_commit 设置为 2。
于是让他把 innodb_force_recovery 参数从 1-6 依次设置重启 MySQL,在设置 innodb_force_recovery = 3 的时候启动成功了。但是在接下来的 mysqldump 过程中遇到一个诡异的问题,在导出 cm_hj_xw 这张表时,mysqld 会重启,错误日志显示:
[ERROR] InnoDB: InnoDB: Unable to allocate memory of size 18446744073709540096.
7f6c69823700 InnoDB: Assertion failure in thread 140103603336960 in file ha_innodb.cc line 17137
手工查询这张表也会导致重启,一番尝试、搜索之后,找到一个类似的 bug#70185,但是官方没承认。心想通过备份或者从库恢复吧,结果压根没有做过备份,也没有从库...
客户爸爸着急,即使放假也得匆忙赶到现场。在路上先让客户把这张表之外的数据都 dump 出来了,既然逻辑读取行不通,我想到了物理导出,InnoDB表开启独立表空间后有一种可传输表空间技术“transportable tablespace”,可以将表空间导出,给其他实例使用。一番操作之后终于把这张表给恢复了:
导出表空间
- flush tables cm_hj_xw for export;
- 拷贝 cm_hj_xw.ibd 和 cm_hj_xw.cfg 文件
- unlock tables
在一个新的实例上导入表空间
- create table cm_hj_xw
- ALTER TABLE cm_hj_xw DISCARD TABLESPACE;
- 拷贝 cm_hj_xw.ibd 和 cm_hj_xw.cfg 文件到库目录下
- ALTER TABLE cm_hj_xw IMPORT TABLESPACE;(经测试135G大小的表,导入表空间需要24分钟)
不得不啰嗦提醒各位DBA同行,innodb_flush_log_at_trx_commit、sync_binlog 一定要设置为 1,数据持久性一致性的保障不是闹着玩的。一定要定期做备份,一定要有主从架构,这样多重保障才能确保数据的可靠。
网友评论