MySQL还原备份方法3----gtid

3.gtid

GTID(全局事务标识符)是 MySQL 给每个事务发的唯一身份证号,用于主从复制和基于 binlog 的数据恢复。

核心组成

复制代码
GTID = 服务器UUID : 事务序号

示例:9e1669b5-2a59-11f1-a260-000c295e8e85:1-7
       └───────── UUID ─────────┘ └─┘
              服务器唯一标识      第7个事务

主要用途

场景 说明
主从复制 从库根据 GTID 自动知道哪些事务已执行,不会重复
故障恢复 从 binlog 中提取指定范围的事务进行恢复
数据追踪 通过 GTID 精确定位每个事务

3.1开启GTID服务

bash 复制代码
mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | OFF       |    #
| gtid_executed                    |           |
| gtid_executed_compression_period | 0         |
| gtid_mode                        | OFF       |	#
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+

enforce_gtid_consistency 和 gtid_mode 要为ON

bash 复制代码
[root@bogon ~]# vim /etc/my.cnf
[root@bogon ~]# tail -4 /etc/my.cnf 
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce-gtid-consistency=ON

[root@bogon mysql]# systemctl start mysqld

mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |
| gtid_executed                    |           |
| gtid_executed_compression_period | 0         |
| gtid_mode                        | ON        |
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+

3.2创建数据

bash 复制代码
mysql> show binary log status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      158 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

#关于数据库db3
mysql> create database db3;
Query OK, 1 row affected (0.01 sec)

mysql> show binary log status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000001 |      340 |              |                  | 9e1669b5-2a59-11f1-a260-000c295e8e85:1 |
+------------------+----------+--------------+------------------+----------------------------------------+
1 row in set (0.00 sec)

#关于数据库gtid
mysql> create database gtid;
Query OK, 1 row affected (0.01 sec)

mysql> use gtid;
Database changed
mysql> 
mysql> create table t1(id int);
Query OK, 0 rows affected (0.02 sec)


mysql> show binary log status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000001 |      713 |              |                  | 9e1669b5-2a59-11f1-a260-000c295e8e85:1-3 |
+------------------+----------+--------------+------------------+------------------------------------------+




mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql>  insert into t1 values(2);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> show binary log status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000001 |     1074 |              |                  | 9e1669b5-2a59-11f1-a260-000c295e8e85:1-4 |
+------------------+----------+--------------+------------------+------------------------------------------+


mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000001';
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+
| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                                              |
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+
| mysql-bin.000001 |    4 | Format_desc    |         1 |         127 | Server ver: 8.4.8, Binlog ver: 4                                  |
| mysql-bin.000001 |  127 | Previous_gtids |         1 |         158 |                                                                   |
| mysql-bin.000001 |  158 | Gtid           |         1 |         235 | SET @@SESSION.GTID_NEXT= '9e1669b5-2a59-11f1-a260-000c295e8e85:1' |
| mysql-bin.000001 |  235 | Query          |         1 |         340 | create database db3 /* xid=6 */                                   |
| mysql-bin.000001 |  340 | Gtid           |         1 |         417 | SET @@SESSION.GTID_NEXT= '9e1669b5-2a59-11f1-a260-000c295e8e85:2' |
| mysql-bin.000001 |  417 | Query          |         1 |         525 | create database gtid /* xid=8 */                                  |
| mysql-bin.000001 |  525 | Gtid           |         1 |         602 | SET @@SESSION.GTID_NEXT= '9e1669b5-2a59-11f1-a260-000c295e8e85:3' |
| mysql-bin.000001 |  602 | Query          |         1 |         713 | use `gtid`; create table t1(id int) /* xid=13 */                  |
| mysql-bin.000001 |  713 | Gtid           |         1 |         792 | SET @@SESSION.GTID_NEXT= '9e1669b5-2a59-11f1-a260-000c295e8e85:4' |
| mysql-bin.000001 |  792 | Query          |         1 |         867 | BEGIN                                                             |
| mysql-bin.000001 |  867 | Table_map      |         1 |         915 | table_id: 92 (gtid.t1)                                            |
| mysql-bin.000001 |  915 | Write_rows     |         1 |         955 | table_id: 92 flags: STMT_END_F                                    |
| mysql-bin.000001 |  955 | Table_map      |         1 |        1003 | table_id: 92 (gtid.t1)                                            |
| mysql-bin.000001 | 1003 | Write_rows     |         1 |        1043 | table_id: 92 flags: STMT_END_F                                    |
| mysql-bin.000001 | 1043 | Xid            |         1 |        1074 | COMMIT /* xid=16 */                                               |
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+



