MySQL 主从复制搭建:服务器数据库读写分离第一步

MySQL 主从复制架构封面图

当你的网站流量逐渐增长,单台 MySQL 服务器开始频繁出现 CPU 满载、查询响应变慢、备份期间网站卡顿这些问题时,很多站长第一反应是升级硬件,却发现成本越堆越高。MySQL 主从复制(Master-Slave Replication)正是解决这类问题的第一条路:它能把”写”和”读”拆到两台甚至多台机器上,让主库专注处理变更,从库分担查询压力。这篇文章会手把手带你理解主从复制背后的机制,并在你的服务器上完成从环境准备到验证生效的完整搭建流程,整个过程大约需要一小时。

为什么要做主从复制:先看清单库的瓶颈

在动手配置之前,先明确主从复制到底解决什么问题。对大部分成长中的站点,数据库读多写少是最典型的负载形态:博客的页面浏览、商品列表展示、报表查询都属于读操作,占比常常超过 80%,而真正会改动数据的写入只占很小一部分。单台数据库服务器必须同时承受所有读写,当某个慢查询拖住 CPU,或磁盘 IO 在备份时段被打满,网站整体响应就会明显变慢。

主从复制把这条链路拆开:主库(Master)只接收写入请求,从库(Slave)通过主库的变更日志保持数据同步,再对外提供查询服务。这样做的直接收益有三层:

  • 读压力被分散到多台机器,主库 CPU 占用明显回落,写入不再被高并发查询拖慢
  • 日常全量备份可以改到从库执行,避免备份期间的 IO 波动直接干扰线上写入
  • 当主库出现硬件故障时,从库可以快速提升为主库,缩短业务中断时间

这里的核心是”异步复制”:主库提交事务后立即返回,把变更写入二进制日志,从库按自己的节奏拉取并重放。正因如此,主从之间的数据在极短时间内可能存在少量延迟,读写分离的应用要能容忍这种最终一致。

环境准备:两台服务器与一个前提条件

搭建主从复制最少需要两台 MySQL 实例。你可以申请两台独立的 VPS虚拟专用服务器)分别部署主库和从库,也可以在同一台物理机上用不同端口跑两个实例——但生产环境强烈建议分机部署,否则磁盘和内存仍是共享的,一旦故障仍然一起宕机。

除了服务器本身,还有几个必须满足的前提:

  • 主库和从库的 MySQL 大版本保持一致,例如都用 8.0,避免跨大版本带来的二进制日志格式和认证插件差异
  • 两台机器之间网络互通,建议使用同机房或同区域的服务器,降低复制延迟和不稳定因素
  • 主库开启二进制日志,这是复制的数据源头,未开启则从库无数据可读
  • 为主从连接单独创建一个专用的复制账号,而不是直接使用 root,权限尽量收敛

网络延迟对复制稳定性影响很大。如果两台服务器跨越多个地域,复制延迟会持续拉高,主从同步经常处于追赶状态,读写分离的效果会大打折扣。这也是为什么同机房部署通常是首选方案。

第一步:修改主库配置并开启二进制日志

MySQL 二进制日志示意图

编辑主库的 MySQL 配置文件 /etc/my.cnf,在 [mysqld] 段下添加以下内容:

[mysqld]
server-id = 1
log-bin = mysql-bin
binlog_format = ROW

server-id 必须在整个复制集群内唯一,主库设为 1,从库设为不同的数字。log-bin 指定二进制日志的文件前缀,binlog_format = ROW 让日志按行级别记录变更,比默认方式更可靠,能规避某些跨版本函数复制失败的问题。修改完成后执行 systemctl restart mysql 重启主库。

验证二进制日志是否生效,登录主库后执行:

SHOW VARIABLES LIKE 'log_bin';

返回结果中 log_bin 为 ON,说明二进制日志已经打开,可以进入下一步。

创建复制账号并锁定主库位置

在主库上创建一个只用于复制的账号。以 MySQL 8.0 为例:

CREATE USER 'repl'@'%' IDENTIFIED BY '强密码';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

这里把账号名取为 repl,授权 REPLICATION SLAVE 即可读取二进制日志做复制回放,权限比 root 小得多。'%' 表示允许从任意主机连接,如果你的从库 IP 固定,可以写成 'repl'@'从库IP' 进一步收紧。

接下来要”冻结”主库数据,保证导出的数据快照和二进制日志位置一一对应。如果业务允许短暂只读,可以执行:

FLUSH TABLES WITH READ LOCK;

然后用 SHOW MASTER STATUS 记录当前日志文件名和位置:

SHOW MASTER STATUS;

记录下返回的 File(如 mysql-bin.000001)和 Position(如 156)两个值,后面配置从库时会用到。如果业务不能停写,可以采用 mysqldump--single-transaction --master-data=2 的方式在线导出,它会在导出的转储文件头部自动写入对应的日志位置。

导出并导入初始数据

