- 概述:
- 当使用GTIDs时,可以识别和跟踪每一个事务,因为它是在原始服务器上提交的,并由任何slave应用;简单来说就是master提交的所有事务都在slaves应用一次,两者的数据就能保证一致性,此外,同一GTID的事务只能在同一服务器上面提交一次。
- 格式:
- GTID表示为一对坐标,由冒号分隔(:)
- GTID = source_id:transaction_id
- source_id标识原始服务器.通常,服务器的server_uuid用于此目的。transaction_id是一个序列号,由在该服务器上提交事务的顺序决定;例如,要提交的第一个事务的transaction_id为1,而在同一个源服务器上提交的第十个事务的transaction_id为10。事务不可能将0作为GTID中的序列号。例如,在最初使用UUID 3E11FA47-71CA-11E1-9E33-C80AA9429562的服务器上提交的第23个事务具有以下GTID:
3E11FA47-71CA-11E1-9E33-C80AA9429562:23 - 如在SHOW MASTER STATUS或SHOW SLAVE STATUS等语句的输出中所写,来自同一服务器的一系列GTID可以折叠成单个表达式,如此处所示
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
刚刚显示的示例表示源自MySQL服务器的第一到第五个事务,其server_uuid是3E11FA47-71CA-11E1-9E33-C80AA9429562。
- 生命周期:
- 事务在master上执行并提交。此客户端事务被分配一个GTID,该GTID由master的UUID和此服务器上尚未使用的最小非零事务序列号组成。GTID被写入master的二进制日志(紧接在日志中的事务本身之前)。如果未将客户端事务写入二进制日志(例如,因为事务已被过滤掉,或者事务是只读的),则不会为其分配GTID
- 如果为事务分配了GTID,则在提交时通过将其写入事务开始时的二进制日志(作为Gtid_log_event)以原子方式持久化GTID。无论何时旋转二进制日志或关闭服务器,服务器都会将写入先前二进制日志文件的所有事务的GTID写入mysql.gtid_executed表。
- 如果为事务分配了GTID,则通过将GTID添加到gtid_executed系统变量(@@GLOBAL.gtid_executed)中的GTIDs集,以非原子方式外部化GTID(在提交事务之后不久)。此GTID集包含所有已提交的GTID事务集的表示形式,并在复制中用作表示服务器状态的标记。启用二进制日志记录(根据master的要求),gtid_executed系统变量中的GTID集是应用事务的完整记录,但mysql.gtid_executed表不是,因为最新的历史记录仍在当前二进制日志文件中
- 将二进制日志数据传输到slave并存储在slave的中继日志中,然后slave读取GTID并将其gtid_next系统变量的值设置为此GTID。这告诉slave必须使用此GTID记录下一个事务。值得注意的是,slave在会话上下文中设置了gtid_next。
- slave验证没有线程在gtid_next中获得GTID的所有权以便处理事务。通过首先读取和检查复制事务的GTID,在处理事务本身之前,slave不仅保证在slave上没有应用具有此GTID的先前事务,而且还保证没有其他会话已经读取此GTID但尚未提交的相关事务。因此,如果多个客户端尝试同时应用同一事务,则服务器只允许其中一个执行,从而解决此问题。slave的gtid_owned系统变量(@@ GLOBAL.gtid_owned)显示当前正在使用的每个GTID以及拥有它的线程的ID。如果已经使用了GTID,则不会引发错误,并且使用自动跳过功能来忽略该事务。
- 如果尚未使用GTID,则slave应用复制的事务。由于gtid_next设置为master已分配的GTID,因此slave不会尝试为此事务生成新的GTID,而是使用存储在gtid_next中的GTID。
- 如果在slave上启用了二进制日志记录,那么GTID将在提交时以原子方式持久化,方法是在事务开始时将其写入二进制日志(作为Gtid_log_event)。无论何时旋转二进制日志或关闭服务器,服务器都会将写入先前二进制日志文件的所有事务的GTID写入mysql.gtid_executed表。
- 如果在slave上禁用二进制日志记录,则通过将GTID直接写入mysql.gtid_executed表来原子性地保留GTID。MySQL向事务添加一条语句,将GTID插入到表中。在这种情况下,mysql.gtid_executed表是slave上应用的事务的完整记录。请注意,在MySQL 5.7中,将GTID插入表中的操作对于DML语句是原子操作,但对于DDL语句则不是,因此如果服务器在涉及DDL语句的事务之后意外退出,则GTID状态可能会变得不一致。从MySQL 8.0开始,DDL语句和DML语句的操作都是原子操作。
- 在slave上提交复制事务之后不久,通过将GTID添加到slave的gtid_executed系统变量(@@ global.gtid_execute)中的GTIDs集合中,以非原子方式外部化GTID。对于master,这个GTID集合包含所有已提交GTID事务的集合的表示。如果在slave上禁用二进制日志记录,则mysql.gtid_executed表也是在slave上应用的事务的完整记录。如果在slave上启用了二进制日志记录,则意味着某些GTIDs仅记录在二进制日志中,gtid_executed系统变量中的GTIDs集是唯一的完整记录。
参考资料:https://dev.mysql.com/doc/refman/5.7/en/replication-gtids.html
PREV: 3:添加一个slave到已有的复制环境(基于二进制日志文件位置) https://blog.51cto.com/itzhoujun/2351567
NEXT:5:使用GTID进行复制 https://blog.51cto.com/itzhoujun/2352693