问题场景:
疑似是误删了数据库,在导入宝塔的备份时,发现用户表也出现了异常,原有5800多用户,导入完只剩下490用户了。
解决方案:
通用思路:
通常情况下,我们遇到这种情况有两种思路:
- 是否有快照备份?是否有数据库sql文件备份?
- 是否有BINLOG日志?
观察数据表排查问题:
首先,我们先需要进入数据库查看用户表的情况,我们发现sms_common_user
表从380个用户开始,就直接到5096用户了,因此数据应该是在这中间出现丢失的
解决方案一:
SQL文件恢复方法
如果有快照备份那当然最好了,直接回滚就好了。但是由于没有做快照策略,因此之前都是宝塔手动备份的SQL文件。
这时,我们需要去查看宝塔的备份
在宝塔的数据库>备份>下载最新的备份文件
下载后解压缩发现是SQL文件,我们可以用记事本或者emeditor打开
可以看到插入用户表里是分两段进行插入的
放到记事本里仔细打开看了下
这381之后的用户明明都有啊,怎么会导入备份写不进去呢?这时,我想到之前某个项目的时候,就出现过用宝塔导入导不进去的情况,后来还是要用命令行导入的。
手动导入SQL方法
手动导入sql文件的大致步骤:
- 输入下面命令然后输入mysql的root密码
mysql -u root -p
- 然后选择进入你要操作的数据库,譬如psbcdvsp
use psbcdvsp
- 导入数据库sql文件
users.sql
(请确保你运行第一个命令的时候,所在目录有users.sql
文件)
source pig.sql
按照上面的步骤我重新导入了一次数据库,结果发现还是不行……
这就有点尴尬了,数据明明有,怎么导不进去呢,我决定进到phpmyadmin
后台,手动输下SQL命令看看
我这里导入sms_common_user
直接从381用户开始,看看能不能导进去
结果发现报错了
报错内容为
#1062 - Duplicate entry '?' for key 'sms_common_user.username'
上面报错的含义是指sms_common_user
表下的username
是唯一的键,也就代表着不允许有重复,那么问题来了,用户名为什么会重复?这个就要结合程序来分析了,这张表大多都是微信登录的用户,微信用户有的时候会出现emoji表情等符号,可能是在备份过程中这些特殊符号不识别,就被转成了?
,因此,我们在恢复的时候就出现了导入失败的情况。如何打破上面的这种僵局呢?我们需要去索引里看下设置
我们把UNIQUE
改成INDEX
就行了,就不要求用户名唯一了,这样就可以顺利导入了!
改完之后,大约用了不到一分钟数据就全部导入成功了,用户恢复到5868个了
解决方案二:
BINLOG日志恢复
不过,这种方法,其实我一开始也想到了,这里也简单做个分享,其实如果你之前关注过行业的新闻,早在2017年就有gitlab著名的删库事件《Gitlab 从删库到恢复:丢失 6 小时生产数据,操作员应该被开除?》
当然,这都不重要,重要的是他们是如何恢复的?其实这里恢复很大程度上是借助BINLOG日志的
我们用的宝塔面板的/www/server/data
路径下
mysql-bin
开头的文件就是日志文件
这里教大家简单的命令将日志导出到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
,然后将其下载到本地
这些文件几乎都是上百兆了,因此我们这时就不能用记事本打开了,就要像我开头说的用emeditor
工具里有个筛选功能还是不错的,在筛选的时候其他无关的内容就不会显示
然后,里面全部操作记录都可以看到
之后我们把和用户相关的数据导入sql数据库就行了(不过,我们的这个案例里核心问题不是数据丢失,而是数据因为表中字段的唯一性,导致无法导入表中)