600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > mysql主从GTID不一致问题gtid_executed gtid_purged Retrieved_Gtid_Set Executed_Gtid_Set(I)

mysql主从GTID不一致问题gtid_executed gtid_purged Retrieved_Gtid_Set Executed_Gtid_Set(I)

时间:2019-11-30 10:15:27

相关推荐

mysql主从GTID不一致问题gtid_executed gtid_purged  Retrieved_Gtid_Set Executed_Gtid_Set(I)

/article/242473.htm

centos7下mysql双主+keepalived - benjamin杨 - 博客园

请设置从库为只读read_only=1,super_read_only=1就会大概率避免下面的情况

1 概念

1.1

gtid_executed等价Executed_Gtid_Set参数,已经执行的gtid集合(gtid-sets)。

gtid_purged,已经清除的gtid集合。

Retrieved_Gtid_Set:从库已经接收到主库的事务编号(从库的IO线程已经接受到了)

Executed_Gtid_Set:已经执行的事务编号(从库的执行sql线程已经执行了的sql)

master:

mysql> show variables like '%uuid%';+---------------+--------------------------------------+| Variable_name | Value |+---------------+--------------------------------------+| server_uuid | 21395c77-16b5-11ed-b628-005056b93c30 |+---------------+--------------------------------------+1 row in set (0.01 sec)

slave:

mysql> show variables like '%uuid%';+---------------+--------------------------------------+| Variable_name | Value |+---------------+--------------------------------------+| server_uuid | 56fc5c7d-d0d7-11ec-bbf9-005056b9e62b |+---------------+--------------------------------------+1 row in set (0.01 sec)

master:

mysql> show master status ;+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+| master-bin.000004 |194 | test,test1 | mysql,performance_schema,information_schema,sys | 21395c77-16b5-11ed-b628-005056b93c30:1-8 |+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+1 row in set (0.00 sec)

slave:

show slave statusRetrieved_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-3

其中主库的Executed_Gtid_Set为21395c77-16b5-11ed-b628-005056b93c30:1-8

可以看见Retrieved_Gtid_Set:21395c77-16b5-11ed-b628-005056b93c30:1-8 ,Executed_Gtid_Set:21395c77-16b5-11ed-b628-005056b93c30:1-8 ,也就是说主库产生了8个事务,从库接受到了来自主库的8个事务,并且都已经执行。

其中21395c77-16b5-11ed-b628-005056b93c30是主库的server-uuid。那么我们可以解析从库的binlog再看看

[root@localhost mysql]# [root@localhost mysql]# mysqlbinlog -vv master-bin.000004/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;DELIMITER /*!*/;# at 4#220808 11:50:46 server id 1 end_log_pos 123 CRC32 0xe8ab61ad Start: binlog v 4, server v 5.7.35-log created 220808 11:50:46# Warning: this binlog is either in use or was not closed properly.BINLOG 'FojwYg8BAAAAdwAAAHsAAAABAAQANS43LjM1LWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQAAa1hq+g='/*!*/;# at 123#220808 11:50:46 server id 1 end_log_pos 194 CRC32 0x0e046fb9 Previous-GTIDs# 21395c77-16b5-11ed-b628-005056b93c30:1-8SET @@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是怎么出来的呢?先说说已经执行的事务:

Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,

56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-3

这里的21395c77-16b5-11ed-b628-005056b93c30:1-8肯定很好理解,就是已经执行主库的1-8的事务,那么56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-3呢?这个其实也简单,有两种情况:

第一种情况:从库有数据写入(从库插入数据)

mysql> show slave status\G;*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 172.16.10.1Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-bin.000004Read_Master_Log_Pos: 194Relay_Log_File: localhost-relay-bin.000009Relay_Log_Pos: 409Relay_Master_Log_File: master-bin.000004Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 194Relay_Log_Space: 708Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 21395c77-16b5-11ed-b628-005056b93c30Master_Info_File: /var/lib/mysql/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-3Auto_Position: 1Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)ERROR: No query specifiedmysql> select * from jettech01;+------+------+| id | name |+------+------+| 1 | a || 2 | b || 3 | c || 5 | f || 7 | k |+------+------+5 rows in set (0.00 sec)mysql> insert into jettech01 value(8,'l');Query OK, 1 row affected (0.00 sec)mysql> select * from jettech01;+------+------+| id | name |+------+------+| 1 | a || 2 | b || 3 | c || 5 | f || 7 | k || 8 | l |+------+------+6 rows in set (0.00 sec)mysql> show slave status\G;*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 172.16.10.1Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-bin.000004Read_Master_Log_Pos: 194Relay_Log_File: localhost-relay-bin.000009Relay_Log_Pos: 409Relay_Master_Log_File: master-bin.000004Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 194Relay_Log_Space: 708Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: 21395c77-16b5-11ed-b628-005056b93c30Master_Info_File: /var/lib/mysql/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4Auto_Position: 1Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)ERROR: No query specified

