事故的起因是因为当我访问某个数据库的某个表的时候,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 数据页损坏事故恢复复盘的更多相关文章

  1. Linux—挂载磁盘(云盘)

    创建挂载目录 [root@localhost ~]# mkdir -p /www 可以看到/dev/vda1盘挂载/ /dev都是位于根路径下,都属于系统盘.根路径 / 都是位于系统盘.而/root, ...

  2. 捉虫日记 | MySQL 5.7.20 try_acquire_lock_impl 异常导致mysql crash

    背景 近期线上MySQL 5.7.20集群不定期(多则三周,短则一两天)出现主库mysql crash.触发主从切换问题,堆栈信息如下: 从堆栈信息可以明显看出,在调用 try_acquire_loc ...

  3. 【Linux】扩展阿里云数据盘分区和文件系统

    扩容云盘只是扩大存储容量,不会扩容文件系统 一.准备工作 在扩展数据盘扩展分区和文件系统前,请提前完成以下工作. 创建快照以备份数据,防止操作失误导致数据丢失. 通过ECS控制台或者API扩容云盘容量 ...

  4. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  5. linux下转换U盘文件系统

    打算在windows 7 下复制一个12G 的文件至U盘,无奈U盘为FAT32格式,最大支持移动4G 的文件,只能将U盘文件系统格式化为NTFS.windows 7系统出现问题,转化中总是出现错误.故 ...

  6. Linux下的磁盘分割和文件系统

    一.各硬件装置在Linux下的文件名 1.IDE硬盘机 在Linux内的文件名: /dev/hd[a-d]  (a-d 刚好是四个这个是有原因的具体如下) 解释:以 IDE 接口来说,由于一个 IDE ...

  7. 如何在 Linux 终端下创建新的文件系统/分区

    在 Linux 中创建分区或新的文件系统通常意味着一件事:安装 Gnome Parted 分区编辑器(GParted).对于大多数 Linux 用户而言,这是唯一的办法.不过,你是否考虑过在终端创建这 ...

  8. 【linux之设备,分区,文件系统】

    一.设备 IDE磁盘的设备文件采用/dev/hdx来命名,分区则采用/dev/hdxy来命名,其中x表示磁盘(a是第一块磁盘,b是第二块磁盘,以此类推), y代表分区的号码(由1开始,..3以此类推) ...

  9. linux.1:创建分区和文件系统

    概述 使用 fdisk.gdisk 和 parted 创建和修改 MBR 和 GPT 分区在本教程中,学习磁盘分区和 Linux 文件系统相关内容,包括学习如何: 使用 mkfs 命令设置 ext2. ...

随机推荐

  1. 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证

    通过这篇 全栈项目|小书架|服务器开发-JWT 详解 文章我们对JWT有了深入的了解,那么接下来介绍JWT如何在项目中使用. 安装 $ npm install jsonwebtoken 生成 Toke ...

  2. 深入理解JVM(四) -- 垃圾内存回收的判定方法和内容

    上一篇文章我们学到了对象在内存中是如何存储的已经是如何被访问的,这篇文章将介绍当内存空间不够时,虚拟机将怎样判定对象可不可以被回收已经哪些地方会发生回收. 垃圾回收主要(不是全部)发生在堆内存中,当一 ...

  3. 【转载】 C#中通过Where方法查找出所有符合条件的元素集合

    在C#的List集合对象中,FirstOrDefault方法可以用于查找List集合中符合条件的第一个元素,如果需要根据条件查找到List集合中的所有符合条件的元素对象集合,则需要使用到List集合的 ...

  4. text-overflow 全兼容

    text-overflow 全兼容 text-overflow 这个CSS属性用于设置或检索是否使用一个省略标记(...)标示对象内文本的溢出.比起在后台用程序截断文本再附上省略标记的做法,用CSS来 ...

  5. python 爬虫 user-agent 生成

    有些网站做了反爬技术,如:比较初级的通过判断请求头部中的user-agent字段来检测是否通过浏览器访问的. 在爬这类网站时需要模拟user-agent import random import re ...

  6. 聊聊GIS中的坐标系|再版

    本文约6500字,建议阅读时间15分钟. 作者:博客园/B站/知乎/csdn/小专栏 @秋意正寒 版权:转载请告知,并在转载文上附上转载声明与原文链接(https://www.cnblogs.com/ ...

  7. Oracle 11g 服务器结构

    Oracle 服务器主要又实例.数据库.程序全局区和前台进程组成. 实例可以进一步划分为系统全局区(SGA)和后台进程(PMON.SMON等)两部分,其中,SGA 使用操作系统的内存资源,而后台进程需 ...

  8. 关于vue-svg-icon的使用方式

    前言 工作中用到svg格式的图标,既然是svg,当然不想用古老的img方式引用,希望能凭借定义svg的fill属性,随意定义图标的颜色:同时不想将整段svg代码写入组建内,于是找到了使用vue-svg ...

  9. 服务网关ZuulFilter过滤器--pre/post/error的用法(校验请求信息,获取路由后的请求/响应信息,处理服务网关异常)

    微服务中Zuul服务网关一共定义了四种类型的过滤器: pre:在请求被路由(转发)之前调用 route:在路由(请求)转发时被调用 error:服务网关发生异常时被调用 post:在路由(转发)请求后 ...

  10. centos7开启80端口及其他端口

    首先centos7的防火墙由iptables改为了firewalld 1. 执行命令:firewall-cmd --zone=public --add-port=80/tcp  --permanent ...