数据是古代大小厂的重要资产,爱护和复原数据成为了重要的技能,
最近几年,常有一些无良程序员删库跑路的状况,不仅给所在企业更是给本人造成重大的损失。
另外,即便不是故意的状况下,也会因为忽略造成数据误操作,是一件及麻烦又头疼的事件……
神器出场
最近的一个我的项目里,客户数据因为保护不当,导致数据失落,为了挽回数据,并建设一个跨网闸(外部组网之间不通,无奈应用 MySql 主从同步)的数据备份机制,发现了一个神器 binlog2sql。
钻研了一番之后,不仅复原了误操作失落的数据,还通过 binlog2sql 将主服务器上的 binlog 转化为 SQL 语句,存入文件,实现了数据同步!
装置
binlog2sql 应用 Python 开发,所以须要 Python 环境
将 binlog2sql 用 git 克隆的本地,GitHub 上的地址是: https://github.com/danfengcao…
git clone https://github.com/danfengcao…
通过 binlog2sql 指标下的 requirements.txt 装置依赖包
pip install -r requirements.txt
一切顺利的话,很快就可实现装置。
命令行进入 binlog2sql 代码目录下测试一下
> python binlog2sql.py
usage: binlog2sql.py [-h HOST] [-u USER] [-p [PASSWORD ...]] [-P PORT] [--start-file START_FILE] [--start-position START_POS] [--stop-file END_FILE] [--stop-position END_POS]
[--start-datetime START_TIME] [--stop-datetime STOP_TIME] [--save-as SAVE_AS] [--stop-never] [--help] [-d [DATABASES ...]] [-t [TABLES ...]] [--only-dml]
[--sql-type [SQL_TYPE ...]] [-K] [-B] [--back-interval BACK_INTERVAL]
Parse MySQL binlog to SQL you want
...< 省略 >...
因为没加任何参数,所以打印出应用阐明,那阐明装置失常了。
简介
binlog2sql 是通过剖析 MySql 数据库的 binlog 文件,从中解析出须要执行的 sql 语句的。
那么应用时须要提供一些必要的参数,其中重要的有数据库服务器链接信息,须要剖析的 binlog 文件名等,
还能够指定解析的起始和完结地位,以及开始和完结工夫。
身手不凡
是骡子是马拉进去溜溜。
复原被删数据
如果库表 tb_user 中的数据如下:
+----+--------+---------------------+
| id | name | createtime |
+----+--------+---------------------+
| 1 | 张三 | 2021-01-10 00:04:33 |
| 2 | 李四 | 2021-01-10 00:04:48 |
| 3 | 王五 | 2021-04-23 20:25:00 |
| 4 | 赵六 | 2021-06-04 11:21:23 |
+----+--------+---------------------+
这时不小心执行了一个删操作,将数据误删了
delete from tb_user
如何复原呢?
咱们看一下数据库的日志状况
show master status;
会看到相似这样的后果
+------------------+-----------+
| File | Position |
+------------------+-----------+
| mysql-bin.000002 | 13136 |
+------------------+-----------+
留神:只有 MySql 数据库关上了日志记录性能,能力查问到
能够看出,目前日志记录在文件 mysql-bin.000002 中,以后最新的记录地位是 12546 行
如果过后误操作的工夫是上午 11 点半左右(可能焦急吃饭,没留神),那么预估一个工夫范畴,比方 11 点 25 到 11 点 35,看看一下过后的操作:
python binlog2sql -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t tb_user --start-file='mysql-bin.000002' --start-datetime='2021-06-04 11:25:00' --stop-datetime='2021-06-04 11:35:00'
输入为:
INSERT INTO `test`.`tb_user`(`createtime`, `id`, `name`) VALUES ('2021-06-04 11:21:23', 4, '李四'); #start 12317 end 12487 time 2021-06-04 11:21:23
DELETE FROM `test`.`tb_user` WHERE `createtime`='2021-01-10 00:04:33' AND `id`=1 AND `name`='张三' LIMIT 1; #start 12728 end 12829 time 2021-06-04 11:27:32
DELETE FROM `test`.`tb_user` WHERE `createtime`='2021-01-10 00:04:48' AND `id`=2 AND `name`='李四' LIMIT 1; #start 12728 end 12829 time 2021-06-04 11:27:32
DELETE FROM `test`.`tb_user` WHERE `createtime`='2021-04-23 20:25:00' AND `id`=3 AND `name`='王五' LIMIT 1; #start 12728 end 12829 time 2021-06-04 11:27:32
DELETE FROM `test`.`tb_user` WHERE `createtime`='2021-06-04 11:21:23' AND `id`=4 AND `name`='赵六' LIMIT 1; #start 12728 end 12829 time 2021-06-04 11:27:32
能够看出,第二行开始到第五行为删除语句,查看语句最初的起始和完结地位 start 12728 end 12829
即 binlog 中,删除执行的地位在 12728-12829 之间,于是锁定准确地位,生成回滚语句:
python binlog2sql -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t tb_user --start-file='mysql-bin.000002' --start-position=12728 --stop-position=12829 -B
留神参数 -B,意思是生成回滚 SQL,即生成的是撤销之前操作的语句
输入为:
INSERT INTO `test`.`tb_user`(`createtime`, `id`, `name`) VALUES ('2021-06-04 11:21:23', 4, '赵六'); #start 12728 end 12829 time 2016-12-13 20:28:05
INSERT INTO `test`.`tb_user`(`createtime`, `id`, `name`) VALUES ('2021-04-23 20:25:00', 3, '王五'); #start 12728 end 12829 time 2016-12-13 20:28:05
INSERT INTO `test`.`tb_user`(`createtime`, `id`, `name`) VALUES ('2021-01-10 00:04:48', 2, '李四'); #start 12728 end 12829 time 2016-12-13 20:28:05
INSERT INTO `test`.`tb_user`(`createtime`, `id`, `name`) VALUES ('2021-01-10 00:04:33', 1, '张三'); #start 12728 end 12829 time 2016-12-13 20:28:05
从输入的语句来看,程序是删除的倒序,而且曾经将原来的 delete 语句改为了 insert 语句,也就是原来操作的逆操作
如果确认语句没问题,执行生成的语句就能够了
是不是既不便又高效呢?
解析 SQL
binlog2sql 功能强大,应用起来也很不便,看看其余性能吧。
作为一个命令行工具,性能都体现在参数里,可分为 解析模式、解析指标、解析范畴三局部。
解析模式
binlog2sql 反对两个解析模式,默认的是单次解析,即运行一次解析一次,
还能够反对继续解析,即不间断地从指标数据库地 binlog 中解析出 sql 来,继续解析通过参数 –never-stop 开启,
开启之后,线程不会退出,始终处于运行状态,会主动判断 binlog 的变动,对变动局部增量式解析。
这种模式能够用于数据库同步,不过生产上应用前,最好思考各种异常情况,比方重启,网络中断等状况。
参数 -K 或 –no-primany-key 示意的去除 INSERT 语句中的主键,这个在数据汇总的场景下很不便,能够防止多个数据源中主键抵触的问题。
参数 -B 或 –flashback,示意回滚模式,在下面的例子中展现过,即会解析成逆操作的 sql 语句。
在回滚模式下,每生成一千条 SQL 语句会加一个 SLEEP 语句,是为免得数据执行时产生拥挤,默认为 1 秒,能够通过 –back-interval 参数来设置,
例如 –back-interval 2 示意暂停 2 秒。
解析指标
MySql 设置 binlog 时能够指定记录哪个库,以及哪些表,即指标。
那么用 binlog2sql 也能够指定解析指标。
参数 -d 或 –databases 用于指定数据库,如果多个库,用空格分隔,例如 -d db1 db2;
参数 -t 或 –tables 用于指定库表,多个库表用空格分隔,例如 -t tb1 tb2。
如果指定解析指标不仅效率更高,而且剖析和执行解析的后果也更不便。
解析范畴
范畴包含 binlog 文件范畴,工夫范畴 以及 行范畴,例如后面例子中用到了 工夫范畴 和 行范畴。
文件范畴 用 –start-file 和 –stop-file 参数来指定,只须要提供 binlog 文件名即可,不须要写全门路,这是因为,binlog2sql 会主动依据指标服务器配置读取 binlog 文件;
工夫范畴 用 –start-datetime 和 –stop-datetime 参数来指定,工夫格局为 %Y-%m-%d %H:%M:%S;
行范畴 用 –start-position 和 –stop-position 参数来指定,也能够简写为 –start-pos 和 –end-pos。
深刻理解
binlog2sql 不仅是一个实用的工具,而且也是个钻研和学习的好例子。
只有不到 500 行代码,很容易浏览;
浏览源码,不仅能深刻理解其实现原理,而且还能够学习到很多好用法。
实现原理
binlog2sql 的原理是,利用 pymysql 从指标服务器上获取 binlog 信息,而后锁定范畴,应用 pymysqlreplication 解析 binlog 文件,最初,失去须要解析出的 sql 语句。
在这根底上,做了一些功能性扩大,比方解析范畴,解析模式等,相对来说比较简单,很容易看懂。
命令行参数
编程时解决命令行参数是机械而繁琐的,特地是有不同性质的性质和别名的参数
binlog2sql 中利用了 argparse 模块,
argparse 模块能够让人轻松编写用户敌对的命令行接口。程序定义它须要的参数,argparse 能够从 sys.argv 解析出提供的命令行参数。而且 argparse 模块还会主动生成帮忙和使用手册,并在用户给程序传入有效参数时报出错误信息。
很容易就能编程高大上的命令行程序接口,再也不必为很 low 的程序接口发愁了。
文件解决上下文(context)
binlog2sql 在回滚模式(即提供了参数 -B)中,应用了一个临时文件记录解析进去的 SQL 语句,并且在实现之后删除。
一般来说,在实现后被动删除文件即可,不过如果能利用 with 块的资源回收性能就更好了。
查看源码,会看到一个创立文件写法:
@contextmanager
def temp_open(filename, mode):
f = open(filename, mode)
try:
yield f
finally:
f.close()
os.remove(filename)
@contextmanager 指示器能够将一个生成器,作为一个上下文管理器,
那么:
with 申明局部,会执行前会执行 yield 语句之前的局部
with 范畴内,会执行 yield 语句,即返回一个须要后续解决的对象,比方文件,后续解决是敞开
with 执行实现前,会执行 yield 语句之后的代码
那么这段代码的意义就是,当文件应用实现后,敞开文件,并且删除掉。
应用形式为:
with temp_open(tmp_file, "w") as f_tmp
...
f_tmp.write(sql + '\n')
...
这样无论如何只有 with 块执行完,文件就会被删除,不必放心遗记,是不是很优雅?
除了这两点,还有很多值得把玩的中央,有趣味的话能够读读源码。
总结
无论是什么工具,都须要有肯定的根底和良好的习惯上才会发挥作用,比方得开启 MySql 的 binlog 日志,并由记录工作的习惯。
同时,任何工具办法都有它的特点,能够在理解性能的同时,钻研一下其应用原理,是一个很好的技能晋升机会。
很多人在埋怨,没有利用场景,没有理论我的项目,其实钻研这些工具,就会有事倍功半的成果。
以上就是本次分享的所有内容,想要理解更多 python 常识欢送返回公众号:Python 编程学习圈,每日干货分享