问题场景
昨天有热心网友找我,疑似是误操作删了库。
同时在导入宝塔的备份时,发现用户表也出现了异常,原有5800多用户,导入完只剩下490用户了
解决方案
通用思路
通常情况下,我们遇到这种情况有两种思路:
- 是否有快照备份?是否有数据库sql文件备份?
- 是否有BINLOG日志?
观察数据表排查问题
首先,我们先需要进入数据库查看用户表的情况,我们发现sms_common_user
表从380个用户开始,就直接到5096用户了,因此数据应该是在这中间出现丢失的
![图片[1]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522060227792-1024x529.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
方案一:SQL文件恢复方法
这时,我们按照上面的解决方案方法一:
如果有快照备份那当然最好了,直接回滚就好了。
要是有快照热心网友还会找我?
![图片[2]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522060436486.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
用户没有做快照策略,因此之前都是宝塔手动备份的SQL文件。
这时,我们需要去查看宝塔的备份
在宝塔的数据库>备份>下载最新的备份文件
![图片[3]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522055808103-1024x451.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
下载后解压缩发现是SQL文件,我们可以用记事本或者emeditor打开
可以看到插入用户表里是分两段进行插入的
![图片[4]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522060545608-1024x68.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
放到记事本里仔细打开看了下
![图片[5]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522060903735-1024x178.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
这381之后的用户明明都有啊,怎么会导入备份写不进去呢?这时,我想到之前autosign那个项目,就出现过用宝塔导入导不进去的情况,后来还是要用命令行导入的
手动导入SQL方法
手动导入sql文件的大致步骤:
- 输入下面命令然后输入mysql的root密码
mysql -u root -p
- 然后选择进入你要操作的数据库,譬如
fancypig
use fancypig
- 导入数据库sql文件
pig.sql
(请确保你运行第一个命令的时候,所在目录有pig.sql
文件)
source pig.sql
按照上面的步骤我重新导入了一次数据库,结果发现还是不行……
![图片[6]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522061240459.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
这就有点尴尬了,数据明明有,怎么导不进去呢,我决定进到phpmyadmin
后台,手动输下SQL命令看看
我这里导入sms_common_user
直接从381用户开始,看看能不能导进去
![图片[7]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062043519-1024x316.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
结果发现报错了
![图片[8]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062127962-1024x185.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
报错内容为
#1062 - Duplicate entry '?' for key 'sms_common_user.username'
上面报错的含义是指sms_common_user
表下的username
是唯一的键,也就代表着不允许有重复,那么问题来了,用户名为什么会重复?这个就要结合程序来分析了,这张表大多都是微信登录的用户,微信用户有的时候会出现emoji表情等符号,可能是在备份过程中这些特殊符号不识别,就被转成了?
,因此,我们在恢复的时候就出现了导入失败的情况。如何打破上面的这种僵局呢?我们需要去索引里看下设置
![图片[9]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062402802.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
我们把UNIQUE
改成INDEX
就行了,就不要求用户名唯一了,这样就可以顺利导入了!
![图片[10]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062413147.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
改完之后,大约用了不到一分钟数据就全部导入成功了,用户恢复到5868个了
![图片[11]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062539194.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
方案二:BINLOG日志恢复
不过,这种方法,其实我一开始也想到了,这里也简单做个分享,其实如果你之前关注过行业的新闻,早在2017年就有gitlab著名的删库事件《Gitlab 从删库到恢复:丢失 6 小时生产数据,操作员应该被开除?》
当然,这都不重要,重要的是他们是如何恢复的?其实这里恢复很大程度上是借助BINLOG日志的
我们用的宝塔面板的/www/server/data
路径下
mysql-bin
开头的文件就是日志文件
![图片[12]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522062951671.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
这里教大家简单的命令将日志导出到sql文件
宝塔的mysqlbinlog
工具位置是/www/server/mysql/bin/mysqlbinlog
这时,我们要将mysql-bin.000006
文件导出到/www/bak.sql
这里记得要先到/www
路径下新建个空的bak.sql
然后再执行下面的命令
/www/server/mysql/bin/mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000006 > /www/bak.sql
就这样,我们把mysql-bin.000005
、mysql-bin.000006
、mysql-bin.000007
依次进行了恢复bak.sql
、bak1.sql
、bak2.sql
,然后将其下载到本地
![图片[13]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522063244806.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
这些文件几乎都是上百兆了,因此我们这时就不能用记事本打开了,就要像我开头说的用emeditor
工具里有个筛选功能还是不错的,在筛选的时候其他无关的内容就不会显示
然后,里面全部操作记录都可以看到
![图片[14]-宝塔误删数据库如何恢复?一次恢复mysql数据的实践-FancyPig's blog](https://static.iculture.cc/wp-content/uploads/2022/05/20220522063516692-1024x532.png?x-oss-process=image/auto-orient,1/format,webp/watermark,image_cHVibGljL2xvZ28ucG5nP3gtb3NzLXByb2Nlc3M9aW1hZ2UvcmVzaXplLFBfMTA,x_10,y_10)
之后我们把和用户相关的数据导入sql数据库就行了(不过,我们的这个案例里核心问题不是数据丢失,而是数据因为表中字段的唯一性,导致无法导入表中)
- 最新
- 最热
只看作者