mysql的gtid复制_MySQL复制和GTID

本文问题

在使用GTID的MySQL复制中,如何判断主从是否一致?

mysql.gtid_executed表是哪个版本开始有的?有什么作用?

GTID在什么时候记录到mysql.gtid_executed表中?

gtid_purged是个全局变量还是会话变量?它存储了哪些内容?

如何更改gtid_purged,有什么作用和限制?

gtid_next变量有什么作用?手动设置gtid_next有什么注意事项?

使用什么语句重置GTID执行历史记录,该语句都进行了哪些操作?

基于GTID的复制

在使用GTID时,每个事务都可以在原始数据库上提交和在从库应用时被识别和跟踪。这意味着当使用GTID时,不需要二进制日志的文件和位置。由于GTID复制完全基于事务,所以可以简单的确定主库和从库是否一致。只要在主库上提交的所有事务在从库上也都进行了提交,就可以保证两者之间的一致性。

GTID始终在主库和从库之间维护。这意味着可以通过检查从库应用的日志来检查事务是从哪个主库获取的。另外,一旦在指定服务器上提交了具有指定GTID的事务,这个服务器会忽略具有相同GTID的事务,因此,在主库上提交的事务在从库上最多只能应用一次,这有助于确保一致性

查看服务器应用过哪些GTID

select @@global.gtid_executed;

select * from mysql.gtid_executed; 这个语句不会显示当前正在使用的二进制日志中的GTID,只有日志刷新后才会记录到该表中。

查看哪些GTID已从服务器上删除

select @@global.gtid_purged 当删除二进制日志时,如果二进制日志中存在GTID,则会将已删除的GTID记录在gtid_purged中

GTID的格式

GTID格式

一个GTID的格式是GTID = source_id:transaction_id

source_id标识了事务的原始服务器,通常是主库的server_uuid

transaction_id是按照事务在主库上提交的顺序递增的一个序列号,从1开始。

GTID集合格式

GTID集合是一个包括一个或多个或者一个范围的GTID的集合。

GTID集合可以包括多个source_id

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-3:11:47-49

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

GTID和GTID集合的不同使用场景

GTID

mysqlbinlog的输出是单个GTID

在Performance_schema中关于复制状态的表中记录的是单个GTID

gtid_next的值是单个GTID

GTID集合

gtid_executed和gtid_purged的值是GTID集合

GTID_SUBSET()和GTID_SUBTRACT()函数需要使用GTID集合作为输入

START SALVE的UNTIL SQL_BEFORE_GTIDS和UNTIL SQL_AFTER_GTIDS子句可以用来设置从库应用事务到GTID集合的第一个GTID,或者在应用GTID集合的最后一个GTID后停止。

mysql.gtid_executed表

MySQL在5.7版本增加了mysql.gtid_executed表。用来记录GTID。在MySQL5.6及以前版本,由于GTID只存储在日志文件中,使用基于GTID的复制必须在从库上启用log_bin和log_slave_updates。增加了这个表之后,GTID的信息可以记录在表中,从而允许从库在禁用日志的情况下,使用基于GTID的复制。

使用RESET MASTER可以清除mysql.gtid_executed表中的内容。

只有当gtid_mode为ON或者ON_PERMISSIVE时,GTID才会存储在mysql.gtid_executed表中。

在MySQL8.0.17版本以前,GTID的存储取决于二进制日志是否可用:

log_bin=OFF或者log_slave_updates=OFF:服务器在执行事务的同时存储该事务的GTID

log_bin=ON:当刷新二进制日志或者关闭数据库时,将之前二进制日志中的所有GTID集合写入到mysql.gtid_executed表中。

在MySQL8.0.17版本以后:

如果仅使用InnoDB存储引擎,当log_bin=ON时,也在执行事务的同时存储该事务的GTID到表中

GTID在从库上的应用

