Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘
事故的起因是因为当我访问某个数据库的某个表的时候,MySQL 立即出现崩溃并且去查看 MySQL 的错误日志出现类似信息
--09T05::.232564Z [ERROR] InnoDB: Space id and page no stored in the page, read in are [page id: space=, page number=], should be [page id: space=, page number=]
--09T05::.232613Z [ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=, page number=]. You may have to recover from a backup.
--09T05::.232620Z [Note] InnoDB: Page dump in ascii and hex ( bytes): --09T05::.301493Z [Note] InnoDB: Uncompressed page, stored checksum in field1 , calculated checksums for field1: crc32 /, innodb , none , stored checksum in field2 , calculated checksums for field2: crc32 /, innodb , none , page LSN , low bytes of LSN at page end , page number (if stored to page already) , space id (if created with >= MySQL-4.1. and stored already)
InnoDB: Page may be a freshly allocated page
--09T05::.301532Z [Note] InnoDB: It is also possible that your operating system has corrupted its own file cache and rebooting your computer removes the error. If the corrupt page is an index page. You can also try to fix the corruption by dumping, dropping, and reimporting the corrupt table. You can use CHECK TABLE to scan your table for corruption. Please refer to http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html for information about forcing recovery.
--09T05::.301558Z [ERROR] [FATAL] InnoDB: Aborting because of a corrupt database page in the system tablespace. Or, there was a failure in tagging the tablespace as corrupt.
-- :: 0x7fe307678700 InnoDB: Assertion failure in thread in file ut0ut.cc line Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (7fe2dc03c240): select * from desktop_document2
Connection ID (thread ID):
Status: NOT_KILLED
可以注意到这里就是 MySQL innodb 的数据发生了损坏。可以看到日志的最下面其实这里就是给出的是可能造成崩溃的 query
这里我们可以看到是要因为对 desktop_document2 进行读取造成的。一旦我们对该表尝试读写或者 check table 都会造成 MySQL 崩溃重启。
这里有两种解决思路:
1. 有备份的话将备份找个地方恢复出来,然后重新生成该表。
2. 如果对应到坏的表 check 了之后发现是可有可无可以重新生成的表,可以直接将该表 drop 掉重建。这样可以省出一些恢复的成本和复杂性。
3. 如果坏的数据不可修复,也没有备份。那么需要避开坏数据用 id 偏移的方式尽量扫描更多的数据出来。
然后这里还有个脚本 可以批量扫描坏表。当遇到第一个坏表的时候检查打印出来的 table_name 并做确认。然后排出掉他再继续扫下面的表。
#!/bin/bash
host_name=127.0.0.1
user_name=
user_pwd=
database=
tables=$(/usr/local/webserver/mysql/bin/mysql -h$host_name -u$user_name -p$user_pwd $database -A -Bse "show tables")
for table_name in $tables
do
echo $table_name
check_result=$(/usr/local/webserver/mysql/bin/mysql -h$host_name -u$user_name -p$user_pwd $database -A -Bse "check table $table_name" | awk '{ print $4 }')
if [ "$check_result" = "OK" ]
then
echo "OK TABLE $table_name"
fi
done
需要注意的是使用该脚本在扫描到坏表的时候同样会触发 MySQL 异常重启。
到目前为止来看似乎情况可控,但是遗憾的是造成这次事故继续扩大的是。当时我发现异常损坏发生在系统盘,然后该盘有天级快照。在和各方确认该数据库影响之后我打算直接使用 aliyun 的天级快照来恢复目前糟糕的情况。然后再重新计算当天的相关数据即可,恢复的周期也比较短。
于是关机开始恢复快照 然而等待我的却是
exoo me????
看上去是引导区损坏了,到这里为止就感觉情况变得非常麻烦了。因为快照恢复之后出现这个问题就意味着之前很长一段时间一直都存在引导区因为文件系统损坏而损坏的情况。也就是说可能之前的快照也都坏了,系统盘无法作为引导启动系统。
后来联系 aliyun 工程师通过 liveCD 重启系统,将之前系统挂载到数据盘开始抢救数据。
这里有个值得反思的地方,当时没有做这个机器的数据库备份是因为想到有快照可以依赖,用快照来当备份使用。但是没有考虑打的是,MySQL 的默认数据目录是 /var/lib ,而这个目录存在于数据库上而并非数据盘上。一旦出现类似的文件系统或者引导区损坏重启之后可能就无法进入系统,最严重的情况可能无法使用快照恢复任何数据。
所以说任何时候即使有快照,都应该对你的数据库进行最少天级备份。
在和 aliyun 确认一些信息之后,我列了一个恢复方案最终使用了方案2恢复了数据。下面贴一个 check list
方案1: 1. data02 上用 data- .8日凌晨3点的快照恢复一块 500g 的数据盘。
2. data02 上配置和 data- 上版本相同的 MySQL(5.7.)。
3. 使用 data- 上 MySQL 的数据目录恢复出当时 MySQL 的情况并且启动 MySQL
4. 使用 innobackupex 将机器上的数据库全量备份出来,同时查看数据完整性情况,使用脚本 check table 检查完整性。
5. 将 data- 机器还原成初始配置,安装同样版本的数据库,并且使用备份恢复数据库数据。 方案2: 1. 直接在 data- 上重置系统。☑️
2. 然后使用镜像挂一个 500g 的盘。☑️
3. 通知 aliyun 工程师使得新挂载的盘变得可读。☑️
4. 安装 MySQL 5.7. 数据库。☑️
5. 将数据库文件找个地方拷贝出来。☑️
6. 将数据文件恢复至 新安装的 5.7. 数据库,并且不保证相关账号密码都和以前一致。☑️
这里要提一下方案2的todo 6,如果全量恢复整个数据库的数据,可以直接将整个数据目录进行覆盖,然后重启数据库就可以简单的直接通过文件恢复数据库。
如果是单纯的要恢复某个表或者某个库,最好还是找机器全量恢复之后,使用 mysqldump 或者 pxb 备份对应的库表进行恢复比较简单。直接通过恢复文件的形式恢复单个表库实在太过于复杂了,感觉没必要。
截止到目前数据库就已经恢复了,剩下的还是要 drop 掉坏掉的表进行重建,或者参照上面的方法进行数据抢救。
其实在之前一个月就发现该机器有一些奇怪的报错日志 类似于
Aborted connection to db: 'test' user: 'root' host: '127.0.0.1' (Got timeout reading communication packets)
后来看了一些资料,这些都是一些网络超时错误,与此次事故无关,可以根据 http://mysql.taobao.org/monthly/2017/05/04/ | https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/ 来仔细排查网络问题。
小结:
不管有没有快照或者别的保护措施都应该对数据库进行天级备份,有备无患。
当能恢复接触到数据的时候应该第一时间对数据进行再备份,保证至少当前状态可以保证不再恶化。
要第一时间通知相关小伙伴事故处理的进度,以及通知到受影响的小伙伴获得他们的支持,恢复之后第一时间恢复相关服务。
Reference:
https://zhuanlan.zhihu.com/p/60327406 MySQL通过frm、ibd文件恢复innodb数据
http://www.yunweipai.com/archives/19844.html MySQL 如何利用 ibd 文件恢复数据
http://mysql.taobao.org/monthly/2017/05/04/ MySQL · 答疑解惑 · MySQL 的那些网络超时错误
https://www.percona.com/blog/2016/05/16/mysql-got-an-error-reading-communication-packet-errors/ mysql-got-an-error-reading-communication-packet-errors
https://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html Forcing InnoDB Recovery
Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘的更多相关文章
- Linux—挂载磁盘(云盘)
创建挂载目录 [root@localhost ~]# mkdir -p /www 可以看到/dev/vda1盘挂载/ /dev都是位于根路径下,都属于系统盘.根路径 / 都是位于系统盘.而/root, ...
- 捉虫日记 | MySQL 5.7.20 try_acquire_lock_impl 异常导致mysql crash
背景 近期线上MySQL 5.7.20集群不定期(多则三周,短则一两天)出现主库mysql crash.触发主从切换问题,堆栈信息如下: 从堆栈信息可以明显看出,在调用 try_acquire_loc ...
- 【Linux】扩展阿里云数据盘分区和文件系统
扩容云盘只是扩大存储容量,不会扩容文件系统 一.准备工作 在扩展数据盘扩展分区和文件系统前,请提前完成以下工作. 创建快照以备份数据,防止操作失误导致数据丢失. 通过ECS控制台或者API扩容云盘容量 ...
- .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...
- linux下转换U盘文件系统
打算在windows 7 下复制一个12G 的文件至U盘,无奈U盘为FAT32格式,最大支持移动4G 的文件,只能将U盘文件系统格式化为NTFS.windows 7系统出现问题,转化中总是出现错误.故 ...
- Linux下的磁盘分割和文件系统
一.各硬件装置在Linux下的文件名 1.IDE硬盘机 在Linux内的文件名: /dev/hd[a-d] (a-d 刚好是四个这个是有原因的具体如下) 解释:以 IDE 接口来说,由于一个 IDE ...
- 如何在 Linux 终端下创建新的文件系统/分区
在 Linux 中创建分区或新的文件系统通常意味着一件事:安装 Gnome Parted 分区编辑器(GParted).对于大多数 Linux 用户而言,这是唯一的办法.不过,你是否考虑过在终端创建这 ...
- 【linux之设备,分区,文件系统】
一.设备 IDE磁盘的设备文件采用/dev/hdx来命名,分区则采用/dev/hdxy来命名,其中x表示磁盘(a是第一块磁盘,b是第二块磁盘,以此类推), y代表分区的号码(由1开始,..3以此类推) ...
- linux.1:创建分区和文件系统
概述 使用 fdisk.gdisk 和 parted 创建和修改 MBR 和 GPT 分区在本教程中,学习磁盘分区和 Linux 文件系统相关内容,包括学习如何: 使用 mkfs 命令设置 ext2. ...
随机推荐
- java后台获取微信小程序openid
一.jar包准备 1.在网盘下载 链接:https://pan.baidu.com/s/15HAAWOg_yn768g4s9IrcPg 提取码:hgj0 二.在pom文件中添加依赖 1.将外部的引入的 ...
- 了解Django之前
什么是web应用? 通俗地讲,就是通过浏览器访问一个网址,该网站从后台调取数据,然后把相应的界面展示给用户这样的一个过程. 什么是HTTP协议? 即超文本传输协议:规定了客户端与服务端消息传输的格 ...
- Markdown 初学总结
Markdown Tutorial(Typora-Specific) 1. Headers 最多可有六级标题,在标题前加 # 作为标记.注意标记与标题内容之间有空格: # 这是一级标题 ## 这是二级 ...
- centos下安装nginx(转载)
http://blog.csdn.net/u010246789/article/details/51501710 有声明,不能转载,所以,就把地址弄了过来
- 接口认证:Bearer Token(Token 令牌)
因为HTTP协议是开放的,可以任人调用.所以,如果接口不希望被随意调用,就需要做访问权限的控制,认证是好的用户,才允许调用API. 目前主流的访问权限控制/认证模式有以下几种: 1)Bearer To ...
- python3 中的try 异常调试与 raise 异常抛出
一.什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Python对象,表示一个错误. 当Py ...
- 用户在浏览器输入URL回车之后,浏览器都做了什么
在直接列出执行的步骤之前先来普及几个知识,相信了解完这些知识之后会对前后端的交互有更深入的理解. 1.TCP连接 TCP:Transmission Control Protocol, 传输控制协议,是 ...
- 转 Python3 ssl模块不可用的问题
编译安装完Python3之后,使用pip来安装python库,发现了如下报错: $ pip install numpy pip is configured with locations tha ...
- EasyUI DataGrid 根据ID选中行(转载)
转载来源: https://blog.csdn.net/chq00788/article/details/51505519 function selectRows(){ //获取需要选中的记录ID ...
- mysql 登录报错
执行命令:mysql -u root -p 错误:error while loading shared libraries: libncurses.so.5: cannot open shared o ...