欢迎来到 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/J6wkUpGXw3YkyEUJXiZ9xA

万答#12,MGR整个集群挂掉后,如何才能自动选主,不用手动干预

https://mp.weixin.qq.com/s/07o1poO44zwQIvaJNKEoPA

『2021数据技术嘉年华·ON LINE』:《MySQL高可用架构演进及实践》

https://mp.weixin.qq.com/s/u7k99y6i7riq7ScYs7ySnA

一条sql语句慢在哪之抓包分析

https://mp.weixin.qq.com/s/AYibbzl860D90rOeyjB6IQ

万答#15,都有哪些情况可能导致MGR服务无法启动

https://mp.weixin.qq.com/s/inSGpd0Q_XIl2Mb-VsvNsA

技术分享 | 为什么MGR一致性模式不推荐AFTER

https://mp.weixin.qq.com/s/rNeq479RNsklY1BlfKOsYg

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

Gitee:

https://gitee.com/GreatSQL/GreatSQL

GitHub:

https://github.com/GreatSQL/GreatSQL

Bilibili:

https://space.bilibili.com/1363850082/video

微信&QQ群:

可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群

QQ群:533341697

微信小助手:wanlidbc

本文由博客一文多发平台 OpenWrite 发布!

万答#5,binlog解析出来的日志为何无法恢复的更多相关文章

  1. #万答10:mysqldump 是如何实现一致性备份的

    万答10:mysqldump 是如何实现一致性备份的 实验场景 MySQL 8.0.25 InnoDB 实验步骤: 先开启 general_log 观察导出执行过程的变化 set global gen ...

  2. 万答#18,MySQL8.0 如何快速回收膨胀的UNDO表空间

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 背 ...

  3. MySQL Binlog解析

    https://yq.aliyun.com/articles/238364?spm=5176.8067842.tagmain.52.73PjU3 摘要: 概述 MySQL的安装可以参考:Linux(C ...

  4. MySQL Binlog 解析工具 Maxwell 详解

    maxwell 简介 Maxwell是一个能实时读取MySQL二进制日志binlog,并生成 JSON 格式的消息,作为生产者发送给 Kafka,Kinesis.RabbitMQ.Redis.Goog ...

  5. MySQL Binlog解析(1)

    一.Binlog File Binlog files start with a Binlog File Header followed by a series of Binlog Event Binl ...

  6. 万答#21,如何查看 MySQL 数据库一段时间内的连接情况

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 查看方式 已知至少有两种方式可以实现 1.开启 general_log 就可以观察到 开启命令 mysql> set ...

  7. 万答17,AWS RDS怎么搭建本地同步库

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 背景说明 AWS RDS 权限受限,使用 mysqldump 的时候无法添加 - ...

  8. 以芯片直读方式得到的全盘镜像解析及ext4日志区域解析

    之前在centos中分析了/dev/sda1下的结构,但当对象是一块以芯片直读方式作出来的全盘镜像呢? 这次以安卓手机的全盘镜像为对象,尝试按照ext4文件系统结构手动解析,加强对ext4文件系统.E ...

  9. 基于innodb_print_all_deadlocks从errorlog中解析MySQL死锁日志

    本文是说明如何获取死锁日志记录的,不是说明如何解决死锁问题的. MySQL的死锁可以通过show engine innodb status;来查看,但是show engine innodb statu ...

随机推荐

  1. 好客租房56-props深入(3props校验-约束规则)

    1常见类型:Array,bool,func,number,object,string 2React:element 3必填项:isRequred 4特定结构的想:shape({}) //导入react ...

  2. 企业应用架构研究系列二十六:信号量SemaphoreSlim与Semaphore

    在进行多线程程序的开发和设计的过程中,不可避免的需要引入semaphore信号量这个组件,这是.net框架提供的一个对多线程计数互斥的方案,就是允许指定的线程个数访问特定的资源而增加的 一个" ...

  3. 我是一个Dubbo数据包...

    hello,大家好呀,我是小楼! 今天给大家带来一篇关于Dubbo IO交互的文章,本文是一位同事写的文章,用有趣的文字把枯燥的知识点写出来,通俗易懂,非常有意思,所以迫不及待找作者授权然后分享给大家 ...

  4. CF1665A GCD vs LCM

  5. c++ 关于二分的STL 详解

    一.解释 以前遇到二分的题目都是手动实现二分,不得不说错误比较多,关于返回值,关于区间的左闭右开等很容易出错,最近做题发现直接使用STL中的二分函数方便快捷还不会出错,不过对于没有接触过的同学,二分函 ...

  6. element-ui table组件使用v-if时的问题

    element-ui项目中经常遇到需要使用v-if指令来根据情况动态显示隐藏某些列情况,这时就会出现滚动条样式异常.列错乱.列宽错乱等问题 解决办法:在el-table上添加:key="Ma ...

  7. 论文阅读 Real-Time Streaming Graph Embedding Through Local Actions 11

    9 Real-Time Streaming Graph Embedding Through Local Actions 11 link:https://scholar.google.com.sg/sc ...

  8. linux-python安装pip

    wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate sudo python3 get-pip.py linux 建立软连接 ...

  9. 强化学习-Windows安装gym、atari和box2d环境

    安装gym pip3 install gym pip3 install gym[accept-rom-license] 安装atari环境[可选] 下载安装VS build tools 如果出现 OS ...

  10. React关于constructor与super(props)之间的相爱相杀

    我们先把菜鸟教程的一段代码拿过来分析一下.下面这段代码是用了将生命周期方法添加到类中实现时钟效果. // 将生命周期方法添加到类中 class Clock extends React.Componen ...