当二进制日志数据传输到从库并且存储到从库的中继日志后,从库读取GTID并且将gtid_next的系统变量设置为这个GTID。这告诉从库下一个事务必须使用这个GTID进行记录。gtid_next是个会话环境

从库验证没有线程拥有gtid_next中记录的GTID的所有权以处理事务。首先读取并且检查复制的事务的GTID,在处理事务前,从库确保具有该GTID的事务没有被应用过,并且没有其他会话已经读取了这个GTID但是还没有进行提交关联的事务。如果有多个客户端试图同时应用同一个事务,服务器只允许其中的一个事务提交。从库上的gtid_owned变量(@@GLOBAL.gtid_owned)显示了当前正在使用的GTID以及它正在被哪个拥有和使用。如果GTID已经被使用,不会产生错误,并且使用自动跳过函数忽略这个事务

如果GTID没有被使用,从库应用这个复制事务。由于gtid_next已经被设置为主库分配的GTID,从库不会为这个使用生成新的GTID,而是使用gtid_next中存储的GTID

如果从库启用了二进制日志,GTID在事务提交时写入到二进制日志中。在刷新二进制日志或者关闭服务器时,将之前的GTID集合写入到mysql.gtid_executed表中

如果从库没有启用二进制日志,GTID直接写入到mysql.gtid_executed表中。MySQL将一个语句添加到事务中,以将GTID插入表中。在这种情况下,mysql.gtid_executed表是从库应用事务的完整记录。在MySQL5.7中,对于DML语句,将GTID插入表的操作是原子的,但对于DDL语句不是原子的,如果服务器在涉及DDL语句的事务处理后意外终止,则GTID状态可能会变得不一致。在MySQL8.0后,该操作对于DDL和DML语句都是原子的

在从库上的复制的事务提交后,GTID马上添加到从库的gtid_executed系统变量中。

相关系统变量

gtid_next

默认情况下,对于在用户会话提交的新事务,服务器自动生成并分配一个新的GTID、当事务在从库中应用时,将保留源服务器分配的GTID。可以通过设置gtid_next来改变这种行为:

gtid_next='AUTOMATIC'

当事务提交并写入到二进制日志时,自动生成并分配一个GTID。如果由于事务回滚或者其他原因没有写入到二进制日志,则不会分配GTID。自动生成的GTID是uuid:最小未使用的transaction_id

gtid_next设置为一个有效的GTID

会将该GTID分配给事务,即使事务没有写入到二进制日志或者事务为空,也会分配这个GTID。

在通过gtid_next指定一个GTID,并且事务提交或回滚后,需要在发出其他语句前使用SET @@SESSION.gtid_next语句来设置下一个事务的GTID。

gtid_purged

gtid_purged中包括了所有在服务器上已经提交的,但是已经不存在于二进制日志中的事务的集合。gtid_purged是gtid_executed的子集。

以下类别的GTID集合存在于gtid_purged中:

在禁用二进制日志的从库上应用的复制事务的GTID集合

在已经删除的二进制日志中的事务的GTID集合

通过SET @@GLOBAL.gtid_purged语句添加的GTID集合

可以手动将不在二进制日志中的GTID集合添加到gtid_purged中

在MySQL5.7中,只有当gtid_executed为空时才能修改gtid_purged。

在MySQL8.0中,没有这种限制

可以使用GTID集合替换整个gtid_purged的内容

新GTID集合必须包括之前已经存在与gtid_purged中的集合,并且不能包括在gtid_executed中但是没有删除的GTID集合,也不能包括@@global.gtid_owned中的集合。

SET @@GLOBAL.gtid_purged = 'gtid_set'

也可以添加指定的GTID集合到gtid_purged中

SET @@GLOBAL.gtid_purged = '+gtid_set'

重置GTID执行历史记录

使用RESET MASTER语句可以重置GTID执行历史记录,将执行以下操作:

将gtid_purged值设置为空字符串(' ')

将gtid_executed的全局值设置为空字符串

清空mysql.gtid_executed表

