Code前端首页关于Code前端联系我们

通过这篇文章了解GTID和MySQL

terry 2年前 (2023-09-26) 阅读数 46 #后端开发

要谈GTID,我们先了解一下MySQL主从复制。

为什么需要Mysql主从复制

我们来说一下为什么大多数情况下Mysql经常采用Mysql主从模式部署。主要原因如下:

  • 对数据进行热备份,当主库宕机时,备份数据库可以及时替代主库,保证业务可用性,一定程度上防止数据丢失。
  • 实现读写分离,写入主库,从库读取,减轻主库的读写压力。当主库进行写过程并被锁定时,从库的读操作不会被阻塞,提高了数据查询的效率。
  • 应对业务量不断增加、I/O访问频率高单机无法满足的问题。添加多个从库来执行加载可以降低整体I/O访问频率,提高单机I/O性能。

数据库中常用的主从复制方式

基于Binlog复制模型

MySQL主从复制默认是异步的。 MySQL所有的增删改查都记录在Binlog中。 Slave节点连接Master时,主动接收Master发送的最新的Binlog文件。并将Binlog保存到本地relay log中,然后执行relay log更新的内容。站点同步的原理如下:

MySQL中的GTID一文了解

1、主库会生成几个binlog日志文件。

2、 请求库 I/O 线程指定位置的 binlog 日志文件(站点)中的指定文件。

3、主库dump线程从指定位置获取binlog日志。

4、主库根据从库发来的位置信息读取binlog,然后打印binlog到从库。

5、从库将接收到的binlog写入本地中继日志(relay-log)文件。

6、 从库的 SQL 线程读取并解析中继日志文件。

7、从库的 SQL 线程重播中继日志中的命令。

如果使用站点同步,两种场景下的操作步骤都比较复杂。

有痛点

