MySQL半同步复制与GTID实战指南

 更新时间:2026年04月13日 10:02:57   作者:Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.  
文章主要介绍了半同步复制和GTID的原理、配置、使用场景和最佳实践,文章还详细描述了启用和测试半同步复制的方法,以及在生产环境中推荐的配置策略,感兴趣的朋友一起看看吧

三、半同步复制与 GTID 实践笔记

3.1 半同步复制原理

  1. Master 执行事务后,暂不提交,等待至少一个 Slave 返回 ACK。
  2. Slave 的 IO 线程接收 Binlog 并写入 Relay Log 后,向 Master 返回 ACK。
  3. Master 收到 ACK 后提交事务,并向客户端返回成功。
  4. 若在超时时间内未收到 ACK(默认 10 秒),自动降级为异步复制。
  5. MySQL 5.6 使用 after_commit 模式(先提交再等 ACK),存在数据风险。MySQL 5.7+ 默认使用更安全的 AFTER_SYNC 模式。

3.2 gtid 模式

当为启用 gtid 时我们要考虑的问题

在 master 端的写入时多用户读写,在 slave 端的复制时单线程日志回放,所以 slave 端一定会延迟与 master 端

这种延迟在 slave 端的延迟可能会不一致,当 master 挂掉后 slave 接管,一般会挑选一个和 master 延迟日志最接近的充当新的 master

那么为接管 master 的主机继续充当 slave 角色并会指向到新的 master 上,作为其 slave

这时候按照之前的配置我们需要知道新的 master 上的 pos 的 id,但是我们无法确定新的 master 和 slave 之间差多

当激活 GITD 之后

当 master 出现问题后,slave2 和 master 的数据最接近,会被作为新的 master

slave1 指向新的 master,但是他不会去检测新的 master 的 pos id,只需要继续读取自己 gtid_next 即可

GTID 的简单工作流程

  1. 主库执行一个事务,提交后自动生成一个唯一的 GTID,记录到 binlog 里;
  2. 从库读取主库的 binlog,先记录这个 GTID(标记为 “已收到”);
  3. 从库执行这个事务,执行完后把 GTID 标记为 “已执行”;
  4. 主从同步时,从库只会向主库请求自己 “未执行” 的 GTID 对应的事务。

设置 gtid

#在master端和slave端开启gtid模式

[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node1 ~]# /etc/init.d/mysqld restart

[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=2
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node2 ~]# /etc/init.d/mysqld restart

[root@mysql-node3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=3
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
三台主机全部执行 /etc/init.d/mysqld restart

#查看gtid状态

mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery      | ON        |
| enforce_gtid_consistency         | ON        |
| gtid_executed                    |           |
| gtid_executed_compression_period | 0         |
| gtid_mode                        | ON        |
| gtid_next                        | AUTOMATIC |
| gtid_owned                       |           |
| gtid_purged                      |           |
| session_track_gtids              | OFF       |
+----------------------------------+-----------+
9 rows in set (0.01 sec)

gtid开启前

gtid开启后

#停止slave端
[root@mysql2 ~]# mysql -uroot -proot
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
[root@mysql3 ~]# mysql -uroot -proot
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

#开启slave端的gtid
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='swp', MASTER_PASSWORD='swp', MASTER_AUTO_POSITIO                                                 N=1;
Query OK, 0 rows affected, 7 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: swp
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 158
               Relay_Log_File: mysql3-relay-bin.000002
                Relay_Log_Pos: 375
        Relay_Master_Log_File: mysql-bin.000003
             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: 158
              Relay_Log_Space: 587
              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: 10
                  Master_UUID: 3f9a4795-332a-11f1-beae-000c29059db4
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Master_Retry_Count: 10
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)

3.3.启用半同步模式

在 master 端配置启用半同步模式

[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
rpl_semi_sync_master_enabled=1			#开启半同步功能
symbolic-links=0

[root@mysql-node1 ~]# mysql -uroot -proot
#安装半同步插件
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#查看插件情况
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
    ->  FROM INFORMATION_SCHEMA.PLUGINS
    ->  WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME          | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.01 sec)

#打开半同步功能
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
#查看半同步功能状态
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

在 slave 端开启半同步功能

