背景:
项目上需要升级原有的mysql5.7数据库到mysql8,并搭建主从,一番操作之后搭好了
步骤略显繁琐,整理下以备日后查阅
下面为搭建步骤
主要分两步:升级主库到mysql8,搭建mysql主从
1.停掉前后端服务,防止有新数据入库
2.停掉 mysql5.7 从库进程,停掉备库
3.通过mysqldump 备份mysql5.7主库数据
docker run --rm -v /data/backups/mysql:/backups mysql:5.7.44 \ mysqldump -h 主库ip -uroot -p'密码' --quick --triggers --routines --events --single-transaction --result-file=/backups/数据库名.sql 数据库名
处理备份文件编码,把5.7数据库编码转为mysql8默认编码
sed -i "s|utf8mb4_general_ci|utf8mb4_0900_ai_ci|g" 数据库名.sql sed -i "s|utf8mb4_bin|utf8mb4_0900_ai_ci|g" 数据库名.sql
4.停掉mysql5.7主库
5.通过docker 搭建mysql8主库
新建目录mysql8,编写 docker-compose.yaml 文件
version: '3.1' services: mysql8-001: container_name: mysql8-001 hostname: mysql8-001 image: mysql:8.0.32 restart: always ports: - 3306:3306 environment: TZ: Asia/Shanghai MYSQL_ROOT_HOST: '%' MYSQL_ROOT_PASSWORD: 'root密码' MYSQL_USER: 普通账号 MYSQL_PASSWORD: 普通账号密码 command: --max_connections=1000 --default-time-zone='+8:00' --explicit_defaults_for_timestamp=true --lower_case_table_names=1 volumes: - ./data:/var/lib/mysql - ./logs:/var/log/mysql - ./conf/my.cnf:/etc/mysql/my.cnf - ./init:/docker-entrypoint-initdb.d
知识点补充:
MySQL 8遵循分层加载原则,按以下顺序读取配置文件(后读取的文件会覆盖前者的同名参数):
-
/etc/my.cnf(全局主配置) -
/etc/mysql/my.cnf(系统级配置) -
/etc/mysql/conf.d/*.cnf(模块化配置片段) -
~/.my.cnf(用户级配置,仅限当前用户)
进入mysql8容器,可以看到有/etc/my.cnf 全局配置,里面已经包含了基础配置,所以新增的my.cnf 只用加要用的就行

# For advice on how to change settings please see # http://dev.mysql.com/doc/refman/8.0/en/server-configuration-defaults.html [mysqld] # # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M # # Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin # # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M # Remove leading # to revert to previous value for default_authentication_plugin, # this will increase compatibility with older clients. For background, see: # https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_default_authentication_plugin # default-authentication-plugin=mysql_native_password skip-host-cache skip-name-resolve datadir=/var/lib/mysql socket=/var/run/mysqld/mysqld.sock secure-file-priv=/var/lib/mysql-files user=mysql pid-file=/var/run/mysqld/mysqld.pid [client] socket=/var/run/mysqld/mysqld.sock !includedir /etc/mysql/conf.d/
在当前目录下新建 conf文件夹,并新建my.cnf文件
[mysqld] #server id server-id = 1 # 主库唯一标识符 #gtid: gtid_mode = on # 启用GTID,简化复制管理 enforce_gtid_consistency = on # 强制gtid一致性,开启后对于特定create table不被支持 #binlog log_bin = mysql-bin # 启用二进制日志 binlog_format = row # 强烈建议,其他格式可能造成数据不一致 #ssl ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem # 增加内存缓存 # InnoDB Buffer Pool Settings innodb_buffer_pool_size = 10G innodb_buffer_pool_instances = 8 # InnoDB Log File and Flush Settings innodb_flush_log_at_trx_commit = 2 innodb_log_file_size = 256M # Binary Log Syncing sync_binlog = 1000 # Temporary Table Settings tmp_table_size = 256M max_heap_table_size = 256M # Sort Buffer Size sort_buffer_size = 8M
参数详解:
(1)前三项都是主从配置,注意主从服务器id不要重复就行
(2)ssl配置是由于 后面配置从库报错:
Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure conne
原因:该错误表明 MySQL 8.0+ 主从复制因 caching_sha2_password 插件要求安全连接(SSL/TLS)而失败。
查看mysql data目录是有生成 ssl文件的,所以配置文件直接加上,指定上ssl文件后,报错解决

(3)增加内存缓存是为了优化磁盘io瓶颈,如果是ssd硬盘,可以忽略
在docker-compose.yml文件同级目录执行命令,启动mysql8容器
docker-compose up -d
至此,mysql主库搭建完成
6.在主库上新建数据库,导入数据
这里把备份sql文件放到 mysql8/init 文件夹下操作
7.修改后端程序mysql配置,尤其注意mysql驱动,版本号最好和mysql服务器保持一致
8.后端发版,开启前端,测试功能是否正常
一切测试无误,表示msyql8数据库升级完成
下面开始搭建mysql8主从
9.搭建mysql8从库
在另一台服务器搭建从库
新建目录mysql8,编写 docker-compose.yaml 文件
version: '3.1' services: mysql8-002: container_name: mysql8-002 hostname: mysql8-002 image: mysql:8.0.32 restart: always ports: - 3306:3306 environment: TZ: Asia/Shanghai MYSQL_ROOT_HOST: '%' MYSQL_ROOT_PASSWORD: 'root密码' MYSQL_USER: 普通账号 MYSQL_PASSWORD: 普通账号密码 command: --max_connections=1000 --default-time-zone='+8:00' --explicit_defaults_for_timestamp=true --lower_case_table_names=1 volumes: - ./data:/var/lib/mysql - ./logs:/var/log/mysql - ./conf/my.cnf:/etc/mysql/my.cnf - ./init:/docker-entrypoint-initdb.d
在当前目录下新建 conf文件夹,并新建my.cnf文件
[mysqld] #server id server-id = 2 # 从库唯一标识符 #gtid: gtid_mode = on # 启用GTID,简化复制管理 enforce_gtid_consistency = on # 强制gtid一致性,开启后对于特定create table不被支持 #binlog log_bin = mysql-bin binlog_format = row # 强烈建议,其他格式可能造成数据不一致 #ssl ssl-ca = /var/lib/mysql/ca.pem ssl-cert = /var/lib/mysql/server-cert.pem ssl-key = /var/lib/mysql/server-key.pem #relay log log_slave_updates = 1 # 记录从库上的更新操作 read_only = 1 # 从库设置为只读 relay_log = mysql-relay-bin # 中继日志配置 #增加内存缓存 # InnoDB Buffer Pool Settings innodb_buffer_pool_size = 10G innodb_buffer_pool_instances = 8 # InnoDB Log File and Flush Settings innodb_flush_log_at_trx_commit = 2 innodb_log_file_size = 256M # Binary Log Syncing sync_binlog = 1000 # Temporary Table Settings tmp_table_size = 256M max_heap_table_size = 256M # Sort Buffer Size sort_buffer_size = 8M
在docker-compose.yml文件同级目录执行命令,启动mysql8容器
docker-compose up -d
至此,mysql8从库搭建完成
这里会有警告:
[Warning] [MY-013595] [Server] Failed to initialize TLS for channel: mysql_main
[Warning] [MY-010069] [Server] Failed to set up SSL because of the following SSL library error: SSL_CTX_set_default_verify_paths failed
原因:MySQL无法找到或访问默认的SSL证书验证路径。
这是由于mysq8 镜像发现是从库,没有新建ssl文件所致,从库一般也不需要ssl证书,所以可以忽略
10.配置主从
(1)在主库上新建主从复制账号
CREATE USER 'repl_user'@'从库ip' IDENTIFIED BY '密码'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'从库ip'; FLUSH PRIVILEGES;
(2)在主库上备份从库数据文件
#进入主库容器 docker exec -it mysq8-001 /bin/bash #备份sql文件 mysqldump --single-transaction -uroot -p'密码' --master-data=2 --set-gtid-purged=ON --all-databases --triggers --routines --events --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats > /docker-entrypoint-initdb.d/mysql_all_backup.sql
使用mysqldump备份主库数据,导出时需排除mysql.innodb_table_stats和mysql.innodb_index_stats表,因为这些表在导入8.0版本时会出现访问系统表错误(Bug 92675)。
为了让从库全量备份主库数据,这里使用 --all-databases 全量备份数据
这里加上--master-data=2参数,自动记录主库备份时的二进制日志文件名和位置在备份文件中
备份后的文件在主库宿主机的 mysql/init 文件夹下
(3)将备份数据导入从库
将备份文件上传至从库 mysql8/init 文件下
#进入从库容器 docker exec -it mysql8-002 /bin/bash #进入数据库 mysql -uroot -p'密码' #导入数据 source /docker-entrypoint-initdb.d/mysql_all_backup.sql
(4)在从库上配置主库信息
接着上面继续执行命令
CHANGE MASTER TO MASTER_HOST='主库ip',
MASTER_PORT='3306', MASTER_USER='repl_user', MASTER_PASSWORD='密码', MASTER_LOG_FILE='mysql-binlog.000005', # 替换为实际文件名 MASTER_LOG_POS=7565; # 替换为实际位置
最后两个信息,在备份sql文件中可以看到
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-binlog.000005', MASTER_LOG_POS=7565;

(5)启动复制进程
继续执行命令
START SLAVE;
(6)验证复制状态
SHOW SLAVE STATUS\G
确保Slave_IO_Running和Slave_SQL_Running都为Yes,表示复制正常运行。

11.数据一致性检查
在主库上创建一个测试表并插入数据,检查从库是否同步:
-- 主库上
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE test_table (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
-- 从库上查询数据
USE testdb;
SELECT * FROM test_table;
12.遇到的问题
到这里是不是有个疑问,就是为啥还在用 8.0.32版本,8.0.42版本都出来了
那是因为之前搭建报错了
Fatal glibc error: CPU does not support x86-64-v2
解决办法:这个服务器没办法换,无奈只能使用旧版本,退而求其次了
13.基于 xtrabackup 搭建主从和这个类似,唯一区别就是查看binlog信息方式不一样
#查看备份文件中binlog的相关信息,使用命令如下
cat /data/xtrabackup/xtrabackup_binlog_info
#可以看到如下所示主库备份完成时的binlog信息
mysql-bin.000032 49968

参考文档:https://www.cnblogs.com/liuhuayiye/p/16808949.html
14.性能优化
减少锁操作:优化SQL语句,减少锁的使用,提高复制效率。
关于主从复制模式:
MySQL主从复制主要有异步复制、半同步复制、全同步复制三种模式,它们在数据一致性、性能、复杂度等方面各有优缺点,以下为具体分析:
异步复制
- 模式:MySQL默认的复制模式。主库执行完客户端提交的事务后,会立即将结果返回给客户端,并不关心从库是否已经接收并处理。
- 优点
- 性能高:主库的写入操作不受从库影响,响应速度快,能充分发挥主库的处理能力。
- 实现简单:配置和管理相对容易,不需要复杂的机制来保证主从同步的严格一致性。
- 缺点
- 数据一致性弱:如果主库崩溃,已经提交的事务可能没有传到从库,导致主从数据不一致,存在数据丢失的风险。
- 容灾能力有限:在主库故障时,从库可能缺少部分数据,影响业务的连续性。
半同步复制
- 模式:介于异步复制和全同步复制之间。主库在执行完客户端提交的事务后,会等待至少一个从库接收到并写入中继日志(relay log)中才返回给客户端。
- 优点
- 数据安全性较高:相比异步复制,减少了数据丢失的风险,能保证至少有一个从库与主库的数据保持一致。
- 平衡性能与一致性:在性能和数据一致性之间取得了一定的平衡,既不像异步复制那样存在较大的数据丢失风险,也不会像全同步复制那样对性能产生严重影响。
- 缺点
- 性能略低:由于需要等待至少一个从库的确认,主库的提交延迟会增加,性能会比异步复制略低。
- 存在单点风险:如果等待确认的从库出现故障,主库可能会阻塞,影响整个系统的可用性。
全同步复制
- 模式:主库执行完一个事务后,需要等待所有从库都执行了该事务才能返回给客户端。
- 优点
- 数据一致性最强:能确保主库和所有从库的数据完全一致,几乎不存在数据丢失的风险。
- 容灾能力强:在主库故障时,任何一个从库都可以接管主库的工作,保证业务的连续性。
- 缺点
- 性能影响大:需要等待所有从库的确认,主库的提交延迟会显著增加,性能会受到严重影响,不适合高并发的写场景。
- 配置复杂:需要确保所有从库都能正常工作,对网络和系统环境的要求较高,配置和管理难度较大。
关于并行复制:
在MySQL主从复制的经典分类中,并行复制(Multi-Threaded Slave, MTS)通常不被单独列为与异步/半同步/全同步同级的“复制模式”,而是作为对半同步或异步复制架构的性能优化手段。以下是其未被纳入传统分类的原因及核心解析:
一、为何传统分类未包含并行复制?
-
定位差异
- 异步/半同步/全同步:是主从数据同步的底层机制,核心解决数据一致性强度(如是否等待从库确认、等待多少从库确认)。
- 并行复制:是从库回放事务的执行策略,核心解决从库性能瓶颈(通过多线程并行执行事务),与主从同步的触发机制(异步/半同步)无关。
类比:同步机制是“何时开始运输数据”,并行复制是“从库如何高效处理数据”。
-
兼容性设计
- 并行复制可叠加在异步或半同步复制上:
- 异步+并行:主库不等待,从库并行回放(牺牲部分一致性,换取高吞吐)。
- 半同步+并行:主库等待至少一个从库确认,从库并行回放(平衡一致性与性能)。
- 全同步复制因需等待所有从库,通常不与并行复制组合(性能代价过高)。
- 并行复制可叠加在异步或半同步复制上:
二、并行复制的核心机制与价值
-
突破单线程瓶颈
- 传统从库使用单线程(SQL线程)按顺序回放主库binlog,在高并发写入时易成瓶颈。
- 并行复制通过多工作线程并行执行不冲突的事务,显著提升从库回放速度。
-
关键参数与策略
-
slave_parallel_workers:控制并行线程数(如设为4,则启动4个工作线程)。 - 并行策略:
- 库级并行(MySQL 5.6):不同库的事务可并行(依赖
--replicate-wild-do-table过滤)。 - 组提交并行(MySQL 5.7+):基于组提交(Group Commit)的
LOGICAL_CLOCK模式,同一组提交的事务可并行(因事务ID连续,无冲突)。 - 基于写集并行(MySQL 8.0+):通过
WRITESET或WRITESET_SESSION检测事务冲突,进一步优化并行度。
- 库级并行(MySQL 5.6):不同库的事务可并行(依赖
-
三、并行复制的优缺点
| 维度 | 优点 | 缺点 |
|---|---|---|
| 性能 | 显著提升从库回放速度,减少主从延迟(尤其高并发场景)。 | 需合理配置并行线程数,过多线程可能导致CPU竞争,过少则效果有限。 |
| 一致性 | 不影响主从同步机制(异步/半同步)的数据一致性强度。 | 事务冲突(如依赖同一行数据)仍需串行执行,可能影响并行效率。 |
| 复杂度 | 配置简单(调整slave_parallel_workers即可),MySQL 8.0+自动优化并行策略。 |
需监控并行线程状态(如SHOW PROCESSLIST),避免线程饥饿或阻塞。 |
| 适用场景 | 适用于读多写少业务(如报表查询),或主库高并发写入需从库快速回放的场景。 | 不适合对一致性要求极端敏感的场景(如金融交易),因并行执行可能引入短暂延迟。 |
四、并行复制的典型应用场景
- 高并发写入+读扩展
- 主库处理高并发写入,从库通过并行复制快速回放,支撑读请求(如电商订单系统)。
- 主从延迟优化
- 主从延迟过高时,启用并行复制可快速追平数据(如日志分析业务)。
- 混合负载场景
- 结合半同步复制保障核心数据一致性,并行复制加速非核心数据回放(如用户行为日志与交易数据分离)。
五、如何选择并行复制策略?
- MySQL 5.6及以下
- 使用库级并行(需分库设计),或升级至更高版本。
- MySQL 5.7+
- 启用
LOGICAL_CLOCK模式,利用组提交特性提升并行度。
- 启用
- MySQL 8.0+
- 优先选择
WRITESET模式,通过冲突检测实现更细粒度的并行。
- 优先选择
- 监控与调优
- 监控
Seconds_Behind_Master(主从延迟)和Slave_running状态,调整slave_parallel_workers和并行策略。
- 监控
总结:并行复制的定位与价值
- 非独立模式:并行复制是从库执行引擎的优化技术,而非主从同步的底层机制。
- 性能增益:通过多线程并行执行事务,显著提升从库回放速度,尤其适合高并发写入场景。
- 兼容性与选择:可与异步/半同步复制结合使用,需根据业务对一致性和性能的要求选择策略(如金融业务用半同步+低并行度,日志分析用异步+高并行度)。
通过合理配置并行复制,MySQL可在保障数据一致性的同时,有效解决从库性能瓶颈,适应多样化的业务需求。
可以按需求选择复制模式:注意并行复制和半同步模式是互斥的,不能同时开启
(1)并行复制:启用并行复制可以提高复制性能。在从库配置文件中添加:
[mysqld]
slave_parallel_type = LOGICAL_CLOCK
slave_parallel_workers = 4
(2)半同步配置
在MySQL 8中,通过my.cnf配置主库和从库启用半同步复制(Semi-Synchronous Replication)需要分别设置主库和从库的参数。以下是详细配置步骤及关键说明:
一、半同步复制原理简述
半同步复制是传统异步复制的增强版,主库在提交事务时需等待至少一个从库接收事务并记录到Relay Log后才会返回客户端成功响应,提升数据一致性(但会轻微增加延迟)。
二、主库(Master)配置
在主库的my.cnf中添加以下参数:
[mysqld] # 1. 启用半同步主库插件(需确保插件文件存在) plugin-load = "rpl_semi_sync_master=semisync_master.so" # 2. 启用半同步主库功能 rpl_semi_sync_master_enabled = ON # 3. 等待从库响应的超时时间(毫秒),超时后降级为异步复制 rpl_semi_sync_master_timeout = 1000 # 推荐值:1000ms(1秒) # 4. 等待从库数量的阈值(MySQL 8.0.26+支持,默认1) # rpl_semi_sync_master_wait_for_slave_count = 1
关键参数说明:
-
rpl_semi_sync_master_enabled = ON:启用主库半同步功能。 -
rpl_semi_sync_master_timeout:避免因从库故障导致主库阻塞,超时后自动降级为异步复制。 -
rpl_semi_sync_master_wait_for_slave_count(可选):指定需等待的从库数量(MySQL 8.0.26+新增,默认值为1)。
三、从库(Slave)配置
在从库的my.cnf中添加以下参数:
[mysqld] # 1. 启用半同步从库插件 plugin-load = "rpl_semi_sync_slave=semisync_slave.so" # 2. 启用半同步从库功能 rpl_semi_sync_slave_enabled = ON # 3. 确保从库IO线程已启用(默认已启用,显式声明更清晰) slave_parallel_workers = 0 # 若使用并行复制,需设为0(半同步与并行复制互斥)
关键参数说明:
-
rpl_semi_sync_slave_enabled = ON:启用从库半同步功能。 -
slave_parallel_workers = 0:半同步复制与并行复制(slave_parallel_workers > 0)冲突,需禁用并行复制。
四、配置后操作步骤
-
重启MySQL服务:
# 主库和从库均需重启 systemctl restart mysqld -
验证插件是否加载:
-- 主库执行 SHOW PLUGINS WHERE NAME LIKE '%semi%'; -- 从库执行 SHOW PLUGINS WHERE NAME LIKE '%semi%';
预期结果:
rpl_semi_sync_master(主库)或rpl_semi_sync_slave(从库)的STATUS为ACTIVE。 -
验证半同步状态:
-- 主库查看半同步统计信息 SHOW STATUS LIKE 'Rpl_semi_sync%'; -- 从库确认半同步是否启用 SHOW VARIABLES LIKE 'rpl_semi_sync_slave_enabled';
关键指标:
Rpl_semi_sync_master_clients:已连接的半同步从库数量。Rpl_semi_sync_master_yes_tx:主库通过半同步提交的事务数。Rpl_semi_sync_master_no_tx:因超时降级为异步复制的事务数。
五、常见问题与解决
-
插件加载失败:
- 原因:插件文件路径错误或权限不足。
- 解决:
-- 确认插件文件路径 SHOW VARIABLES LIKE 'plugin_dir'; -- 检查文件是否存在 ls -l /usr/lib/mysql/plugin/semisync_master.so # 主库 ls -l /usr/lib/mysql/plugin/semisync_slave.so # 从库
-
半同步未生效:
- 检查步骤:
- 确认主从库均已启用半同步(
SHOW VARIABLES)。 - 检查主库是否收到从库ACK(
SHOW STATUS LIKE 'Rpl_semi_sync%')。 - 确认网络延迟未导致超时(调整
rpl_semi_sync_master_timeout)。
- 确认主从库均已启用半同步(
- 检查步骤:
-
与并行复制冲突:
- 现象:半同步复制无法与
slave_parallel_workers > 0同时启用。 - 解决:根据业务需求选择其一:
- 高一致性需求:半同步复制(
slave_parallel_workers = 0)。 - 高性能需求:并行复制(
rpl_semi_sync_slave_enabled = OFF)。
- 高一致性需求:半同步复制(
- 现象:半同步复制无法与
六、完整配置示例
主库my.cnf
[mysqld] server-id = 1 log_bin = mysql-bin binlog_format = ROW # 半同步主库配置 plugin-load = "rpl_semi_sync_master=semisync_master.so" rpl_semi_sync_master_enabled = ON rpl_semi_sync_master_timeout = 1000
从库my.cnf
[mysqld] server-id = 2 relay_log = mysql-relay-bin read_only = ON # 半同步从库配置 plugin-load = "rpl_semi_sync_slave=semisync_slave.so" rpl_semi_sync_slave_enabled = ON slave_parallel_workers = 0 # 禁用并行复制
七、总结
- 主库:需启用
rpl_semi_sync_master插件并设置超时时间。 - 从库:需启用
rpl_semi_sync_slave插件并禁用并行复制。 - 验证:通过
SHOW PLUGINS和SHOW STATUS确认配置生效。 - 注意事项:半同步复制会增加主库延迟,需根据业务场景权衡一致性与性能。
浙公网安备 33010602011771号