MySQL 8.0.35 基于GTID 主从复制安装增强半同步复制

基于二进制包最小化安装,GTID 主从复制 + 增强半同步复制架构

  • 主库:192.168.195.141
  • 从库:192.168.195.142

1. 环境信息

项目 主库 (Master) 从库 (Slave)
IP 192.168.195.141 192.168.195.142
MySQL版本 8.0.35(二进制包,glibc2.17) 8.0.35(二进制包,glibc2.17)
server-id 1 2
gtid_mode ON ON
半同步复制 rpl_semi_sync_master(增强半同步) rpl_semi_sync_slave(增强半同步)
角色 Master Slave

2. 清理环境(两台均执行)

如果之前已有 MySQL 实例运行,需先停止并清理数据目录。

bash 复制代码
systemctl stop mysqld
rm -rf /data/mysql/3306/data/*

3. 安装 MySQL(两台均执行)

3.1 创建用户与组

bash 复制代码
groupadd mysql
useradd -g mysql mysql

3.2 解压二进制包

bash 复制代码
cd /usr/local/
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz
tar xvf mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz
ln -s mysql-8.0.35-linux-glibc2.17-x86_64 mysql

验证:

bash 复制代码
/usr/local/mysql/bin/mysql --version
# /usr/local/mysql/bin/mysql  Ver 8.0.35 for Linux on x86_64 (MySQL Community Server - GPL)

3.3 创建数据目录

bash 复制代码
mkdir -p /data/mysql/3306/data
chown mysql.mysql /data/mysql/3306/data/

4. 编辑配置文件

4.1 主库 /etc/my.cnf(141)

ini 复制代码
[client]
socket = /data/mysql/3306/data/mysql.sock
[mysqld]
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
user    = mysql
port    = 3306
socket  = /data/mysql/3306/data/mysql.sock
log_error = /data/mysql/3306/data/mysqld.err
log_timestamps = system
log-bin = mysql-bin
server-id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl-semi-sync-master-enabled = 1

参数解释:

  • log-bin = mysql-bin:开启 binlog,主库必须开启。
  • server-id = 1:服务器唯一标识,主从环境中每个实例必须不同。
  • gtid_mode = ON:开启 GTID 复制。GTID(Global Transaction Identifier)为每个事务分配全局唯一ID,格式为 source_id:transaction_id,其中 source_id 是实例的 server_uuid,transaction_id 是事务序列号。
  • enforce_gtid_consistency = ON:强制 GTID 一致性,只允许事务安全的语句执行。如果要将 gtid_mode 设置为 ON,则此参数必须为 ON。
  • plugin-load = "rpl_semi_sync_master=semisync_master.so":启动时加载增强半同步主库插件,使实例启动后自动开启半同步复制功能,无需手动 INSTALL PLUGIN
  • rpl-semi-sync-master-enabled = 1:启动时自动开启主库半同步复制。配合 plugin-load 使用,重启后半同步自动生效。

4.2 从库 /etc/my.cnf(142)

ini 复制代码
[client]
socket = /data/mysql/3306/data/mysql.sock
[mysqld]
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
user    = mysql
port    = 3306
socket  = /data/mysql/3306/data/mysql.sock
log_error = /data/mysql/3306/data/mysqld.err
log_timestamps = system
server-id = 2
gtid_mode = ON
enforce_gtid_consistency = ON
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-slave-enabled = 1

与主库的区别:

  • server-id = 2:从库的 server-id 必须与主库不同。
  • 从库不需要显式配置 log-bin,MySQL 8.0 默认开启 binlog。
  • plugin-load = "rpl_semi_sync_slave=semisync_slave.so":启动时加载增强半同步从库插件。
  • rpl-semi-sync-slave-enabled = 1:启动时自动开启从库半同步复制。

5. 初始化实例(两台均执行)

bash 复制代码
/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --initialize

获取临时密码:

bash 复制代码
grep "temporary password" /data/mysql/3306/data/mysqld.err
# 主库:A temporary password is generated for root@localhost: -;iK2Wls,fek
# 从库:A temporary password is generated for root@localhost: <gtafDtrA9?Z

6. 配置 systemd 服务(两台均执行)

6.1 创建 /etc/systemd/system/mysqld.service

ini 复制代码
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/data/mysql/3306/data/mysqld.pid
TimeoutSec=0
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --pid-file=/data/mysql/3306/data/mysqld.pid --daemonize $MYSQLD_OPTS
EnvironmentFile=-/etc/sysconfig/mysql
LimitNOFILE = 65535
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false

6.2 创建 /etc/sysconfig/mysql

ini 复制代码
MYSQLD_OPTS=

7. 启动实例(两台均执行)

bash 复制代码
systemctl daemon-reload
systemctl start mysqld
systemctl enable mysqld

8. 修改 root 密码(两台均执行)

bash 复制代码
/usr/local/mysql/bin/mysql -uroot -S /data/mysql/3306/data/mysql.sock -p
sql 复制代码
alter user user() identified by 'Root@123456';

9. 搭建 GTID 主从复制

9.1 主库创建复制用户

sql 复制代码
-- 在主库(141)执行
CREATE USER 'repl'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

9.2 从库建立 GTID 复制

sql 复制代码
-- 在从库(142)执行
CHANGE MASTER TO
MASTER_HOST='192.168.195.141',
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_AUTO_POSITION=1,
GET_MASTER_PUBLIC_KEY=1;

START SLAVE;

参数解释:

  • MASTER_AUTO_POSITION=1:使用 GTID 自动定位,无需手动指定 MASTER_LOG_FILEMASTER_LOG_POS。从库 IO 线程连接主库时,会自动交换 GTID 信息,从库告诉主库自己已执行了哪些事务,主库只发送缺失的事务。

  • GET_MASTER_PUBLIC_KEY=1:MySQL 8.0 默认使用 caching_sha2_password 认证插件,非 SSL 连接时需获取主库公钥完成认证。
    GTID 复制 vs 位置点复制的区别:

  • 位置点复制:需要先在主库 mysqldump 备份(--master-data=2),scp 到从库恢复,再根据备份中的 CHANGE MASTER TO MASTER_LOG_FILE=..., MASTER_LOG_POS=... 建立复制。

  • GTID 复制:无需备份恢复,直接用 MASTER_AUTO_POSITION=1 建立复制,从库自动获取缺失的事务。简化了配置过程。

9.3 验证主从状态

sql 复制代码
-- 在从库(142)执行
show slave status\G)执行
show slave status\G
复制代码
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 192.168.195.141
                  Master_User: repl
                  Master_Port: 3306
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 1760
               Relay_Log_File: MYSQL142-relay-bin.000003
                Relay_Log_Pos: 1195
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
          Exec_Master_Log_Pos: 1760
        Seconds_Behind_Master: 0
             Master_Server_Id: 1
                  Master_UUID: 8f823f85-850e-11f1-b6e3-000c29048d1f
           Retrieved_Gtid_Set: 8f823f85-850e-11f1-b6e3-000c29048d1f:1-6
            Executed_Gtid_Set: 8f823f85-850e-11f1-b6e3-000c29048d1f:1-6,
                               98351ec0-850e-11f1-8d8e-000c29a59955:1
                Auto_Position: 1
         Get_master_public_key: 1

重点关注:

  • Slave_IO_Running: YesSlave_SQL_Running: Yes,两个均为 Yes 代表主从复制搭建成功。
  • Auto_Position: 1,表示使用 GTID 自动定位。
  • Retrieved_Gtid_Set:已从主库获取的 GTID 事务集。
  • Executed_Gtid_Set:已执行的 GTID 事务集。

10. 安装增强半同步复制

三种复制方式对比:

复制方式 原理 优缺点
异步复制 主库执行完事务立即返回客户端,不等待从库 性能好,但主库崩溃可能丢数据
全同步复制 主库执行完事务,等待所有从库都执行完才返回 数据最安全,但性能最差
半同步复制 主库执行完事务,等待至少一个从库接收到并写入 relay log 才返回 兼顾安全性和性能

传统半同步 vs 增强半同步:

方式 等待ACK时机 问题
传统半同步(AFTER_COMMIT) 引擎层提交之后等待从库ACK 主库已提交,其他会话可见数据;若此时主库崩溃切换,从库无此数据,出现数据不一致
增强半同步(AFTER_SYNC) 引擎层提交之前等待从库ACK 数据未提交,外界不可见;若主库崩溃切换,从库仍是老数据,不存在不一致问题

增强半同步是 MySQL 5.7 引入的"无损复制"(Lossless Replication),由参数 rpl_semi_sync_master_wait_point 控制,默认值为 AFTER_SYNC

10.1 加载半同步插件

注意: 由于我们已在 my.cnf 中配置了 plugin-loadrpl-semi-sync-*-enabled 参数,实例启动时会自动加载插件并开启半同步。以下为手动安装方式,供参考。

手动安装方式(主库):

sql 复制代码
-- 在主库(141)执行
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;

手动安装方式(从库):

sql 复制代码
-- 在从库(142)执行
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

判断插件是否加载成功:

sql 复制代码
SHOW PLUGINS;
-- 应看到:
-- | rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |  (主库)
-- | rpl_semi_sync_slave  | ACTIVE | REPLICATION | semisync_slave.so  | GPL |  (从库)

10.2 重启从库 IO 线程

重要: 安装半同步插件后,必须重启从库的 IO 线程,否则仍以异步模式运行。

sql 复制代码
-- 在从库(142)执行
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

10.3 验证半同步复制状态

主库:

sql 复制代码
-- 在主库(141)执行
SHOW STATUS LIKE 'Rpl_semi_sync_master_status';
复制代码
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON    |
+-----------------------------+-------+

从库:

sql 复制代码
-- 在从库(142)执行
SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
复制代码
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+

只有这两个变量都为 ON,才意味着半同步复制正在运行。


11. 验证主从复制 + 半同步

11.1 主库 show processlist

sql 复制代码
-- 在主库(141)执行
show processlist;
复制代码
+----+-----------------+---------------------+------+-------------+--------+--------------------------------------------------+------------------+
| Id | User            | Host                | db   | Command     | Time   | State                                            | Info             |
+----+-----------------+---------------------+------+-------------+--------+--------------------------------------------------+------------------+
|  5 | event_scheduler | localhost           | NULL | Daemon      | 234    | Waiting on empty queue                           | NULL             |
| 16 | repl            | 192.168.195.142:54622 | NULL | Binlog Dump GTID | 78 | Source has sent all binlog to replica; waiting for more updates | NULL |
| 20 | root            | localhost           | NULL | Query       | 0      | init                                             | show processlist |
+----+-----------------+---------------------+------+-------------+--------+--------------------------------------------------+------------------+

注意 :GTID 复制下,主库的 Binlog Dump 线程显示为 Binlog Dump GTID ,与位置点复制的 Binlog Dump 不同。

11.2 数据同步测试

主库写入测试数据:

sql 复制代码
-- 在主库(141)执行
CREATE DATABASE test_semi;
USE test_semi;
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(20));
INSERT INTO t1 VALUES (1,'semi_sync_test');
SELECT * FROM t1;
-- +----+----------------+
-- | id | name           |
-- +----+----------------+
-- |  1 | semi_sync_test |
-- +----+----------------+

从库查询验证:

sql 复制代码
-- 在从库(142)执行
SELECT * FROM test_semi.t1;
-- +----+----------------+
-- | id | name           |
-- +----+----------------+
-- |  1 | semi_sync_test |
-- +----+----------------+

数据一致,GTID + 增强半同步主从复制工作正常。

11.3 半同步事务统计验证

sql 复制代码
-- 在主库(141)执行
SHOW STATUS LIKE '%Rpl_semi%';
复制代码
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 1     |
| 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      | 325   |
| Rpl_semi_sync_master_tx_wait_time          | 325   |
| 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     |
+--------------------------------------------+-------+

重点关注:

  • Rpl_semi_sync_master_yes_tx = 1:通过半同步复制成功执行的事务数。
  • Rpl_semi_sync_master_no_tx = 0:退化为异步复制执行的事务数。为 0 表示没有发生退化。
  • Rpl_semi_sync_master_clients = 1:当前半同步复制从库的个数。

12. 半同步复制常用参数

12.1 主库参数

sql 复制代码
SHOW GLOBAL VARIABLES LIKE '%semi%';
复制代码
+-------------------------------------------+------------+
| 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 |
+-------------------------------------------+------------+

参数解释:

  • rpl_semi_sync_master_enabled = ON:主库半同步复制已开启。
  • rpl_semi_sync_master_timeout = 10000:等待从库 ACK 的超时时间,单位毫秒,默认 10 秒。超时后半同步退化为异步复制。如果不想退化,可设置为一个较大值。
  • rpl_semi_sync_master_wait_for_slave_count = 1:主库需要等待反馈的从库个数,默认为 1。
  • rpl_semi_sync_master_wait_no_slave = ON:当半同步从库数量小于 wait_for_slave_count 时,是否仍显示为半同步。ON 表示仍显示半同步,OFF 表示立即切换为异步。
  • rpl_semi_sync_master_wait_point = AFTER_SYNC:半同步等待点。AFTER_SYNC 为增强半同步(无损复制,默认值),AFTER_COMMIT 为传统半同步。

12.2 从库参数

sql 复制代码
SHOW GLOBAL VARIABLES LIKE '%semi%';
复制代码
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+

13. 半同步复制注意事项

  1. 半同步复制在主库和从库上必须同时开启。

  2. 从库响应的条件是事务对应的二进制日志事件写入到 Relay log 中。

  3. 超时退化 :在规定的时间内(由 rpl_semi_sync_master_timeout 参数决定,默认 10s),主库如果没有收到从库的响应,半同步复制会切换为异步复制。错误日志中会提示:

    复制代码
    [Warning] [MY-011153] [Repl] Timeout waiting for reply of binlog (file: mysql-bin.000004, pos: 9720138), semi-sync up to file mysql-bin.000004, position 9718392.

    后续如果收到了从库的响应,则异步复制又会恢复成半同步复制。如果不想半同步复制退化为异步复制,可将 rpl_semi_sync_master_timeout 设置为一个较大值。

  4. 一主多从:在一主多从的架构中,如果要开启半同步复制,并不要求所有的从库都是半同步复制。

  5. 延迟影响:半同步复制会给事务的提交带来一定程度的延迟,这个延迟至少是一个 TCP/IP 往返的时间。所以,建议半同步复制在低延时的网络中使用。


14. GTID 相关参数确认

14.1 主库(141)

复制代码
gtid_mode              = ON
enforce_gtid_consistency = ON
gtid_executed          = 8f823f85-850e-11f1-b6e3-000c29048d1f:1-6
gtid_next              = AUTOMATIC
gtid_purged            = 

14.2 从库(142)

复制代码
gtid_mode              = ON
enforce_gtid_consistency = ON
gtid_executed          = 8f823f85-850e-11f1-b6e3-000c29048d1f:1-6,
                         98351ec0-850e-11f1-8d8e-000c29a59955:1
gtid_next              = AUTOMATIC
gtid_purged            = 

说明:

  • 从库的 gtid_executed 包含两个 UUID 的事务:主库的 8f823f85-850e-11f1-b6e3-000c29048d1f:1-6(通过复制获取)和从库自身的 98351ec0-850e-11f1-8d8e-000c29a59955:1(本地事务)。
  • gtid_next = AUTOMATIC:自动获取下一个 GTID 值,默认值。

15. 连接信息

bash 复制代码
# 主库(141)
/usr/local/mysql/bin/mysql -uroot -S /data/mysql/3306/data/mysql.sock -p'Root@123456'

# 从库(142)
/usr/local/mysql/bin/mysql -uroot -S /data/mysql/3306/data/mysql.sock -p'Root@123456'

16. 完整配置文件

16.1 主库 /etc/my.cnf(141)--- 最终版

ini 复制代码
[client]
socket = /data/mysql/3306/data/mysql.sock
[mysqld]
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
user    = mysql
port    = 3306
socket  = /data/mysql/3306/data/mysql.sock
log_error = /data/mysql/3306/data/mysqld.err
log_timestamps = system
log-bin = mysql-bin
server-id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl-semi-sync-master-enabled = 1

16.2 从库 /etc/my.cnf(142)--- 最终版

ini 复制代码
[client]
socket = /data/mysql/3306/data/mysql.sock
[mysqld]
basedir = /usr/local/mysql
datadir = /data/mysql/3306/data
user    = mysql
port    = 3306
socket  = /data/mysql/3306/data/mysql.sock
log_error = /data/mysql/3306/data/mysqld.err
log_timestamps = system
server-id = 2
gtid_mode = ON
enforce_gtid_consistency = ON
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-slave-enabled = 1

17. GTID 复制的限制

  1. 不支持 CREATE TABLE ... SELECT ... 语句。从 MySQL 8.0.21 开始,该限制被取消。
  2. 不允许在事务、存储过程、函数、触发器中执行 CREATE TEMPORARY TABLEDROP TEMPORARY TABLE 操作。从 MySQL 8.0.13 开始,如果 binlog 格式为 ROW 或 MIXED,该限制被取消。
  3. 不能将 InnoDB 表和非 InnoDB 表放到一个事务内操作。
相关推荐
Kapaseker1 小时前
你是不是还没用过 select?实战 Kotlin select
android·kotlin
__Witheart__2 小时前
适用于Android内核boot.img生成流程
android·rockchip
木易 士心2 小时前
Jetpack Compose 深度解析:初始组合与重组的底层奥秘
android
GitLqr11 小时前
Flutter 无障碍开发实战:玩转 Semantics 解决视障用户使用痛点
android·flutter·dart
CodexDave13 小时前
MySQL事务隔离级别与MVCC机制解析
前端·数据库·mysql·nginx·性能优化·负载均衡
雨白15 小时前
掌握 NestedScrolling 嵌套滑动:手写仿知乎折叠主页
android
王琦031815 小时前
生产环境中使用通用二进制包安装
mysql
Xzaveir16 小时前
别把所有“认证”都塞进 AuthService:实名、一键登录与号码身份的领域拆分
android·人工智能
BerrySen17816 小时前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·人工智能