欢送来到 GreatSQL社区分享的MySQL技术文章,如有疑难或想学习的内容,能够在下方评论区留言,看到后会进行解答
问题形容
问题来自一位群友,简略说就是用 mysqlbinlog 工具读取 binlog 欲进行复原,却发现数据并没被复原。
先一起来看下他是怎么做复原的。
表中原来有几条数据,但不小心被清空了:
[yejr]> select * from t1;+----+| c1 |+----+| 1 || 2 || 3 || 4 |+----+
查看binlog event,有几条插入数据,最初还有一条 truncate table 的"误操作",当初想要把表数据恢复到误删数据前的状态。
[yejr]> show binlog events in 'binlog.000003';+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+| binlog.000003 | 4 | Format_desc | 3306 | 125 | Server ver: 8.0.25-15, Binlog ver: 4 || binlog.000003 | 125 | Previous_gtids | 3306 | 196 | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:1-5 || binlog.000003 | 196 | Gtid | 3306 | 282 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:6' || binlog.000003 | 282 | Query | 3306 | 358 | BEGIN || binlog.000003 | 358 | Rows_query | 3306 | 405 | # insert into t1 select 1 || binlog.000003 | 405 | Table_map | 3306 | 454 | table_id: 91 (yejr.t1) || binlog.000003 | 454 | Write_rows | 3306 | 494 | table_id: 91 flags: STMT_END_F || binlog.000003 | 494 | Xid | 3306 | 525 | COMMIT /* xid=75 */ || binlog.000003 | 525 | Gtid | 3306 | 611 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:7' || binlog.000003 | 611 | Query | 3306 | 687 | BEGIN || binlog.000003 | 687 | Rows_query | 3306 | 734 | # insert into t1 select 2 || binlog.000003 | 734 | Table_map | 3306 | 783 | table_id: 91 (yejr.t1) || binlog.000003 | 783 | Write_rows | 3306 | 823 | table_id: 91 flags: STMT_END_F || binlog.000003 | 823 | Xid | 3306 | 854 | COMMIT /* xid=76 */ || binlog.000003 | 854 | Gtid | 3306 | 940 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:8' || binlog.000003 | 940 | Query | 3306 | 1016 | BEGIN || binlog.000003 | 1016 | Rows_query | 3306 | 1063 | # insert into t1 select 3 || binlog.000003 | 1063 | Table_map | 3306 | 1112 | table_id: 91 (yejr.t1) || binlog.000003 | 1112 | Write_rows | 3306 | 1152 | table_id: 91 flags: STMT_END_F || binlog.000003 | 1152 | Xid | 3306 | 1183 | COMMIT /* xid=77 */ || binlog.000003 | 1183 | Gtid | 3306 | 1269 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:9' || binlog.000003 | 1269 | Query | 3306 | 1345 | BEGIN || binlog.000003 | 1345 | Rows_query | 3306 | 1392 | # insert into t1 select 4 || binlog.000003 | 1392 | Table_map | 3306 | 1441 | table_id: 91 (yejr.t1) || binlog.000003 | 1441 | Write_rows | 3306 | 1481 | table_id: 91 flags: STMT_END_F || binlog.000003 | 1481 | Xid | 3306 | 1512 | COMMIT /* xid=78 */ || binlog.000003 | 1512 | Gtid | 3306 | 1596 | SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:10' || binlog.000003 | 1596 | Query | 3306 | 1693 | use `yejr`; truncate table t1 /* xid=87 */ |
运行上面的命令想要进行复原数据,但发现不能正确复原:
$ mysqlbinlog --start-position=4 --stop-position=1512 binlog.000003 | mysql -f yejr
曾经指定了读取binlog的地位是从4开始,到1512截止,因为再下一个event就是"误操作"了。之后查问 yejr.t1 表数据还是空的,没有被正确复原。
问题解决
首先再次强调线上操作要十分审慎,如果只是一般的DML操作,倡议当时关上事务模式,这样万一误操作了还能执行 rollback 回滚。
但如果是DDL操作,则基本上只能依赖备份或者提早从库,所以务必再三确认是在测试环境还是线上环境,以及行将执行的命令影响如何。
再回到问题自身。
在执行 mysqlbinlog 解析binlog并尝试复原时,察看新的binlog,确认没有写入新数据,阐明的确没执行复原操作。
解析binlog查看,并没有相似 SET SQL_LOG_BIN=0 等疏忽binlog的设置,而如果复制SQL指令执行进去手动执行,却是能够胜利的。阐明binlog自身没问题,是其余起因导致的。
再查看 binlog event 时留神到启用了 GTID 模式,在 GTID 模式下有个特点是要求 全局惟一。
除了GTID值继续递增之外,有个不容易留神的特点是,当事务GTID在已执行过的GTID汇合(Executed_Gtid_Set)中的话,就不会再次被执行。假如以下几种场景:
假如以后Executed_Gtid_Set汇合是 1-10,如果下一个GTID是5,它在这个范畴内,则无奈被执行。
假如以后Executed_Gtid_Set汇合是 1-10, 20-30,如果下一个GTID是13,不在这个范畴内,则能够被执行。
别离做个测试:
# 查看以后gtid[yejr]> show master status;+---------------+----------+--------------+------------------+----------------------------------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+---------------+----------+--------------+------------------+----------------------------------------------+| binlog.000004 | 762 | | | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:1-15:20 |+---------------+----------+--------------+------------------+----------------------------------------------+# 下一个GTID在范畴内,不会被执行[yejr]> set session gtid_next='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:13';[yejr]> insert into t1 select 6;Query OK, 0 rows affected (0.00 sec) #<-- 0 rows# 下一个GTID不在范畴内,会被执行[yejr]> set session gtid_next='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:17';[yejr]> insert into t1 select 6;Query OK, 1 row affected (0.01 sec) #<-- 1 row affectedRecords: 1 Duplicates: 0 Warnings: 0# 再次查看gtid[yejr]> show master status;+---------------+----------+--------------+------------------+-------------------------------------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+---------------+----------+--------------+------------------+-------------------------------------------------+| binlog.000004 | 1091 | | | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1:1-15:17:20 |+---------------+----------+--------------+------------------+-------------------------------------------------+
验证后果的确如上所说。
晓得起因就好办了,查看 mysqlbinlog 的帮忙文档,查看选项 --skip-gtids 的解释:
--skip-gtids Do not preserve Global Transaction Identifiers; instead make the server execute the transactions as if they were new.
它能够使得解析进去的binlog event不再保留原来的 GTID 信息,这就能够当成新的 event 被执行了。所以,如果想要从binlog复原数据,执行mysqlbinlog时,记得加上 --skip-gtids 选项。
全文完。
Enjoy MySQL :)
文章举荐:
GreatSQL MGR FAQ
https://mp.weixin.qq.com/s/J6...
万答#12,MGR整个集群挂掉后,如何能力主动选主,不必手动干涉
https://mp.weixin.qq.com/s/07...
『2021数据技术嘉年华·ON LINE』:《MySQL高可用架构演进及实际》
https://mp.weixin.qq.com/s/u7...
一条sql语句慢在哪之抓包剖析
https://mp.weixin.qq.com/s/AY...
万答#15,都有哪些状况可能导致MGR服务无奈启动
https://mp.weixin.qq.com/s/in...
技术分享 | 为什么MGR一致性模式不举荐AFTER
https://mp.weixin.qq.com/s/rN...
对于 GreatSQL
GreatSQL是由万里数据库保护的MySQL分支,专一于晋升MGR可靠性及性能,反对InnoDB并行查问个性,是实用于金融级利用的MySQL分支版本。
Gitee:
https://gitee.com/GreatSQL/Gr...
GitHub:
https://github.com/GreatSQL/G...
Bilibili:
https://space.bilibili.com/13...
微信&QQ群:
可搜寻增加GreatSQL社区助手微信好友,发送验证信息“加群”退出GreatSQL/MGR交换微信群
QQ群:533341697
微信小助手:wanlidbc
本文由博客一文多发平台 OpenWrite 公布!