mysql GTID复制机制
MySQL 的 GTID(Global Transaction Identifier,全局事务标识符)复制机制是 MySQL 5.6 及以上版本引入的一种高级复制功能,旨在简化主从复制的管理,提高数据一致性和故障恢复的可靠性。相比传统的基于二进制日志位置(binlog position)的复制方式,GTID 复制通过为每个事务分配一个全局唯一标识符,极大地方便了复制的配置和维护。
GTID 复制的基本原理
GTID 是一个全局唯一的事务 ID,由两部分组成:
- 服务器 UUID:每个 MySQL 实例有一个唯一的标识符,通常在服务器启动时生成,存储在
auto.cnf
文件中。 - 事务序列号:一个递增的数字,表示该服务器上的事务顺序。
GTID 的格式通常是这样的:UUID:Transaction_ID
,例如 3e11fa47-71ca-11e1-9e33-c80aa9429562:23
。
Transaction_id 是在该主库上生成的事务序列号,从1开始,1-2代表第二个事务;第1-n代表n个事务
Retrieved_Gtid_Set: 4dfe51b2-f2b7-11ef-8924-0242c0a8d704:1-5
Executed_Gtid_Set: 4a308329-f2b7-11ef-97f0-0242c0a8d703:1-2,
4dfe51b2-f2b7-11ef-8924-0242c0a8d704:1-5
4dfe51b2-f2b7-11ef-8924-0242c0a8d704:1-5
UUID: 4dfe51b2-f2b7-11ef-8924-0242c0a8d704
Transaction_ID: 1-5
在 GTID 复制中,主库(Master)上执行的每个事务都会被分配一个 GTID,并记录在二进制日志中。从库(Slave)通过读取主库的二进制日志,获取并应用这些带有 GTID 的事务。从库会跟踪已应用的 GTID 集合(gtid_executed
),从而确保不会重复执行相同的事务。
GTID 复制的工作流程
主库端:
- 每次提交事务时,主库生成一个 GTID,并将其与事务一起记录到二进制日志中。
- 二进制日志通过复制通道传输给从库。
从库端:
- 从库通过复制线程(IO 线程和 SQL 线程)读取主库的二进制日志。
- 从库检查事务的 GTID 是否已经存在于自己的
gtid_executed
集合中。 - 如果 GTID 未执行,从库应用该事务,并更新自己的 GTID 集合;如果已执行,则跳过。
一致性保障:
- GTID 确保事务在主从之间严格按照提交顺序应用,避免了传统复制中因日志位置偏移导致的不一致问题。
GTID 复制的优点
- 简化故障切换:传统复制需要手动计算日志文件和位置,而 GTID 允许从库自动定位到正确的复制点,便于主从切换。
- 数据一致性:GTID 保证事务只被应用一次,避免重复或遗漏。
- 多源复制支持:GTID 在多主复制场景中更容易管理事务来源。
- 易于监控和管理:通过
gtid_executed
和gtid_purged
等变量,可以清晰地了解复制状态。
gtid模式下binlog结构
➜ test mysqlbinlog mysql-bin.000001
# The proper term is pseudo_replica_mode, but we use this compatibility alias
# to make the statement usable on server versions 8.0.24 and older.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#250224 22:06:25 server id 3 end_log_pos 123 CRC32 0x2b74819b Start: binlog v 4, server v 5.7.44-log created 250224 22:06:25 at startup
ROLLBACK/*!*/;
BINLOG '
4Xy8Zw8DAAAAdwAAAHsAAAAAAAQANS43LjQ0LWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADhfLxnEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
AZuBdCs=
'/*!*/;
# at 123
#250224 22:06:25 server id 3 end_log_pos 154 CRC32 0x558a01da Previous-GTIDs
### 1.Previous-GTIDs代表的gtid集合是曾经的gtid,换句话说是被purge掉的事务
# [empty]
# at 154
#250224 22:10:16 server id 3 end_log_pos 219 CRC32 0xbb953763 GTID last_committed=0 sequence_number=1 rbr_only=no original_committed_timestamp=0 immediate_commit_timestamp=0 transaction_length=0
# original_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
# immediate_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
/*!80001 SET @@session.original_commit_timestamp=0*//*!*/;
/*!80014 SET @@session.original_server_version=0*//*!*/;
/*!80014 SET @@session.immediate_server_version=0*//*!*/;
SET @@SESSION.GTID_NEXT= '4dfe51b2-f2b7-11ef-8924-0242c0a8d704:1'/*!*/; ### 2.purged 事物
# at 219
#250224 22:10:16 server id 3 end_log_pos 313 CRC32 0x101009d7 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1740406216/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!80005 &~0x1003ff00*//*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
create database gaga
/*!*/;
# at 313
#250224 22:12:25 server id 3 end_log_pos 378 CRC32 0x89b3e865 GTID last_committed=1 sequence_number=2 rbr_only=no original_committed_timestamp=0 immediate_commit_timestamp=0 transaction_length=0
# original_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
# immediate_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
/*!80001 SET @@session.original_commit_timestamp=0*//*!*/;
/*!80014 SET @@session.original_server_version=0*//*!*/;
/*!80014 SET @@session.immediate_server_version=0*//*!*/;
SET @@SESSION.GTID_NEXT= '4dfe51b2-f2b7-11ef-8924-0242c0a8d704:2'/*!*/; ### 3.新的事务的gtid信息,写在每个事务的前面
# at 378
#250224 22:12:25 server id 3 end_log_pos 479 CRC32 0xde92108b Query thread_id=2 exec_time=0 error_code=0
use `gaga`/*!*/;
SET TIMESTAMP=1740406345/*!*/;
create table t2 (id int(4)) # 创建表
/*!*/;
# at 479
#250224 22:12:39 server id 3 end_log_pos 544 CRC32 0xa14d2919 GTID last_committed=2 sequence_number=3 rbr_only=yes original_committed_timestamp=0 immediate_commit_timestamp=0 transaction_length=0
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
# immediate_commit_timestamp=0 (1970-01-01 08:00:00.000000 CST)
/*!80001 SET @@session.original_commit_timestamp=0*//*!*/;
/*!80014 SET @@session.original_server_version=0*//*!*/;
/*!80014 SET @@session.immediate_server_version=0*//*!*/;
SET @@SESSION.GTID_NEXT= '4dfe51b2-f2b7-11ef-8924-0242c0a8d704:3'/*!*/;
# at 544 ### 4.
#250224 22:12:39 server id 3 end_log_pos 616 CRC32 0x6d656f4e Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1740406359/*!*/;
BEGIN
/*!*/;
# at 616
#250224 22:12:39 server id 3 end_log_pos 661 CRC32 0x063fcfc8 Table_map: `gaga`.`t2` mapped to number 113
# at 661
#250224 22:12:39 server id 3 end_log_pos 706 CRC32 0x4ecef684 Write_rows: table id 113 flags: STMT_END_F
BINLOG '
V368ZxMDAAAALQAAAJUCAAAAAHEAAAAAAAEABGdhZ2EAAnQyAAEDAAHIzz8G
V368Zx4DAAAALQAAAMICAAAAAHEAAAAAAAEAAgAB//4BAAAA/t4AAACE9s5O
'/*!*/;
# at 706
#250224 22:12:39 server id 3 end_log_pos 737 CRC32 0x3e164934 Xid = 7019
COMMIT/*!*/;
# at 737
#250224 22:17:30 server id 3 end_log_pos 760 CRC32 0x197523e6 Stop
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
建立GTID复制方式
- 1.基于gtid主动同步复制
- 2.基于冷备份 + 自定义gtid复制开始位置
注意事项
GTID 与非 GTID 的兼容性:如果从传统复制升级到 GTID,需要确保所有事务都转换为 GTID 模式。
跳过错误事务:可以用
SET GTID_NEXT='specific_gtid';
跳过有问题的 GTID。性能开销:GTID 会稍微增加日志大小和复制管理的开销,但在现代硬件上影响通常不大。
执行过gtid
mysql.gtid_executed