主从复制的起点必须一致,否则从库开始应用日志后会因为找不到对应记录而报错。先在主库把目标数据库导出:

mysqldump -u root -p --single-transaction --master-data=2 --databases yourdb > db-backup.sql

其中 yourdb 替换为你实际的数据库名,--single-transaction 让 InnoDB 引擎在不加锁的情况下生成一致快照,--master-data=2 会把当前二进制日志文件名和位置注释写入转储文件。导出完成后,执行 UNLOCK TABLES 释放主库的只读锁。

把转储文件上传到从库,进入从库 MySQL 后导入:

mysql -u root -p < db-backup.sql

导入完成后不要急着写任何数据。此时从库的数据和主库导出时刻是一致的,正好满足复制的起点要求。

配置从库并启动复制

编辑从库的 /etc/my.cnf,设置唯一的 server-id,并建议把只读模式打开,防止应用误写从库:

[mysqld]
server-id = 2
read_only = 1

重启从库后,登录从库 MySQL,执行 CHANGE MASTER 指定主库信息。这里的二进制日志文件名和位置来自前面 SHOW MASTER STATUS(或转储文件头部)的记录:

CHANGE MASTER TO
  MASTER_HOST='主库IP',
  MASTER_USER='repl',
  MASTER_PASSWORD='强密码',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=156;

然后启动复制:

START SLAVE;

最后检查复制状态,这是整个搭建过程最关键的一步:

SHOW SLAVE STATUS\G

重点关注 Slave_IO_RunningSlave_SQL_Running 两个字段,两者都必须为 Yes。Slave_IO_Running 表示从库能正常从主库拉取二进制日志,Slave_SQL_Running 表示从库正在正确应用这些日志。任何一个不是 Yes,都要回到日志文件与位置、账号权限、网络连通性这几个方向去排查,而不是继续往下走。

验证复制生效并接入读写分离

MySQL 主从复制验证示意图

复制启动后,做一次最简单的写入-读取验证。在主库执行:

INSERT INTO yourdb.emp (name, salary) VALUES ('测试用户', 8000);

在从库执行同样的查询:

SELECT * FROM yourdb.emp WHERE name='测试用户';

如果能查到刚写入的这条记录,说明数据已经通过复制流到了从库,主从复制基本打通。接下来把应用的查询逻辑拆开:写入走主库连接,读请求走从库连接。很多 ORM 和连接池都支持多从库配置,也可以使用中间层做自动路由,但要注意,复制延迟仍然存在,刚写入的数据不应立刻从从库读取,否则可能出现"写后读空"的问题。

常见故障与排查清单

MySQL 主从复制故障排查清单示意图

搭建过程中最常见的三个坑值得提前规避。第一个是二进制日志位置写错,导致从库一直报 Could not find first log file,这时把 MASTER_LOG_FILEMASTER_LOG_POS 改成 SHOW MASTER STATUS 的准确值即可。第二个是从库连接主库被拒绝,先检查主库的 bind-address 是否限制了监听地址,以及防火墙是否放行了 3306 端口。第三个是复制因某个 SQL 语句中途停止,Slave_SQL_Running 变成 No,可以先查看 Last_Error 定位问题,再决定是修复数据还是跳过该事务。

如果复制长期处于延迟追赶状态,优先检查主从之间的网络往返时间,以及从库服务器的磁盘 IO 是否成为瓶颈。高写入量的业务还需要评估从库数量:一台从库可以分担一部分读流量,但读压力继续增长时,加从库比一直升级单机硬件更灵活,也更容易控制成本。

总结与后续建议

到这里,你在两台服务器之间走通了 MySQL 主从复制的完整链路:开启二进制日志、创建复制账号、导出导入初始数据、配置从库并启动复制、最后验证读写分离生效。这组操作是数据库横向扩展的第一步,建议你按"一个环节改一项、改完就验证"的节奏执行,这样出问题时能快速定位到底卡在哪一步。

如果你需要迁移整站或评估更大规模的架构,可以参考 Hostease 在数据库与服务器方面的其他实操内容。需要说明的是,主从复制解决的是读扩展和容灾,它并不代替"真正的备份"——从库会同步复制主库的错误操作(比如误删表),所以定期快照和异地备份仍然不能省。如果你需要更高水平的数据库性能和稳定的网络环境,也可以把 MySQL 数据库放在高性能的独立服务器 上运行,同时搭配 VPS(虚拟专用服务器) 作为从库节点。关于读写分离对 网站整体响应速度(TTFB)的影响,我们做过专门分析,值得一并阅读;如果你的业务主要在 WordPress 生态,也可以查看 WordPress 数据库优化 的相关文章,里面有不少可以直接落地的做法。总结一下:从单机 MySQL 走向主从复制,是成本可控又能显著提升扩展能力的第一步,建议你尽快按上面的步骤把它部署起来,跑通后你会发现数据库的瓶颈一下子松了大半。

发表评论