照成事故的原因可以说非常悲催了。因为线上数据库做迁移,由之前一台window服务器MySQL5.7.17版本迁移到另外一台Linux服务器MySQL8.0.17版本。因为了省事,在未做数据库备份的前提下直接使用了navicat 的表在线复制功能去做,结果出现异常了。新库中没有将表与数据复制过去,结果老库中表直接变成了一个自己不认识的样子。出现该情况吓得里面找备份库去还原。找到一个非常相近的备份库,是两个小时前的备份。只能先将这个还原到新库Mysql 8.0.17上,检查没有多大问题后,脑子瓦特的将老库window MySQL5.7.17 的库删除后又重新建了同名库后(删除库表示不能通过data还原)直接卸载了。是的直接卸载了,还没平稳度过一天发现线上出问题了,丢失了极少数的数据。数据找回之旅开始了!
备份!备份!备份! 数据库所有操作先备份,真的很重要!
上述中被卸载的 MySQL 5.7.17
(小版本号也很重要),为了模拟生产上的环境,我们在线下电脑上安装了此版本。在原老库服务器上拷贝了老库的Data
目录,忘记一点前提 原老数据库开启了binlog日志备份,在老库的Data
目录中存在大量的日志备份文件。根据日志时间判断,最有用的是一个文件是mysql-log.0000025
,我们需要的数据也存在其中。下一步我们想办法打开此文件。MySQL binlog 日志没有很好的可视化工具,尝试过使用文本编辑器打开,结果全是乱码,无法可视。只能通过MySQLbinlog工具进行查看,这种查看方式首先要将日志环境放入mysql中,才能使用。下面我们讲一下还原的步骤:
- 第一步:在老库
Data
目录中ibtmp1
、ibdata1
、ibtmp1
、ib_logfile1
、auto.cnf
五个文件覆盖到线下模拟环境中,同时将mysql-log.0000025
日志文件考入线下模拟环境data中。 - 第二步:开启线下模拟环境的binlog日志(修改my.ini文件开启)。重启数据库服务,此时查看线下模拟环境的binlog开启情况。
mysql> show variables like 'log_%'; // 没有开启log_bin的值是OFF,开启之后是ON
mysql>show binary logs; // 查看binlog 文件列表
查看文件列表有没有发现,我们的mysql-log.0000025
文件没有在其中,不着急下一步。
image.png
- 第三步:在线下模拟环境的
Data
目录有个mysql-bin.index
文件,这个是用富文本可以编辑的。按照他的格式,我们将mysql-log.0000025
文件加入,重启数据库服务。
image.png
image.png
再次执行show binary logs;
命令,日志文件已经成果还原。
- 第四步:使用
show binlog events in 'mysql-bin.000025';
命令就可以查看了。但是这种方式几乎得不到什么有用的信息。
image.png
好了,至此我们已经成功还原了模拟环境,下一步进行数据操作
方式一:使用mysqlbinlog.exe 导出sql 文件找出可执行的sql
// 原始导出 sql 文件,但是内容都是base64 编码后的。
mysqlbinlog mysql-bin.000025 > a.sql
// 导出base64解码后的 sql 文件,但是出现问题 中文乱码。
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000025 > a.sql
使用导出base64解码后的 sql 文件,但是出现问题 中文乱码,但是基本可视。
image.png
由于乱码加上数据量巨大,直接找sql这种方式容易出错不可行。
方式二:使用mysqlbinlog.exe 直接还原到线下模拟环境
由于我们只是丢失了个别时间段的时间,所以我们使用指定时间的数据恢复方式进行处理。
mysqlbinlog --start-datetime="2018-04-27 20:58:18" --stop-datetime="2018-04-27 20:58:35" --database=dbName mysql-bin.000025 |mysql -uroot -p
--start-datetime
与--stop-datetime
的时间如何找,我们通过方式1 中导出的sql 文件,找到每个BEGIN开始的时间,推算出我们需要的开始和结束时间。或者还可以使用指定位置来恢复,不过我们没有尝试。
通过此方法最终成功找回数据。
网友评论