面向猴子编程 错删表数据的修复方案

引文

人生在世,难免有手滑的时候。没有悄悄咪咪删过表数据的程序员的人生,一定是不完美的。特别是连续加班后,带着昏沉沉的大脑,难免会一个不留神,写下了罪恶的foreach remove语句。满怀信心的一看数据库。啪,快乐没有了!表数据因为不合适的查询条件,进行了全表数据删除的操作!
此时的你一定万分慌张,甚至已经收拾好行李,准备下一秒就提着桶跑路了!
为什么要跑路呢?因为你不知道接下来该如何处理,只能依靠工具猴最原始的自我保护机制,驱使自己前进。
除了跑路,我们还能做些什么呢?!别慌,下面就来讲讲遇到这种情况,我们该如何从容应对。

MysqlBinLog

全文的数据修复基础在于mysql的binlog功能,所以下文会从binlog的原理、使用等几点方面来介绍如何进行数据修复。

什么是MysqlBinLog

binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。

binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但你可以通过查询通用日志来查看MySQL执行过的所有语句。

binlog可以用于记录mysql的数据变更,数据在恢复的时候binlog日志能起到很大的作用。mysql的主从复制就是利用的binlog原理。

检查MysqlBinLog功能是否开启

因为一切基于binlog日志,所以binlog日志必须处于开启状态下,才会记录开启之后的表结构变更和表数据修改。如果你删数据后发现binlog日志没开且正好又是生产环境,那恭喜你,你基本只能跑路了!

查看

登录mysql后执行以下语句show variables like 'log_%';
面向猴子编程 错删表数据的修复方案_第1张图片

从中我们可以看出,binlog并没有处于开启阶段。

开启

查看my.cnf路径

如果不知道位置,可以执行以下命令/usr/local/mysql/bin/mysql --help --verbose | grep my.cnf
在这里插入图片描述

/etc 新建文件my.cnf并添加如下内容

[mysqld]
# log_bin
log-bin = mysql-bin #开启binloglc
binlog-format = ROW #选择row模式
server_id = 1 #配置mysql replication需要定义,不能和canal的slaveId重复

my.cnf文件追加644权限,sudo chmod 644 my.cnf

如果追加777权限,会报以下问题导致无法读取配置
面向猴子编程 错删表数据的修复方案_第2张图片

重启mysql后再次查询

面向猴子编程 错删表数据的修复方案_第3张图片

此时已经将binlog打开了~~

查看binlog文件

查看flashback工具是否安装

mysql默认使用mysqlbinlog作为flashback工具,你可以进入以下路径查看是否已经安装

/usr/local/mysql/bin/

可以通过以下命令来查看binlog数据,前提是你的mysql必须已经安装了mysqlbinlog(通常是自带的)
面向猴子编程 错删表数据的修复方案_第4张图片

查看binlog文件

通过执行以下命令,可以查看binlog里已经记录的操作

/usr/local/mysql/bin/mysqlbinlog -vv mysql-bin.004777

面向猴子编程 错删表数据的修复方案_第5张图片

参数解释

end_log_pos 表示binlog中的命令位置
table_map 代表操作的库和对应的表
Delete_rows: table id 129 flags: STMT_END_F 代表记录的具体操作,其中Delete可以是Update或者Write等

当然我们还可以通过mysqlbinlog自带的命令对数据进行定位查询,可以追加以下参数

–start-position=849196 代表起始位置,其中的数值就是上文中的end_log_pos
–stop-position=1526352 代表最终位置,其中的数值就是上文中的end_log_pos
–start-datetime=“2015-06-28 8:45:00”
–start-datetime=“2015-06-28 10:10:00”

此时的命令可以变为:

/usr/local/mysql/bin/mysqlbinlog --start-position=849196 --stop-position=1526352 -vv mysql-bin.004777

通过以上方式你就可以从binlog中找到在某段时间的具体操作了~~

当然,你还可以通过/usr/local/mysql/bin/mysqlbinlog命令获取支持的其他操作!

其他

查找出来的数据你可以通过管道grep的方式对数据进行进一步的筛选~~这里就不做说明了~

修复数据

通过以上的查询,你可以在binlog中定位出自己需要rollback的数据的位置了。但是光光这样还是不够的,在实际操作中,还有一些鲜为人知的坑,下面针对这些坑进行说明。

回滚命令

binlog的操作回滚命令为:

./mysqlbinlog -B -T goods_sku  --start-position=849196 --stop-position=1526754 mysql-bin.004777 | mysql -h 127.0.0.1 -u root -p

参数解释

-B 代表进行flashback操作
-T 代表具体回滚操作的数据表
–start-position 回滚的开始位置
–end-position 回滚的结束位置
mysql -h 127.0.0.1 -u root -p 将数据回滚的目标数据库