如果数据库启用了二进制日志,将会删除现有的二进制日志并且清空二进制日志索引文件。重新生成序号为1的日志文件

问题答案

在使用GTID的MySQL复制中,如何判断主从是否一致?

通过查看已经执行的GTID集合是否一致来进行判断

查看已经执行的GTID集合

select @@global.gtid_executed;

不能通过select * from mysql.gtid_executed来查看的原因是因为只有二进制日志刷新后才会将gtid记录到该表中,当前正在使用的二进制日志中的事务不会记录到表中

mysql.gtid_executed表是哪个版本开始有的?有什么作用?

MySQL在5.7版本增加了mysql.gtid_executed表。用来记录GTID。

在MySQL5.6及以前版本,由于GTID只存储在日志文件中,使用基于GTID的复制必须在从库上启用log_bin和log_slave_updates。增加了这个表之后,GTID的信息可以记录在表中,从而允许从库在禁用日志的情况下,使用基于GTID的复制。

GTID在什么时候记录到mysql.gtid_executed表中?

在MySQL8.0.17版本以前,GTID的存储取决于二进制日志是否可用:

log_bin=OFF或者log_slave_updates=OFF:服务器在执行事务的同时存储该事务的GTID

log_bin=ON:当刷新二进制日志或者关闭数据库时,将之前二进制日志中的所有GTID集合写入到mysql.gtid_executed表中。

在MySQL8.0.17版本以后:

如果仅使用InnoDB存储引擎,当log_bin=ON时,也在执行事务的同时存储该事务的GTID到表中

gtid_purged是个全局变量还是会话变量?它存储了哪些内容?

gtid_purged是个全局变量

gtid_purged中包括了所有在服务器上已经提交的,但是已经不存在于二进制日志中的事务的集合。gtid_purged是gtid_executed的子集。

以下类别的GTID集合存在于gtid_purged中:

1.在禁用二进制日志的从库上应用的复制事务的GTID集合

2.在已经删除的二进制日志中的事务的GTID集合

3.通过SET @@GLOBAL.gtid_purged语句添加的GTID集合

如何更改gtid_purged,有什么作用和限制?

更新整个gtid_purged中的集合

SET @@GLOBAL.gtid_purged = 'gtid_set'

添加指定的GTID集合到gtid_purged中(8.0+)

SET @@GLOBAL.gtid_purged = '+gtid_set'

作用

用于在服务器上记录已应用某个GTID集合的事务,但是这些事务在二进制日志中不存在的时候。

比如说还原数据库,但是没有包含事务的相关二进制日志的时候

限制

在MySQL5.7中,只有当gtid_executed为空时才能修改gtid_purged。

在MySQL8.0中,没有这种限制

gtid_next变量有什么作用?手动设置gtid_next有什么注意事项?

默认情况下,对于在用户会话提交的新事务,服务器自动生成并分配一个新的GTID、当事务在从库中应用时,将保留源服务器分配的GTID。可以通过设置gtid_next来改变这种行为:

gtid_next='AUTOMATIC'

当事务提交并写入到二进制日志时,自动生成并分配一个GTID。如果由于事务回滚或者其他原因没有写入到二进制日志,则不会分配GTID。

gtid_next设置为一个有效的GTID

会将该GTID分配给事务,即使事务没有写入到二进制日志或者事务为空,也会分配这个GTID。

注意事项:

在通过gtid_next指定一个GTID,并且事务提交或回滚后,需要在发出其他语句前使用SET @@SESSION.gtid_next语句来设置下一个事务的GTID。

使用什么语句重置GTID执行历史记录,该语句都进行了哪些操作?

RESET MASTER

操作:

将gtid_purged值设置为空字符串(' ')

将gtid_executed的全局值设置为空字符串

清空mysql.gtid_executed表

如果数据库启用了二进制日志,将会删除现有的二进制日志并且清空二进制日志索引文件。重新生成序号为1的日志文件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值