痛点一:首次开启主从复制步骤复杂,必须一致。

  • 查找主库的binlog位置。
  • 设置从库的binlog位置。
  • 启动从库的复制线程。
  • 痛点二:恢复主从复制步骤复杂

    • 找到从复制线程停止的点。
    • 解决复制异常中的事务。如果无法解决,则必须手动跳过指定类型的错误,例如通过设置slave_skip_errors = 1032,1062。当然,这个假设是跳过这样的错误是没有损失的。 (1062错误是插入数据时唯一键冲突;1032错误是删除数据时找不到该行)

    GTID复制模式

    针对基于Binlog复制模式解决的痛点,一个新的该模式是MySQL 5.6中提供的数据恢复思想,这就是基于GTID的复制模式。 MySQL可以通过内部机制GTID自动寻找同步点,并且通过GTID可以保证主库提出的每个事务在集群中都有唯一的事务ID,这就加强了数据库主从的一致性和容错性。错误恢复数据。如果主库宕机,发生主从切换,GTID方法可以让其他从库自动找到新主库的副本位置。此外,GTID可以忽略已经执行的事务,从而减少数据错误的可能性。 GTID同步的原理如下:

    • 主节点在遇到交易之前会生成一个GTID,记录在❿❙❙❙❿❙❿❙交易中。
    • 从节点I/O线程读取主节点binlog❿❿ ❿❿它在从属文件中。中继日志 在日志中。从节点配置主节点的GTID的值和gtid_next,这是下一个要读取的GTID值。
    • 从节点SQL线程从中继日志中读取gtid_next中的值,然后查找自己的binlog GTID 。
    • 如果有这条记录,则表示GTID的交易已被执行,将被忽略。
    • 如果没有这样的记录,则从节点从中继日志中执行GTID的事务,并将其记录在自己的binlog日志中。同时,在读取和执行交易之前,首先检查其他session是否持有GTID,确保不重复。

    GTID相关概念介绍

    什么是GTID

    GTID指的是全局事务ID,全称是❀全局事务有以下特点: GTID交易全局唯一,一笔交易对应一个GTID值。

  • GTID 值在同一个 MySQL 实例上仅执行一次。
  • GTID 由 server_uuid + tid❙ 组成,其中: ❿ server_uuid是MySQL第一次启动时自动生成的(128位) 随机值。生成后,该值存储在数据目录下的auto.cnf文件中。

  • tid:表示该实例上提交的事务数量,随着事务完成而单调增加,因此GTID保证了每个MySQL实例事务的执行(同一个事务并不总是再次执行,会补充有根本没有执行任何交易)。
  • 组合风格如下:

     26630fed-fe68-11ec-b051-000c29509871:1-27

    GTID相对于传统复制的优势

    • 主从设置更简单,无需手动指定位置。
    • 复制集群具有统一的标识,更易于识别和管理。
    • 故障转移更容易。不需要像传统复制那样找到log_file和log_position的位置。
    • 通常情况下,GTID是连续的,没有空洞,可以更好地保证数据的一致性。
    • 相比ROW复制模式,数据安全性更高,切换更容易。
    • 它比传统复制更安全。 GTID在MySQL实例上只执行一次,避免重复执行导致数据混乱或主从不一致。

    GTID 使用限制

    GTID 复制适用于事务。一笔交易只对应一个GTID。这里有很多限制。主要限制如下:

    • 在复制组中,必须打开或关闭GTID。
    • 需要重新启动才能启用 GTID(5.7 除外)
    • 不支持 创建表 table_name select * from table_name 语句副本。

    原理:

    会生成两条sql,一条是DDL建表SQL,一条是insert和插入数据的sql。因为 DDL 会导致自动提交,所以这条 sql 至少需要两个 GTID,但 GTID 模式下这条 sql 只能生成一个 GTID)

    • 不允许在一个事务中包含两个事务表(使用 InnoDB存储引擎表)的操作还包括非事务性表(与MyISAM存储引擎表)。
    • 不支持创建或删除临时表操作,例如CREATE TEMPORARY TABLE或DROP TEMPORARY TABLE语句操作。
    • 使用GTID复制从库中跳过错误时,不支持参数sql_slave_skip_counter的语法。传统复制可以使用此命令来跳过事务。

    如何开启GTID模式

    主要在Mysql配置文件中添加以下2个配置:

     #开启 gtid 模式 gtid_mode=on #配置不允许任何事务违反 GTID 一致性,用于保证数据一致性 enforce_gtid_consistency=on

    从库配置同步参数:使用协议_ID_position的主从关系。与之前的 Binlog 复制方式相比,Binlog 的 POS 站点改为 Master_Auto_position = 1 自动获取 Binlog POS 站点的配置。 MySQL服务重启或启动时2秒。

    enforce_gtid_consistency 此参数是必需的,仅启用复制安全事务。请参见上述步骤的具体限制。 gtid_execulated_compression_period 当启用 GTID 时,服务器会定期对 mysql.gtid_execulated 表进行压缩。通过设置 gtid_execulated_compression_period 系统变量,您可以控制压缩表之前允许的事务数,从而控制压缩率。如果设置为 0,则不进行压缩。gtid_mode是否启用GTID模式。 gtid_next表示下一个要执行的GTID信息。 gtid_owned该参数包含全局和会话。全局是指所有服务器都有GTID,会话级别是指当前客户端拥有的所有GTID。 gtid_purged已清除的 GTID 包含在 gtid_execulated 中。 session_track_gtids 此参数控制用于捕获的 GTID 以及 OK PACKAGE 中返回的跟踪器。

    如何确定复制方法是 GTID 还是 pos

    显示从站状态 检查 Auto_Position 字段。 0为Pos模式,1为Gtid模式。

     mysql> show slave status\G;                Auto_Position: 1

    gtid 改为 pos 模式:

     change master to master_auto_position=0;

    当前执行 gtid 信息

    mysql> SELECT @@GLOBAL.GTID_EXECUTED; +-------------------------------------------------------------------------------------+ | @@GLOBAL.GTID_EXECUTED                                                             | +-------------------------------------------------------------------------------------+ | 26630fed-fe68-11ec-b051-000c29509871:1-31, bf480f97-fe64-11ec-9b9d-000c29af7696:1-3 | +-------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)  mysql> SELECT * FROM mysql.gtid_executed; +--------------------------------------+----------------+--------------+ | source_uuid                         | interval_start | interval_end | +--------------------------------------+----------------+--------------+ | 26630fed-fe68-11ec-b051-000c29509871 |             1 |           29 | | 26630fed-fe68-11ec-b051-000c29509871 |             30 |           30 | | bf480f97-fe64-11ec-9b9d-000c29af7696 |             1 |           1 | +--------------------------------------+----------------+--------------+

    mysql.gtid_execulated 表由 MySQL 服务器提供,供内部使用。当在副本上禁用二进制日志记录时,它允许副本使用 GTID,并允许在二进制日志记录丢失时保留 GTID 状态。 RESET MASTER命令,gtid_executed表被删除。

    如果服务意外停止,则当前二进制日志文件中的gtid不会存储在gtid_executed表中。在恢复期间,这些 GTID 将添加到二进制日志文件表中,以便复制可以继续。

    关于 gtid_execulated 表

    当 MySQL 服务器启用二进制日志记录时,仅在二进制轮转期间更新 mysql.gtid_execulated 表。因为在重启等情况下,仍然可以通过扫描二进制日志来确定当前运行的GTID位置。 。

    简单来说,这个表会记录当前执行的GTID。 MySQL 5.6中必须配置log_slave_updates参数的最重要原因是slave重启后,无法知道当前slave运行的GTID位置,因为变量gtid_execulated是一个内存值:MySQL 5.7使得gtid_execulated 值是持久的。使用的技术与MySQL 5.6处理SQL线程存储位置的方式相同,这意味着GTID值被持久化在InnoDB表中并与用户事务一起提交以实现数据一致性。触发条件:

    • 如果binlog轮转(flush binlog_logs/达到max_binlog_size)或者服务关闭,所有写入binlog的Gtid信息都会写入到mysql.gtid_executed表中。
    • 从库:如果没有启用log_bin或者没有启用log_slave_updates,则从库会对应用中继日志中的每个事务执行一次mysql.gtid_execulated操作。

    简单分析GTID同步状态

    除了传统的binlog和pos值查看之外,GTID模式可以更直观地看到特定事务​​的执行情况。

     mysql> show slave status\G; *************************** 1. row ***************************                Slave_IO_State: Waiting for master to send event                  Master_Host: 192.168.77.135                  Master_User: repl                  Master_Port: 3306                Connect_Retry: 60              Master_Log_File: master-binlog.000043          Read_Master_Log_Pos: 666                Relay_Log_File: gtidb-relay-bin.000002                Relay_Log_Pos: 585        Relay_Master_Log_File: master-binlog.000043              Slave_IO_Running: Yes            Slave_SQL_Running: Yes              Replicate_Do_DB:           Replicate_Ignore_DB:             Replicate_Do_Table:         Replicate_Ignore_Table:       Replicate_Wild_Do_Table:   Replicate_Wild_Ignore_Table:                     Last_Errno: 0                    Last_Error:                   Skip_Counter: 0          Exec_Master_Log_Pos: 666              Relay_Log_Space: 792              Until_Condition: None                Until_Log_File:                 Until_Log_Pos: 0            Master_SSL_Allowed: No            Master_SSL_CA_File:             Master_SSL_CA_Path:               Master_SSL_Cert:             Master_SSL_Cipher:                 Master_SSL_Key:         Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No                Last_IO_Errno: 0                Last_IO_Error:                 Last_SQL_Errno: 0                Last_SQL_Error:   Replicate_Ignore_Server_Ids:               Master_Server_Id: 100                  Master_UUID: 26630fed-fe68-11ec-b051-000c29509871              Master_Info_File: /var/lib/mysql/master.info                    SQL_Delay: 0          SQL_Remaining_Delay: NULL      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates            Master_Retry_Count: 86400                  Master_Bind:       Last_IO_Error_Timestamp:       Last_SQL_Error_Timestamp:                 Master_SSL_Crl:             Master_SSL_Crlpath:             Retrieved_Gtid_Set: 26630fed-fe68-11ec-b051-000c29509871:32            Executed_Gtid_Set: 26630fed-fe68-11ec-b051-000c29509871:1-32, bf480f97-fe64-11ec-9b9d-000c29af7696:1-3                Auto_Position: 1          Replicate_Rewrite_DB:                   Channel_Name:             Master_TLS_Version:  1 row in set (0.00 sec)
    • GTID相关的密钥参数描述
    参数名称缩写简介
    retresded_gtid_set_set_gtids的主节点执行从属节点有
    Auto_Position自动维护position位置,显示为1

    gtid skip gtid_next

     stop slave; set gtid_next='26630fed-fe68-11ec-b051-000c29509871:37' begin;commit; set gtid_next='automatic'; start slave;

    注:此操作与sql_slave_skips数据一致性类似,不能保证数据一致性不会跳过。需要人工干预。强烈建议从Machinestarts开始read_only=1

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门