[root@mysql-slave和slave2都做 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
rpl_semi_sync_slave_enabled=1			#开启半同步功能
symbolic-links=0

[root@mysql-slave和slave2都做# mysql -uroot -proot
mysql>  INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
Query OK, 0 rows affected (0.00 sec)
mysql> STOP SLAVE IO_THREAD;			#重启io线程,半同步才能生效
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.01 sec)
mysql>  SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

3.4.测试

在 master 端写入数据

mysql> insert into baibai.userlist values ('xixi','12340');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 2     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 4     |
| Rpl_semi_sync_master_no_times              | 1     |
| Rpl_semi_sync_master_no_tx  #未同步数据0笔  | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 633   |
| Rpl_semi_sync_master_tx_wait_time          | 633   |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx   #已同步数据1笔| 1     |
+--------------------------------------------+-------+

模拟故障:

#在slave端
[root@mysql-slave2]# mysql -uroot -proot
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
[root@mysql-slave]# mysql -uroot -proot
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

#在master端插入数据
mysql> insert  into lee.userlist values ('baibai','12340');
Query OK, 1 row affected (10.00 sec)			#10秒超时
mysql>  SHOW STATUS LIKE 'Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 2     |
| Rpl_semi_sync_master_no_times              | 1     |
| Rpl_semi_sync_master_no_tx                 | 1     |		#一笔数据为同步
| Rpl_semi_sync_master_status                | OFF   |		#自动转为异步模式,当slave恢复
| Rpl_semi_sync_master_timefunc_failures     | 0     |		#会自动恢复
| Rpl_semi_sync_master_tx_avg_wait_time      | 981   |
| Rpl_semi_sync_master_tx_wait_time          | 981   |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

3.5 核心参数说明

参数说明
rpl_semi_sync_master_enabledMaster 是否启用半同步
rpl_semi_sync_slave_enabledSlave 是否启用半同步
rpl_semi_sync_master_timeout等待 ACK 超时时间(毫秒),默认 10000
rpl_semi_sync_master_wait_for_slave_count至少需要等待几个 Slave 返回 ACK
rpl_semi_sync_master_wait_pointAFTER_SYNC(推荐) / AFTER_COMMIT
gtid_mode是否开启 GTID
enforce_gtid_consistency强制 GTID 一致性,开启 GTID 时必须启用

3.6 最佳实践建议

  1. 生产环境推荐 GTID + 半同步组合使用,兼顾高可用与数据一致性。
  2. 设置合理的 rpl_semi_sync_master_timeout(如 5–10 秒),避免网络抖动影响写入。
  3. 监控 Rpl_semi_sync_master_clientsRpl_semi_sync_master_status,及时发现半同步降级。
  4. 主从切换时,GTID 模式可大幅简化操作,无需手动找 position。
    _COMMIT | |gtid_mode | 是否开启 GTID | |enforce_gtid_consistency` | 强制 GTID 一致性,开启 GTID 时必须启用 |

3.6 最佳实践建议

  1. 生产环境推荐 GTID + 半同步组合使用,兼顾高可用与数据一致性。
  2. 设置合理的 rpl_semi_sync_master_timeout(如 5–10 秒),避免网络抖动影响写入。
  3. 监控 Rpl_semi_sync_master_clientsRpl_semi_sync_master_status,及时发现半同步降级。
  4. 主从切换时,GTID 模式可大幅简化操作,无需手动找 position。
  5. 半同步降级为异步后,待从库恢复会自动切回,无需人工干预。

到此这篇关于MySQL半同步复制与GTID实战指南的文章就介绍到这了,更多相关MySQL半同步复制与GTID内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql 转换NULL数据方法(必看)

    mysql 转换NULL数据方法(必看)

    下面小编就为大家带来一篇mysql 转换NULL数据方法(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • node连接mysql数据库遇到的问题和解决方案

    node连接mysql数据库遇到的问题和解决方案

    这篇文章主要介绍了node连接mysql数据库遇到的问题和解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • MySQL主从切换的超详细步骤

    MySQL主从切换的超详细步骤

    一般来说在客户的生产环境,每隔一段实践就需要进行MySQL数据库的功能演练,主从切换,数据同步,数据备份等,下面这篇文章主要给大家介绍了关于MySQL主从切换的超详细步骤,需要的朋友可以参考下
    2022-06-06
  • MySQL  外键(foreign key)约束的作用和使用

    MySQL  外键(foreign key)约束的作用和使用

    外键约束是用于建立两个表之间关系的一种约束,本文主要介绍了MySQL外键约束详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Mysql Sql 语句练习题(50道)

    Mysql Sql 语句练习题(50道)

    mysql一直作为比较热门的数据库存储,搭配php使用简直是绝配,mysql的sql语句也是很重要的一门课,这里为大家分享一下sql语句,大家可以试试
    2020-12-12
  • Mysql实时备份实现方法

    Mysql实时备份实现方法

    这篇文章主要介绍了Mysql实现实时备份,需要的朋友可以参考下
    2016-02-02
  • MySQL 8.0.0开发里程碑版发布!

    MySQL 8.0.0开发里程碑版发布!

    MySQL 8.0.0开发里程碑版发布,感兴趣的小伙伴们可以阅读一下
    2016-09-09
  • mysql 8.0.12 简单安装教程

    mysql 8.0.12 简单安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.12 简单安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • MySQL中可为空的字段设置为NULL还是NOT NULL

    MySQL中可为空的字段设置为NULL还是NOT NULL

    今天小编就为大家分享一篇关于MySQL中可为空的字段设置为NULL还是NOT NULL,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • MySQL中隔离级别RC与RR的区别及说明

    MySQL中隔离级别RC与RR的区别及说明

    这篇文章主要介绍了MySQL中隔离级别RC与RR的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论