MySQL 8.0.35主从复制搭建实战:CentOS 7下完整SOP与GTID配置

发布时间:2026/10/3 3:32:43
MySQL 8.0.35主从复制搭建实战:CentOS 7下完整SOP与GTID配置 做MySQL运维的朋友应该都有这种体会版本越新坑越深但主从复制永远是躲不掉的基本功。手上这套 MySQL 8.0.35 主从复制搭建 SOP跑在 CentOS 7 上是我在测试环境反复验证过几轮之后整理出来的完整流程。从虚拟机准备、二进制安装到主从账号创建、初始数据迁移、复制通道启动和同步验证每一步都尽量落到可执行命令。刚接手MySQL运维的同学可以照着抄老手也可以拿这份文档当模板把细节补进自己的操作手册里。这次选用 CentOS 7 x86_64 minimal 2009 镜像在 VirtualBox 里建两台虚拟机作为主从节点。系统层面只做最小化安装所有MySQL目录、日志、数据路径都自定义方便后续扩展。MySQL 使用 8.0.35 官方二进制版不依赖操作系统的 yum 仓库版本可控升级路径也清晰。整个 SOP 会覆盖环境规划、安装初始化、复制配置、数据迁移、验证监控、故障排查目标是搭一套干净、可复盘、能直接交接给团队的主从环境。1. 方案设计与环境规划1.1 主从节点角色分配与版本选型搭建主从复制之前第一件事不是敲命令而是把架构想清楚。我这边规划了两台节点主库 master 负责业务读写从库 replica 承担读流量和备份任务。IP 规划固定下来后面所有配置文件、授权语句、复制通道都会用这两个地址避免临场手写导致连接混乱。主库 master10.0.0.1CentOS 7 最小化安装4核8G内存磁盘40G。从库 replica10.0.0.2CentOS 7 最小化安装4核8G内存磁盘40G。MySQL 版本选择 8.0.35而不是 5.7一个重要原因是 8.0 是当前主流长期支持分支GTID、参数化密码、InnoDB 增强这些能力都比 5.7 完善。8.0.35 属于 8.0 系列的后期维护版本bug 收敛相对稳定适合作为 SOP 基线。如果你所在团队还在用 5.7这套流程的大部分逻辑仍然适用但命令差异我会在文中标注。CentOS 7 自带的 MySQL 仓库版本很旧而且通过 yum 安装会把/etc/my.cnf、目录权限、systemd 单元全部交给包管理一旦想要自定义数据目录、日志路径需要额外处理。所以这里采用官方二进制包/usr/local/mysql做软链数据目录独立放在/data/mysql下。这样主从两台机器的目录结构完全一致写 SOP 时不需要区分环境。1.2 系统基础配置与安全基线系统装完后不要急着下载 MySQL。先把基础环境整理干净否则后面排查问题时会分不清是系统问题还是数据库问题。第一步是关闭防火墙和 SELinux。测试环境可以直接systemctl stop firewalld并systemctl disable firewalldSELinux 也改成 permissive。生产环境不建议关防火墙应该放行 3306 端口做细粒度控制。CentOS 7 里卸载自带的 mariadb-libs 也要提前做掉否则会和 MySQL 二进制冲突。systemctl stop firewalld systemctl disable firewalld sed -i s/SELINUXenforcing/SELINUXpermissive/g /etc/selinux/config yum remove -y mariadb-libs接下来配置/etc/hosts让两台机器可以通过主机名互相访问。主从复制过程中如果有 DNS 抖动会导致 IO 线程频繁重连用 hosts 静态解析能省掉这类问题。cat /etc/hosts EOF 10.0.0.1 master 10.0.0.2 replica EOF还要保证时间同步。MySQL 的 binlog 和 relay log 都依赖时间戳如果主从时钟偏差太大日志轮转、事务切分都可能出现诡异现象。CentOS 7 默认用 chrony启动后确认chronyc sources能看到同步源即可。这一步看起来跟复制没直接关系但经验告诉我很多复制延迟问题其实是系统时钟漂移引起的。2. MySQL 8.0.35 二进制安装与目录规划2.1 官方二进制包的下载与解压我习惯把源码包放在/usr/local/src然后解压到/usr/local下再创建软链。这样以后升级时只需要换软链指向新目录回滚也方便。cd /usr/local/src wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.35-linux-glibc2.12-x86_64.tar.xz tar xf mysql-8.0.35-linux-glibc2.12-x86_64.tar.xz -C /usr/local/ ln -s /usr/local/mysql-8.0.35-linux-glibc2.12-x86_64 /usr/local/mysql然后创建系统用户和目录。MySQL 二进制包不允许用 root 初始化数据目录所以必须有一个专用账号。目录规划我固定成/data/mysql/data、/data/mysql/binlog、/data/mysql/relaylog、/data/mysql/tmp这样不管是备份、归档还是排错路径一眼就能看懂。useradd -r -s /sbin/nologin mysql mkdir -p /data/mysql/{data,binlog,relaylog,tmp} chown -R mysql:mysql /data/mysql /usr/local/mysql注意chown必须同时给/usr/local/mysql和/data/mysql因为二进制目录里有些脚本要在运行时写临时文件。权限不足时MySQL 初始化阶段会报Permission denied常见却容易忽略。2.2 主从差异化配置文件解析配置文件是主从复制里最需要差异化处理的部分。两台机器核心参数一致但server-id必须不同从库需要额外指定relay_log。我用/etc/my.cnf作为唯一配置入口主从节点各自维护一份避免环境差异被掩盖。主库配置节选[mysqld] usermysql basedir/usr/local/mysql datadir/data/mysql/data socket/data/mysql/mysql.sock pid-file/data/mysql/mysql.pid port3306 server-id1 log-binbinlog binlog_formatROW gtid_modeON enforce_gtid_consistencyON log_replica_updatesON skip_name_resolveON character-set-serverutf8mb4 collation-serverutf8mb4_0900_ai_ci default-time-zone08:00从库配置除了server-id2和relay-log/data/mysql/relaylog/relay-bin外其余保持一致。log_replica_updates在 8.0 里默认开着写出来是为了让文档更明确从库重放事务时同时记录自己的 binlog这样从库还能继续级联复制或做备份。这里解释几个关键参数为什么不能省binlog_formatROW8.0 默认就是 ROW 格式它比 STATEMENT 更安全能避免函数、存储过程在不同库上产生不同结果。gtid_modeON配合enforce_gtid_consistencyON开启 GTID 后从库不再依赖 binlog 文件和位点而是通过事务 ID 自动定位。skip_name_resolveON强制只通过 IP 访问数据库避免反向 DNS 查询导致连接变慢。2.3 初始化数据目录与启动服务MySQL 8.0 使用mysqld --initialize初始化不再用mysql_install_db。为了便于 SOP 统一处理我先用--initialize-insecure创建空密码 root 账号然后再用密码策略设置。如果你对安全格外敏感可以直接用--initialize但那样初始化日志里会输出随机密码拿到密码后还要处理过期问题反而多一步。/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf --initialize-insecure --usermysql初始化完成后用 systemd 管理 MySQL 进程。给主从节点都写一份/etc/systemd/system/mysqld.service内容如下[Unit] DescriptionMySQL Server Afternetwork.target [Service] Typenotify Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf LimitNOFILE65535 Restarton-failure [Install] WantedBymulti-user.target执行systemctl daemon-reload和systemctl enable --now mysqld再用mysql -S /data/mysql/mysql.sock -uroot登录验证。这里有个细节socket 路径必须和 my.cnf 里的 socket 保持一致否则客户端连不上很多新手会在这里卡住。3. 主从账号创建与初始数据迁移3.1 在主库创建复制专用账号复制账号不要直接拿 root 用风险太大权限也难收敛。复制进程只需要REPLICATION SLAVE权限就可以从主库拉取 binlog 并应用到从库。账号按最小权限原则单独创建方便以后回收和审计。CREATE USER repl10.0.0.% IDENTIFIED WITH caching_sha2_password BY StrongPass2024; GRANT REPLICATION SLAVE ON *.* TO repl10.0.0.%; FLUSH PRIVILEGES;这里特别说明认证插件。MySQL 8.0 默认使用caching_sha2_password远比mysql_native_password安全但复制客户端第一次连接时如果网络通道没有开启 SSL服务端需要把 RSA 公钥发给客户端否则认证会报错。解决办法是在从库配置复制通道时显式设置GET_SOURCE_PUBLIC_KEY1。后文会写到具体写法。如果你不想处理公钥问题也可以在创建账号时指定IDENTIFIED WITH mysql_native_password BY ...但 MySQL 8.0.35 已经弃用这个插件不建议新环境使用。用caching_sha2_password加GET_SOURCE_PUBLIC_KEY是更干净的做法。3.2 使用 mysqldump 完成初始数据迁移主从复制开始前必须保证从库的数据和主库当前状态一致。如果从库是空的还能接受一旦业务库已有存量数据直接START REPLICA往往会出现主键冲突或事务缺失。我这里选mysqldump做逻辑备份因为它是官方自带工具且 GTID 模式下可以正确导出事务位点信息。对于数据量极大、禁止长时间锁表的库物理备份工具会更合适但这套 SOP 面向中小规模环境逻辑备份足够。主库执行/usr/local/mysql/bin/mysqldump -uroot -p --single-transaction --set-gtid-purgedON --databases testdb /tmp/testdb.sql这里的关键参数是--single-transaction它基于 InnoDB 的一致性快照不锁表记录的是整个 dump 过程中全局事务的一个一致点。--set-gtid-purgedON会把SET GLOBAL.GTID_PURGED写入 dump 文件这样从库恢复后主库已经执行过的事务会在从库被跳过避免重复应用。把 dump 文件传到从库scp /tmp/testdb.sql root10.0.0.2:/tmp/再从库导入/usr/local/mysql/bin/mysql -uroot -p -S /data/mysql/mysql.sock /tmp/testdb.sql导入完成后在从库上确认GTID_PURGED已经包含主库之前的全部事务这一步是后续自动定位的基础。4. 从库配置复制通道与启动4.1 使用 CHANGE REPLICATION SOURCE TO 配置连接信息MySQL 8.0.22 之后官方把CHANGE MASTER TO改名为CHANGE REPLICATION SOURCE TO把START SLAVE改成START REPLICA。旧语法虽然还在但官方文档已经标记为废弃SOP 里我统一用新语法避免被后续版本移除时再改一遍。在从库执行STOP REPLICA; CHANGE REPLICATION SOURCE TO SOURCE_HOST10.0.0.1, SOURCE_PORT3306, SOURCE_USERrepl, SOURCE_PASSWORDStrongPass2024, SOURCE_AUTO_POSITION1, GET_SOURCE_PUBLIC_KEY1; START REPLICA;SOURCE_AUTO_POSITION1是 GTID 模式下的核心配置它让从库启动时向主库请求从当前 GTID 位置之后的事务。只要 dump 文件已经把GTID_PURGED设置正确就不需要再手动指定 binlog 文件和行数复制坐标完全由 GTID 自己管理。GET_SOURCE_PUBLIC_KEY1就是前面提到的认证公钥参数。如果创建复制账号时用了caching_sha2_password这个参数必须加上否则首次连接可能报错Authentication requires secure connection或Public Key Retrieval is not allowed。4.2 启动复制并检查关键状态启动复制后不要急着看数据先确认两个线程是否都处于 Yes。执行SHOW REPLICA STATUS\G重点看这几项Replica_IO_Running: YesIO 线程已经连接主库正在拉取 binlog。Replica_SQL_Running: YesSQL 线程正在应用 relay log。Seconds_Behind_Source: 0从库与主库的延迟为 0。如果输出字段名还是Slave_IO_Running、Slave_SQL_Running说明当前版本仍保留了旧字段别名不影响使用但我们要关注新字段名。Seconds_Behind_Master在 8.0.35 里依然可见属于兼容字段。也可以用SHOW REPLICA STATUS\G的Last_IO_Errno、Last_SQL_Errno快速判断错误。Last_IO_Error为连接问题Last_SQL_Error为应用数据问题。两条错误处理思路完全不同排查时先区分是哪条线程报错。5. 同步验证与故障排查5.1 端到端读写验证方案复制状态显示 Yes 还不够必须做业务数据验证。我习惯在主库建一个测试库插入几条记录再在从库上查询。这一步能直接暴露 dump 过程中的数据不一致问题。主库执行CREATE DATABASE copytest; USE copytest; CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(50)); INSERT INTO t1 VALUES (1, master-1), (2, master-2);从库执行USE copytest; SELECT * FROM t1;正常情况会立即看到两条记录。如果在从库看到的是旧数据甚至查询不到这张表说明 dump 文件没有完整导入或者复制坐标偏移需要回看SHOW REPLICA STATUS和 dump 文件里的 GTID_PURGED。更严谨的做法是连续写入几条数据观察从库Seconds_Behind_Source是否保持 0。我通常会写一个循环插入 1000 条数据的脚本然后查看主从两边的max(id)是否一致。主从同步不只是配出来还要能扛住真实写入压力。5.2 常见报错与恢复操作速查下面是这套 SOP 实施过程中我实际踩过的几个坑按出现频率排序。场景一IO 线程启动失败报认证公钥问题。错误日志里出现Authentication plugin caching_sha2_password reported error: Authentication requires secure connection基本就是GET_SOURCE_PUBLIC_KEY没设置。先STOP REPLICA重新执行带GET_SOURCE_PUBLIC_KEY1的CHANGE REPLICATION SOURCE TO再启动即可。场景二上下行 server-id 相同。如果从库虚拟机是从主库克隆出来的MySQL 的数据目录里可能包含了相同的auto.cnf里面的 server-uuid 完全一致。复制启动时会报Fatal error: The replica I/O thread stops because master and replica have equal MySQL server UUIDs。解决方法是停掉从库 MySQL删除/data/mysql/data/auto.cnf再重启从库。MySQL 会重新生成 UUID然后重新配置复制通道。场景三SQL 线程报 1062 主键冲突。这通常意味着从库上已经有相同主键的记录而 binlog 里的事务试图再次插入。第一反应不要直接跳过错误先比较主从两边的数据找出是哪条记录出问题。如果是测试环境可以STOP REPLICA临时SET GLOBAL SQL_SLAVE_SKIP_COUNTER1再START REPLICA跳过当前事务。但这只适合应急生产环境必须认真排查否则数据会在某个时间点悄悄分叉。场景四中继日志损坏或文件过大。偶尔会遇到中继日志文件损坏复制线程卡住。处理方法是STOP REPLICA; RESET REPLICA ALL;之后重新配置复制通道。这种方式会清掉从库的复制坐标所以只适合从库数据仍可信、需要重新拉取的情况。报错关键字处理思路Authentication requires secure connection增加 GET_SOURCE_PUBLIC_KEY1 重配复制通道equal MySQL server UUIDs删除 auto.cnf 并重启从库Error 1062 Duplicate entry先比对数据临时跳过或修数据relay log read failureSTOP REPLICARESET REPLICA ALL 后重配5.3 从库只读保护与日常巡检复制环境搭好之后一定要给从库加上只读保护。否则业务方或者运维误操作直接写在从库上主从数据立刻偏航。在从库的 my.cnf 中加入read_only1 super_read_only1read_only会拒绝所有非 SUPER 权限账号的写操作super_read_only连 SUPER 权限账号也一并拒绝。复制线程不受这两个参数影响所以可以放心开启。我建议从库从一开始就加上这两个参数而不是等出事故以后再补。日常巡检关注三块复制线程状态、延迟秒数、磁盘空间。relay log如果长期不清理relaylog目录会被撑满。虽然重启 SQL 线程会触发 relay log 清理但高压力下还是建议监控/data/mysql/relaylog的大小。主从复制不是配完就结束后续磁盘、网络、连接数都要进入监控范围。6. 几个容易被忽略的经验补充6.1 防火墙与端口放行的实际操作如果你的环境不允许关闭防火墙那么主库的 3306 端口必须放行。CentOS 7 使用 firewalld放行命令是firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload很多时候从库连接主库失败不是用户名密码写错而是端口根本没通。排查时先看从库能不能 telnet 到主库 3306确认网络层没问题再看 MySQL 错误日志。顺序反了会浪费时间。6.2 复制参数调整与性能验证主从复制搭完后可以按业务负载调整几个参数但不要盲目改。binlog_cache_size默认 32K如果单事务写得大可以适当调大sync_binlog1保证 binlog 实时落盘但也增加了写 IO需要结合磁盘能力权衡。innodb_flush_log_at_trx_commit如果从库作为备份库使用可以调成 0 或 2 来提高重放性能但数据安全等级会下降普通业务不建议动。我还习惯做一次模拟故障验证直接在主库kill -9掉 mysqld 进程观察从库复制线程是否正常主库恢复后复制是否自动续传。这种压测能暴露很多文档里写不出的短板比如主库 OS 重启后从库是否还能建立连接、复制账号密码是否过期、防火墙策略是否在重启后自动加载。6.3 SOP 文档应该包含哪些东西最后说下 SOP 本身。很多团队的主从复制文档只写了几条命令新员工拿到后不知道怎么落地。我建议 SOP 至少包含五块内容架构拓扑图、节点资源配置、完整配置文件模板、可复制执行的命令清单、常见故障处置手册。命令清单里要标注哪些在主库执行哪些在从库执行执行顺序也必须写死避免一个人横跳两台服务器时搞混。每执行完一个阶段就在节点名后面打勾。我之前帮团队整理这套文档时把每个阶段执行完成后应看到的状态也写了进去比如“初始化后 root 能通过 socket 登录”“从库 SHOW REPLICA STATUS 两个线程均为 Yes”“测试建表后从库能查到数据”。这些验证点比命令本身更能保证 SOP 的可交付性。实际做下来我觉得搭建主从复制最难的不是敲那几条 SQL而是每一步背后的判断逻辑为什么用 GTID、为什么加 GET_SOURCE_PUBLIC_KEY、为什么从库要只读。把这些逻辑写透这份 SOP 才能从“能跑”变成“可靠”。我在测试环境里已经重复跑了很多次每次都会回看步骤检查有没有遗漏的系统依赖、权限和后置验证。你拿到这套流程后先拿测试库跑一遍再切生产过程中的差异点自己补上以后它就是你自己团队的主从复制标准动作了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询