可以看见已经执行的事务有来自主库的Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,也有从库刚自己写入的数据:56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4。我们可以解析binlog看看。看从库的bin-log日志。

[root@localhost mysql]# ls -al localhost-relay-bin.* slave36-bin.*-rw-r-----. 1 mysql mysql 299 5月 11 11:50 localhost-relay-bin.000008-rw-r-----. 1 mysql mysql 409 5月 11 11:50 localhost-relay-bin.000009-rw-r-----. 1 mysql mysql 58 5月 11 11:50 localhost-relay-bin.index-rw-r-----. 1 mysql mysql 177 5月 11 11:06 slave36-bin.000001-rw-r-----. 1 mysql mysql 177 5月 11 11:06 slave36-bin.000002-rw-r-----. 1 mysql mysql 2941 5月 11 14:41 slave36-bin.000003-rw-r-----. 1 mysql mysql 63 5月 11 11:06 slave36-bin.index

localhost-relay-bin.000009:从库执行主库同步过来的bin-log

slave36-bin.000003:从库自己的bin-log日志

[root@localhost mysql]# mysqlbinlog -vv slave36-bin.000003 --include-gtids="56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4"#220511 14:41:38 server id 2 end_log_pos 2741 CRC32 0x161748e6 GTIDlast_committed=11sequence_number=12rbr_only=yes/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;SET @@SESSION.GTID_NEXT= '56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:4'/*!*/;# at 2741#220511 14:41:38 server id 2 end_log_pos 2813 CRC32 0xa2271211 Querythread_id=3exec_time=0error_code=0SET TIMESTAMP=1652251298/*!*/;BEGIN/*!*/;# at 2813#220511 14:41:38 server id 2 end_log_pos 2868 CRC32 0xd00023ca Table_map: `test`.`jettech01` mapped to number 108# at 2868#220511 14:41:38 server id 2 end_log_pos 2910 CRC32 0x7a951c9a Write_rows: table id 108 flags: STMT_END_FBINLOG 'olp7YhMCAAAANwAAADQLAAAAAGwAAAAAAAEABHRlc3QACWpldHRlY2gwMQACA/4C/gEDyiMA0A==olp7Yh4CAAAAKgAAAF4LAAAAAGwAAAAAAAEAAgAC//wIAAAAAWyaHJV6'/*!*/;### INSERT INTO `test`.`jettech01`### SET### @1=8 /* INT meta=0 nullable=1 is_null=0 */### @2='l' /* STRING(1) meta=65025 nullable=1 is_null=0 */# at 2910#220511 14:41:38 server id 2 end_log_pos 2941 CRC32 0x6fd47737 Xid = 396COMMIT/*!*/;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*/;[root@localhost mysql]# ^C

从binlog中可以清楚的看到是从库进行了写入。下面说第二组情况

第二种情况:主从切换(我这里使用MHA切换主从)

Retrieved_Gtid_Set: 56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4

可以看到在切换以后主库的server-id是2。这里的意思是接收到主库56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4,并且已经执行这个事务,那么这个事务其实就是之前在从库写入的那条数据。对于21395c77-16b5-11ed-b628-005056b93c30:1-8个是之前作为主库执行。如果此时在主库再插入1条数据,那么又会变化如下

Retrieved_Gtid_Set: 56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-5Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-5

下面说说文章开头提到的gtid不连续的问题,类似21395c77-16b5-11ed-b628-005056b93c30:37-45,这个是由于binlog被清理以后导致的,我们可以测试一下。然后查看gtid_purged变量。

