删库了?或许还能抢救一下
前言
删库一般是不存在的,尤其是正式环境下,但是,万一呢?我就曾经遇到过,不过不是我,是我的同事,总会有这种情况发送,所以不管是发生还是没发生,都要知道该如何拯救,在没有任何保护措施的情况下,这是最后的稻草
最后的救命稻草就是mysql最重要的日志之一 [binlog],它记录了所有的DDL和DML(除了数据查询语句)语句,也是实现主从复制的关键
#查看是否启动binlog日志(大部分默认是开启的)OFF是关闭,ON是开启
#如果没有配,你先跑,我断后~
show VARIABLES like 'LOG_bin%';
参数说明:
log_bin_basename:这个是 binlog 日志文件的名称前缀,将来产生的 binlog 日志文件名为 java_logbin.xxx
log_bin_index:这个是 binlog 的索引文件,保存了所有 binlog 的目录,因为 binlog 可能会有多个
没有配强烈建议配上,找到mysql配置文件my.cnf进行配置. 提示:这里也可以命令设置,但只能本此服务中有效,宕机或者关机重启后就会失效了,建议修改配置文件
#查看配置文件目录
find / -name my.cnf 或者 whereis mysql.cnf
编辑my.cnf,根据公司需求在末尾最后加上相应内容,ps:最好先备份一份
这是我自己的配置
log_bin=java_logbin #日志文件名
binlog_format=row #日志格式
expire_logs_days=3 #日志过期时间
这里有几点需要特别说明:
日志不设置默认大小是1GB,大概满了之后就会生成新的文件(格式:xx.00001,xx.00002,....)
binlog 的日志有三种格式,分别是 STATEMENT、ROW、MIXED。在 mysql5.7.7 版本之前默认使用的是 STATEMENT,之后的版本默认使用的是 ROW, 这里推荐也是使用ROW
我只讲下重要的区别,详情请参考顶部文章
STATEMENT: 只记录修改的原本的sql,比如执行了,delete from xx where type='文具',那日志中就只记录了这一条原始的sql,优点是文件体积小
ROW:(推荐) 记录的是每一条数据被修改的详细细节,比如执行了,delete from xx where type='文具',总共删除了10条数据,日志则会记录十条被删除的sql,变成:delete from xx where id=1,name=张三,type=文具 ... , 缺点就是文件体积会比较大
MIXED : STATEMENT 和 ROW 的结合,mysql 会根据具体执行的 sql 语句,来选择合适的日志格式进行记录,但并不推荐.它只在遇到复杂的语句或函数操作时才会选择 ROW 来记录日志
配置完后需要重启一下mysql才会生效
systemctl restart mysqld 或 service mysql restart
再次查看日志信息
#查看是否启动binlog日志
show VARIABLES like 'LOG_bin%';
#同时可以看一下相关配置信息
#查看日志文件名及大小,
show master logs;
#查看/设置自动过期时间
show VARIABLES like 'expire_logs_days';
set global expire_logs_days = 3;(临时设置,本次服务中有效)
#刷新并生成到新的日志文件
flush logs;
这里就要开始恢复数据了,为了演示我造了一些数据作为参考:
现在去查看binlog日志,路径还记得吗,就是上面查看时候启动的命令会展示
找到路径后如果直接打开会发现是一堆乱码,因为这是二进制文件
不要紧,mysql提供了专门的命令
Mysqlbinlog -v xxx.00001
如果出现了以下错误,是因为mysqlbinlog识别不了该格式,最方便的方法就是加上-- no-defaults
即可: mysqlbinlog --no-defaults -v xxx.00001
但是有个问题,一个日志文件,小的还好,大的可咋整,随随便便一个几百兆,要从几百兆日志中找到我们需要的日志,还是比较麻烦的,还好 mysqlbinlog 命令提供一些参数选项可以让我们对 binlog 文件进行筛选,最常用的参数就是时间参数
如果删库的时间大概是「10:40」,那我们就以这个时间点为参考,找前后 5 分钟的日志
mysqlbinlog -v --start-datetime='2021-06-10 10:35:00' --stop-datetime='2021-06-10 10:45:00' bin-log.000004 | grep t_user
日志大概是这个样子,@1代表库中第一个字段,@2则代表第二个,以此类推
找到后,就可以把它转成log日志下载下来了
mysqlbinlog -v --start-datetime='2021-06-10 10:35:00' --stop-datetime='2021-06-10 10:45:00' bin-log.000004 > tmp.log
到这里不也就简单很多了,删除的所有数据都有,只需要用把内容部分替换一下变成insert语句即可,可以参考我这里的替换
把第一排和最后一排改一下,就变成了可执行的语句
总结:到这里也就结束了,最重要的还是需要做好足够的安全措施,保护数据不收影响.比如定时备份,部署双机,主从,人员的权限管理等待.也希望永远用不到.更多具体的内容参考文章顶部的参考文章,里面大佬们介绍的更详细