回滚前准备

并不是所有的mysqlbinlog都支持回滚操作的,因为mysqlbinlog分为多个版本,部分版本不支持-B命令,所以,这时候我们要通过/usr/local/mysql/bin/mysqlbinlog来查询mysqlbinlog工具是否满足flashback操作。
面向猴子编程 错删表数据的修复方案_第6张图片

只有支持的命令中包含-B操作指令,才能进行flashback回滚~~~

当然,如果你服务器上面的mysqlbinlog不支持-B操作命令,那又该怎么处理呢?

本人因为苦搜全网没有找到正确的mysqlbinlog工具,于是乎从同事的机子上将支持-B命令的mysqlbinlog.bin文件对本地的进行了替换,临时解决了上述问题。
不支持在 Docs 外粘贴 block

执行回滚命令

好了,mysqlbinlog准备好了,接下来就可以开开心心执行命令等待数据恢复了?不,你不可以!在执行过程中可能会遇到以下常见问题:
在这里插入图片描述

之所以报这个问题,是因为mysql中缺少check_constraint_checks这个系统参数!而这个参数,是mariaDB独有的!

我们可以通过以下命令查看是否含有check_constraint_checks参数

show global variables LIKE "%system%"

面向猴子编程 错删表数据的修复方案_第7张图片

很显然,目前的系统中并没有对应的参数。

缺少参数的解决方案

目前的解决方案是通过docker去下载一个mariaDB,通过将mariaDB作为目标数据库,来规避这个问题。

后记

在回滚的过程中还可能碰到其他奇奇怪怪的问题,比如会报缺少相关主键等问题~
因为回滚操作是从后往前进行逆向执行的,所以有时候遇到write指令的时候会导致报主键不存在的错误,这时候就需要好好分析binlog文件,制定相应回滚策略。
当一切都准备妥当了大家都可以不用跑路了安安心心恢复数据,快快乐乐继续当打工人了!

追记

研究了一下binlog2sql这个工具,是大众点评开源的一款用于解析binlog的工具。
官网地址如下:
https://github.com/danfengcao/binlog2sql

使用方法很简单,就如同官网介绍的一样,执行这两个命令就能安装了。

git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
pip install -r requirements.txt

但是安装过程中可能会遇到一些问题,比如pip命令不存在。

这时候你可以通过以下几个方式进行排查

  • 首先,通过python -V 命令查看当前python版本,如果版本过低,建议更新成最新的版本。
  • 如果是使用brew进行安装的,就涉及到python版本切换的问题。下面介绍如何切换版本。

Brew下python版本切换

  1. 使用brew install python安装最新版本的python
  2. 编辑./bash_profile文件,追加以下环境变量
export PATH="/usr/local/Cellar/[email protected]/3.9.4/bin:${PATH}"
alias python="/usr/local/Cellar/[email protected]/3.9.4/bin/python3.9"
alias pip="/usr/local/Cellar/[email protected]/3.9.4/bin/pip3"
  1. 执行source .bash_profile使环境变量生效
  2. 通过python -V命令查看当前版本是否切换成功

执行命令,解析binlog,生成sql

通过执行以下命令,可以正向的生成binlog中所记录的sql

python /Users/apple/code/binlog2sql/binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uroot -p root  -d tg_common -t goods_sku --start-file=mysql-bin.000004

注意,其中的/Users/apple/code/binlog2sql/binlog2sql/binlog2sql.py需要根据binlog2sql的git clone路径进行配置
执行结果如下:
面向猴子编程 错删表数据的修复方案_第8张图片

执行命令,解析binlog,生成反向sql

反向sql生成命令和正向的差不多,就是多了一个-B的指令

python /Users/apple/code/binlog2sql/binlog2sql/binlog2sql.py -h127.0.0.1 -P3306 -uroot -p root  -d tg_common -t goods_sku --start-file=mysql-bin.000004 -B

执行结果如下:
在这里插入图片描述

可以发现,执行的正好是上面的逆sql(表结构相关命令不生成逆向sql)

一些坑

官网对于可执行的binlog文件有这样一段描述
在这里插入图片描述

正如官网描述的一样,在实际操作中我们发现,无法执行其他路径的binlog文件。
此外,就算把来自外部的binlog文件移动到当前mysql的binlog文件路径下,依旧会报以下错误
在这里插入图片描述

即使使用外部文件将当前myql下的binlog文件进行同名替换,依旧会报以下错误
面向猴子编程 错删表数据的修复方案_第9张图片

所以,不建议使用binlog2sql这个工具去解析外部binlog文件

你可能感兴趣的:(面向猴子编程)