binlog不可能永远驻留在服务上,需要定期进行清理(通过expire_logs_days可以控制定期清理间隔),否则迟早它会把磁盘用尽。gtid_purged用于记录已经被清除了的binlog事务集合,它是gtid_executed的子集。只有gtid_executed为空时才能手动设置该变量,此时会同时更新gtid_executed为和gtid_purged相同的值。gtid_executed为空意味着要么之前没有启动过基于GTID的复制,要么执行过RESET MASTER。执行RESET MASTER时同样也会把gtid_purged置空,即始终保持gtid_purged是gtid_executed的子集。

slave,从库:

mysql> show master logs;+--------------------+-----------+| Log_name | File_size |+--------------------+-----------+| slave36-bin.000001 | 177 || slave36-bin.000002 | 177 || slave36-bin.000003 |2941 |+--------------------+-----------+3 rows in set (0.00 sec)mysql> flush logs;Query OK, 0 rows affected (0.00 sec)mysql> show master logs;+--------------------+-----------+| Log_name | File_size |+--------------------+-----------+| slave36-bin.000001 | 177 || slave36-bin.000002 | 177 || slave36-bin.000003 |2990 || slave36-bin.000004 | 234 |+--------------------+-----------+4 rows in set (0.00 sec)mysql> PURGE BINARY LOGS TO 'slave36-bin.000004';Query OK, 0 rows affected (0.00 sec)mysql> show master logs;+--------------------+-----------+| Log_name | File_size |+--------------------+-----------+| slave36-bin.000004 | 234 |+--------------------+-----------+1 row in set (0.00 sec)

然后只要从库有重新启动,才会读取。MySQL服务器启动时,通过读binlog文件,初始化gtid_executed和gtid_purged,使它们的值能和上次MySQL运行时一致。

gtid_executed被设置为最新的binlog文件中Previous_gtids_log_event和所有Gtid_log_event的并集。

gtid_purged为最老的binlog文件中Previous_gtids_log_event。

没启动前:

Retrieved_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4

重启以后并且插入数据:

Retrieved_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8Executed_Gtid_Set: 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-5

mysql> show variables like 'gtid_purged';+---------------+------------------------------------------------------------------------------------+| Variable_name | Value |+---------------+------------------------------------------------------------------------------------+| gtid_purged | 21395c77-16b5-11ed-b628-005056b93c30:1-8,56fc5c7d-d0d7-11ec-bbf9-005056b9e62b:1-4 |+---------------+------------------------------------------------------------------------------------+1 row in set (0.01 sec)

到这里相信聪明的你一定看懂了。最后顺道说说gtid跳过复制错误的方法,对于跳过一个错误,找到无法执行事务的编号,比如是21395c77-16b5-11ed-b628-005056b93c30:1-8,那么操作如下:

stop slave;set gtid_next='21395c77-16b5-11ed-b628-005056b93c30:1-8';begin;commit;set gtid_next='AUTOMATIC';start slave;

上面方法只能跳过一个事务,那么对于一批如何跳过?在主库执行show master status,看主库执行到了哪里,比如:21395c77-16b5-11ed-b628-005056b93c30:1-33,那么操作如下:

stop slave;reset master;set global gtid_purged=' 21395c77-16b5-11ed-b628-005056b93c30:1-33';start slave;

gtid_executed:

如何查看已经执行过的GTID?

系统表 mysql.gtid_executed 存放了所有执行过的GTID(在活动的binlog中的除外),但是由于不包含活动的binlog当中的GTID,因此需要查看精确值时,可以查看 global variable gtid_executed 的值,这个变量的值是准确的(或者 show master status )。

同一个GTID的事务不会在一个Server上执行两次,可以保证数据一致性。

GTID SET

GTID SET是指多个GTID的集合,示例如下:

2174B383-5441-11E8-B90A-C80AA9429562:1-3, 24DA167-0C0C-11E8-8442-00059A3C7B00:1-19

gtid_executed 和 gtid_purged 这两个系统变量 都是 GTID SET

gtid_purged:

这个一个 GTID SET,包含了所有已经提交过的,但是不在 binlog 当中的 GTID ,它是 gtid_executed 的子集。以下几种 GTID 都会添加到 gtid_purged 当中:

1. 未开启binlog的从库上提交过的GTID

