乐趣区

关于mysql:万答5binlog解析出来的日志为何无法恢复

欢送来到 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 affected
Records: 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 公布!

退出移动版