mysql> create table t2(id int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t2 values (2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values (3);
Query OK, 1 row affected (0.00 sec)

mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)

mysql> show binary log status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000002 |      198 |              |                  | 9e1669b5-2a59-11f1-a260-000c295e8e85:1-7 |
+------------------+----------+--------------+------------------+------------------------------------------+

主要关注File 和 Executed_Gtid_Set 这个部分

eg.

File:mysql-bin.000002

Executed_Gtid_Set:9e1669b5-2a59-11f1-a260-000c295e8e85:1-7

​ mysql-bin.000002是二进制日志文件编号

​ 9e1669b5-2a59-11f1-a260-000c295e8e85这台 MySQL 的唯一身份证号

​ 这里的1-7表示:这个 MySQL 上已经执行了 7 个 GTID 事务,编号从 1 到 7

3.3模拟数据破坏

bash 复制代码
mysql> drop database gtid;
Query OK, 2 rows affected (0.03 sec)
mysql> drop database gtid;
Query OK, 2 rows affected (0.03 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| db3                |
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| school             |
| sys                |
+--------------------+
7 rows in set (0.00 sec)

3.4还原数据 & 检验

1.确定gtid

2.确定要++还原的数据++的 gtid事务 的起始和结束编号。

3.涉及到的日志文件
上一步是删除了gtid数据库。。。所以还原这个部分

gtid:9e1669b5-2a59-11f1-a260-000c295e8e85

该数据库的gtid事务 的起始和结束编号:2-7

涉及到的日志文件:mysql-bin.000001和mysql-bin.000002

bash 复制代码
[root@bogon ~]# cd /var/lib/mysql

#这个是2-7
[root@bogon mysql]#  mysqlbinlog --include-gtids='9e1669b5-2a59-11f1-a260-000c295e8e85:2-7' mysql-bin.000001 mysql-bin.000002 -r /tmp/gtid2.sql

#这个1-7错误(包含了db3,而db3还存在),用来测试的
[root@bogon mysql]#  mysqlbinlog --include-gtids='9e1669b5-2a59-11f1-a260-000c295e8e85:1-7' mysql-bin.000001 mysql-bin.000002 -r /tmp/gtid1.sql
 
 #--skip-gtids参数
[root@bogon mysql]#  mysqlbinlog --skip-gtids --include-gtids='9e1669b5-2a59-11f1-a260-000c295e8e85:1-7' mysql-bin.000001 mysql-bin.000002 -r /tmp/gtid3.sql
bash 复制代码
#用gtid1.sql
mysql>  set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /tmp/gtid1.sql;
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show databases like 'gtid';
Empty set (0.00 sec)

#用gtid2.sql
mysql>  set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /tmp/gtid2.sql;
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show databases like 'gtid';
Empty set (0.00 sec)

#用gtid3.sql
mysql>  set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /tmp/gtid3.sql;
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show databases like 'gtid';
+-----------------+
| Database (gtid) |
+-----------------+
| gtid            |
+-----------------+
mysql> select * from  gtid.t2;
+------+
| id   |
+------+
|    2 |
|    3 |
+------+

Q:why用用gtid2.sql不行???

删除后,创建 gtid 库和表数据相当于"没执行过",应该能重放

但 GTID 机制不这么认为,它只管"有没有执行过",不管"结果还在不在"。

所以恢复时必须用 --skip-gtids 撕掉标签,强制重放。

这不是 GTID 没用,而是它本来就不是为"误删恢复"这个场景设计的

不加 --skip-gtids:MySQL 一看 GTID 编号已经执行过,直接跳过,不恢复。
--skip-gtids:把 GTID 编号撕掉,MySQL 当作新事务,正常执行恢复。


你的实验对应关系

文件 加没加 --skip-gtids 结果 原因
gtid1.sql ❌ 没加 失败 GTID 1-7 全被跳过
gtid2.sql ❌ 没加 失败 GTID 2-7 全被跳过
gtid3.sql ✅ 加了 成功 GTID 被移除,正常执行

记住这一条规则

从 binlog 恢复误删数据时,永远加 --skip-gtids

GTID幂等性

GTID 幂等性是给主从复制设计的,防止重复执行;误删恢复时一定要加 --skip-gtids,绕过幂等性检查。

MySQL 有一个系统变量 gtid_executed,记录着所有已经执行过的 GTID 编号

当一个事务进来时:

  1. MySQL 检查它的 GTID 编号
  2. gtid_executed 里查找
  3. 找到了 → 直接跳过(保证不重复执行)
  4. 没找到 → 正常执行

这就是幂等性的来源:同一个 GTID 的事务,执行多次和一次的效果一样(不会重复执行)

相关推荐
chatexcel2 小时前
【实战教程】ChatDB 入门:基于自然语言的无 SQL 数据库操作实践
数据库·sql·oracle
黑金IT2 小时前
从“视觉断言”到“自动化指挥”:Qwen3-V2 如何终结 AI 的随机性
运维·人工智能·自动化
.select.2 小时前
TCP 6(重传机制)
linux·服务器·tcp/ip
胡单纯2 小时前
AI 直接解析 PDF 文档!OpenClaw 2026.3.3 新功能实测太强了
数据库·人工智能·pdf
大卡片2 小时前
IO缓存区
linux·运维·缓存
志栋智能2 小时前
超自动化巡检:洞察未知隐患,助您事前不出事
大数据·运维·网络·数据库·自动化
杼蛘2 小时前
Kali下载与简单使用/MariaDB安装/Docker安装/MySQL镜像安装
mysql·docker·kali·mariadb
出海干货炒鱿鱼2 小时前
IP大科普:住宅IP、机房IP、原生IP、双ISP
运维·服务器
somi72 小时前
ARM-驱动-03 Linux 字符设备驱动开发
linux·arm开发·驱动开发·自用