当前位置: 代码网 > it编程>数据库>Mysql > MySQL半同步复制与GTID实战指南

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

2026年04月13日 Mysql 我要评论
三、半同步复制与 gtid 实践笔记3.1 半同步复制原理master 执行事务后,暂不提交,等待至少一个 slave 返回 ack。slave 的 io 线程接收 binlog 并写入 relay

三、半同步复制与 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内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com