2. 已经被 "purge" 掉的 binlog 当中的 GTID 。(当发出 purge binary log 命令之后,如果被 purge的binlog中包含有GTID,那么查看 gtid_purged 变量值的时候,就会看到该变量值发生了变化)

3. 使用 'set global gtid_purged= "xxxx" ' 添加的 GTID

什么时候需要设置 gtid_purged 变量?

人为设置 gtid_purged 的目地是为了告诉服务器,即使它们不在 binlog 中,这些 GTID 已经 被应用过了,不能/不需要再重做。一个必须人为设置 gtid_purged 的场景见文章

总结

relay_log_recover=0

slave会扫描最后一个relay log文件,Retrieved_Gtid_Set显示的是当前扫描所得的GTID;io线程会通过扫描所得的最后一个GTID+1(如果Retrieved_Gtid_Set>=Executed_Gtid_Set)为依据来拉取,如果Retrieved_Gtid_Set

relay_log_recover=1

slave中把所有relay log清除,io线程通过Executed_Gtid_Set后的+1个事务开始拉取并生成新的relay log文件;SQL线程在清除relay log时把Relay_Log_File、Relay_Log_Pos设为空,所以SQL线程从新的relay log文件的第一个事务开始应用

1.2 产生:

当一个事务提交时,就会分配一个GTID(前提是事务有写入到binlog),GTID单调递增且连续。

1.3 GTID格式:

GTID = source_id:transaction_id

其中 source_id 一般指 source 的 server_uuid , 示例:3E11FA47-71CA-11E1-9E33-C80AA9429562:2

mysql.gtid_executed表:GTID持久化的介质,MySQL启动阶段会读取这个表来获取gtid_executed变量的值。gtid_executed变量(show global variables):MySQL数据库已经执行了哪些GTID事务,处于内存中。show slave status中的executed_gtid_set也取自这里。

mysql> show global variables like '%gtid%';+----------------------------------+------------------------------------------+| Variable_name| Value|+----------------------------------+------------------------------------------+| binlog_gtid_simple_recovery| ON || enforce_gtid_consistency | ON || gtid_executed| 21395c77-16b5-11ed-b628-005056b93c30:1-8 || gtid_executed_compression_period | 1000 || gtid_mode | ON || gtid_owned | || gtid_purged | || session_track_gtids | OFF |+----------------------------------+------------------------------------------+8 rows in set (0.01 sec)

mysql> show master status ;+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+| master-bin.000004 |194 | test,test1 | mysql,performance_schema,information_schema,sys | 21395c77-16b5-11ed-b628-005056b93c30:1-8 |+-------------------+----------+--------------+-------------------------------------------------+------------------------------------------+1 row in set (0.00 sec)

gtid_purged变量(show global variables):由于BINLOG文件的删除(如purge binary logfiles或者超过expire_logs_days设置)已经丢失的GTID事务,同时在搭建备库的我们使用set global gtid_purged变量来提示MySQL哪些GTID事务我已经执行过了

这也是我们DBA通常能够观察到的几种GTID,有了前文的描述我们知道其中mysql.gtid_executed表是一种GTID持久化的介质,而gtid_executed变量和gtid_purged变量则对应了,gtid_state中的executed_gtidslost_gtids内存数据。他们分别表示MySQL数据库执行了哪些GTID事务,有哪些GTID事务由于BINLOG文件的删除已经丢失了。

其次我们先来达成一个共识gtid_executed变量一定是实时更新的不管主库和从库。我们的讨论分为主库,从库和通用从源码的角度进行详细讨论。并且约定都是打开GTID的情况下。最后给出最终总结。

1.4gtid_executed,全局参数,GTID集合包含所有在该服务器上执行过的事务编号和使用set gtid_purged语句设置过的事务编号,使用SHOW MASTER STATUS和SHOW SLAVE STATUS命令得到的Executed_Gtid_Set列值就取自于全局参数gitd_executed。

gtid_purged,全局参数,GTID集合包含从binlog中purged掉的事务ID,该集合是全局参数gtid_executed的子集。

2 参数更新机制

2.1 master:当复制主库关闭binlog时:

1. 事务提交不会生成GTID,mysql.gtid_executed表/gtid_executed变量/gtid_purged变量均不更新。

2.2 当复制主库开启binlog时:

1. 事务提交需要生成Binlog,GTID在Binlog的ordered_commit flush阶段生成。

2. 表mysql.gtid_executed在实例重启或flush log或binlog文件写满等造成binlog发生切换是保存上一个binlog执行过的全部gtid,属于非实时更新。

3. 全局变量gtid_executed在事务commit阶段更新,属于实时更新。

4. 全局变量gtid_purged在执行purge binary log命令或binlog超过保持期进行清理binlog时更新,属于非实时更新。

2.3当复制从库关闭binlog或关闭log_slave_update时:slave

1. 在从库上应用主库binlog时不会生成新的GTID,也不会写入复制从库的binlog文件。

2. 表mysql.gtid_executed在应用主库binlog事务时更新,并与事务一起提交,属于实时更新。

3. 全局变量gtid_executed在主库binlog事务commit阶段更新,属于实时更新。

4. 全局变量gtid_purged在主库binlog事务commit阶段更新,属于实时更新。

2.4 当复制从库开启binlog或开启log_slave_update时:

1. 在从库上应用主库binlog时不会生成新的GTID,但会写入复制从库的binlog文件。

2. 表mysql.gtid_executed在实例重启或flush log或binlog文件写满等造成binlog发生切换是保存上一个binlog执行过的全部gtid,属于非实时更新。

3. 全局变量gtid_executed在事务commit阶段更新,属于实时更新。

4. 全局变量gtid_purged在执行purge binary log命令或binlog超过保持期进行清理binlog时更新,属于非实时更新。

3 参数重置机制

在某些场景下,需要修改全局变量gtid_purged和gtid_executed的值,执行对全局变量gtid_purged进行赋值时,会报以下错误:

ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

设置@@GLOBAL.GTID_EXECUTED需要通过RESET MASTER命令,该命令会清空当前服务器上的Binlog文件,并将@@GLOBAL.GTID_EXECUTED和@@GLOBAL.GTID_PURGED的值重置为空,重新初始化binlog文件序号,重新初始化GTID的事务ID起始值.

4 参数恢复机制

参数binlog_gtid_simple_recovery用于控制在实例重启时,如何计算全局变量gtid_executed和gtid_purged。在MySQL 5.7.7及之后版本中该参数默认为True。

binlog_gtid_simple_recovery=FALSE

• To initialize gtid_executed, binary log files are iterated from the newest file, stopping at the first binary log that has any Previous_gtids_log_event. All GTIDs from Previous_gtids_log_event and Gtid_log_events are read from this binary log file. This GTID set is stored internally and called gtids_in_binlog. The value of gtid_executed is computed as the union of this set and the GTIDs stored in the mysql.gtid_executed table.

This process could take a long time if you had a large number of binary log files without GTID events, for example created when gtid_mode=OFF.

• To initialize gtid_purged, binary log files are iterated from the oldest to the newest, stopping at the first binary log that contains either a Previous_gtids_log_event that is non-empty (that has at least one GTID) or that has at least one Gtid_log_event. From this binary log it reads Previous_gtids_log_event. This GTID set is subtracted from gtids_in_binlog and the result stored in the internal variable gtids_in_binlog_not_purged. The value of gtid_purged is initialized to the value of gtid_executed, minus gtids_in_binlog_not_purged.

binlog_gtid_simple_recovery=TRUE

which is the default in MySQL 5.7.7 and later, the server iterates only the oldest and the newest binary log files and the values of gtid_purged and gtid_executed are computed based only on Previous_gtids_log_event or Gtid_log_event found in these files. This ensures only two binary log files are iterated during server restart or when binary logs are being purged.

在实例重启后,全局变量gtid_executed和gtid_purged的值取决于:

1、从binlog文件头读取Previous_gtids_log_event获取该binlog之前的gtid_set

2、从binlog文件的所有事件中获取该binlog中包含的gtid_set

3、从mysql.gtid_executed表获取到执行过的gtid_set

通过上面三个集合算出当前实例执行过的gtid_set和当前BINLOG中包含的gtid_set。

4 mysql.gtid_executed表更新机制

在MySQL 5.6版本中,开启GTID模式必须打开参数log_slave_updates,即从库必须在记录一份binlog,以保证在从库重启后,可以通过扫描最后一个二进制日志获得当前从库执行过的GTID集合。

在MySQL 5.7.5版本中引入mysql.gtid_executed表来存放gtid信息,因此在GTID模式下不要求开启log_slave_update参数。

在MySQL 5.7版本中,对mysql.gtid_executed表的更新策略分为:

1、主库服务器,未开启log_bin参数,则不对mysql.gtid_executed表进行更新。

2、主库服务器,开启log_bin参数,当二进制文件进行rotation时或者关闭实例时对mysql.gtid_executed进行更新。

3、从库服务器,未开启log_bin参数或未开启log_slave_updates参数,在用户事务执行时对mysql.gtid_executed进行更新,并与用户事务一起进行提交。

4、从库服务器,开启log_bin参数和开启log_slave_updates参数,当二进制文件进行rotation时或者关闭实例时对mysql.gtid_executed进行更新。

当主库开启log_bin参数或从库开启log_slave_update参数时,执行或应用事务所生成的binlog会写入磁盘,当二进制文件进行rotation时或者关闭实例时对mysql.gtid_executed进行更新,表mysql.gtid_executed中不能提供完整的GTID集合数据,需以参数gtid_executed为准,如果实例异常重启,最近的GTID集合数据没有更新到mysql.gtid_executed表中,当实例恢复时,通过扫描最后一个binlog文件来获得最新的GTID集合数据。

当从库未开启log_bin参数或未开启log_slave_updates参数时,应用主库所传递过来的事务不会产生新的binlog,在执行事务开始便可以获取到该事务的GTID,因此可以随着事务一起提交,类似于MySQL 5.6版本中随事务一起更新mysql.slave_master_info表一样。

当执行RESET MASTER时,表mysql.gtid_executed会被清空。

5 mysql.gtid_executed表压缩

当从库未开启log_slave_updates参数时,由于每个事务都会向mysql.gtid_executed表写入记录,为防止mysql.gtid_executed表数据量暴增,MySQL 5.7引入参数gtid_executed_compression_period来控制每执行N个事务后,对mysql.gtid_executed表进行一次压缩,将多个连续的gtid值合并为gtid集合。如果gtid_executed_compression_period被设置为0,则不会进行压缩。

当主库开启log_bin参数或从库开启log_slave_update参数时,参数gtid_executed_compression_period并不会被使用,只有当二进制文件进行Rotation时才会进行GTID压缩。MySQL Replication--全局参数gtid_executed和gtid_purged - TeyGao - 博客园

==================================

1.

#从库通过show slave status\G找到冲突的GTID号(如上图)stop slave sql_thread;SET gtid_next = '冲突的GTID号';#SET gtid_next = '00017261-1111-1111-1111-111111111111:858';之后的变化为Executed_Gtid_Set: 00017261-1111-1111-1111-111111111111:1-858,BEGIN;COMMIT;SET gtid_next = 'AUTOMATIC';start slave sql_thread;#最后从库再次执行 show slave status\G 进行验证。

2.gtid_next与GLOBAL GTID_PURGED:小知识分享

相同点:

都是改变Executed_Gtid_Set的值。(表示为从库已经执行完毕的事务gtid信息)

不同点:

gtid_next是一个具体的gtid号(影响范围小)

GLOBAL GTID_PURGED是一段gtid号,并且需要Executed_Gtid_Set为空,也就是需要执行reset master

(影响范围大,比如说新建一个增量的从库,就可以告诉从库执行那些relaylog,有这个场景但没实践过)

#配合以下语句使用

show variables like '%gtid_purged%';#查看从库执行过的信息

(reset master之后为空,从库的binlog也会重建)

#SET GLOBAL GTID_PURGED='1111:1-850'

#手动让从库认为1111:845已经执行

3.恢复报错:

ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty

当前GTID_EXECUTED参数已经有值,而从集群倒出来的dump文件中包含了SET @@GLOBAL.GTID_PURGED的操作

4.解决方法

方法三:vim all_db.sql (记录下图的set信息,然后删除set值,重新恢复单库)(注意备份文件的大小,越大打开的越慢)方法二:reset master这个操作可以将当前库的GTID_EXECUTED值置空方法一:--set-gtid-purged=off在dump导出时,添加--set-gtid-purged=off参数,避免将gtid信息导出mysqldump -uroot -p --set-gtid-purged=off -d test> test.sql

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。