网站数据库读写分离提升性能:网站数据库读写分离

为什么要做数据库读写分离

当网站用户量增长,单台数据库服务器既要处理写入(新增、修改、删除)又要处理读取(查询),很容易因为CPU、内存或磁盘I/O瓶颈导致响应变慢。读写分离通过将写入操作交给主库,读取操作分发给一个或多个从库,让主库专注于写入,从库分担读压力,整体吞吐量大幅提升。
这个方案不需要昂贵的硬件,只靠软件配置就能实现,是中小型网站性价比最高的优化手段之一。

搭建主从复制环境

实现读写分离的第一步是让主库和从库之间的数据实时同步,也就是MySQL主从复制

1. 准备条件

  • 两台服务器(或云主机),操作系统不限(本文以CentOS 7 + MySQL 8.0为例)。
  • 主库IP:192.168.1.10,从库IP:192.168.1.20。
  • 确保两台服务器之间网络连通(互相能ping通,防火墙放开3306端口)。
  • MySQL版本尽量一致,最好都是8.0系列。

2. 配置主库

登录主库服务器,编辑MySQL配置文件(通常位于/etc/my.cnf/etc/mysql/my.cnf),在[mysqld]段添加以下内容:

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

保存后重启MySQL服务:

systemctl restart mysqld

登录MySQL(mysql -uroot -p),创建一个专门用于复制的用户,并授予权限:

CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'YourPass123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%';
FLUSH PRIVILEGES;

查看主库当前状态,记录下FilePosition,后面配置从库时要用:

SHOW MASTER STATUS;

输出示例:

+------------------+----------+
| File             | Position |
+------------------+----------+
| mysql-bin.000001 |      877 |
+------------------+----------+

3. 配置从库

登录从库服务器,修改配置文件,在[mysqld]段添加:

[mysqld]
server-id = 2
# 以下两行可选,用于设置只读(防止误写入从库)
read-only = 1
super-read-only = 1

重启从库MySQL:

systemctl restart mysqld

登录从库MySQL,执行以下命令连接到主库并开始同步(请根据实际IP和刚才记录的File、Position替换):

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.10',
  SOURCE_USER='repl',
  SOURCE_PASSWORD='YourPass123',
  SOURCE_LOG_FILE='mysql-bin.000001',
  SOURCE_LOG_POS=877;

*注意:MySQL 8.0.23之前版本使用MASTER_HOSTMASTER_USER等旧版关键字,用法相同。
*

启动复制:

START REPLICA;

查看复制状态是否正常:

SHOW REPLICA STATUS\G

重点看这两项:

  • Slave_IO_Running: Yes
  • Slave_SQL_Running: Yes

如果都显示Yes,说明主从复制已建立。

配置应用层读写分离

主从复制只是数据同步,网站还要知道写请求走主库、读请求走从库
这一步通常在应用程序里配置,不需要改动MySQL自身。
以PHP的Laravel框架为例,修改.env文件:

DB_CONNECTION=mysql
DB_HOST=192.168.1.10    # 主库IP
DB_PORT=3306
DB_DATABASE=yourdb
DB_USERNAME=root
DB_PASSWORD=password

# 读写分离配置
DB_READ_HOST=192.168.1.20  # 从库IP
DB_READ_DATABASE=yourdb
DB_READ_USERNAME=root
DB_READ_PASSWORD=password

config/database.php中配置:

'mysql' => [
    'driver' => 'mysql',
    'write' => [
        'host' => env('DB_HOST', '192.168.1.10'),
    ],
    'read' => [
        'host' => env('DB_READ_HOST', '192.168.1.20'),
    ],
    'database' => env('DB_DATABASE', 'yourdb'),
    'username' => env('DB_USERNAME'),
    'password' => env('DB_PASSWORD'),
    // 其他配置...
],

其他框架(ThinkPHP、Symfony、Yii)也有类似写法。
如果你用的是宝塔面板,可以在“数据库”菜单中直接添加主从复制,然后在网站管理的“数据库配置”里手动修改数据库连接代码。

如果不想改代码,也可以使用MySQL中间件如ProxySQL、MyCat,这类工具可以透明地在前端拦截SQL,按规则转发。
但对于零基础用户,修改应用配置是最快、风险最低的方式。

常见坑位与排查方法

1. 主从延迟导致读不到刚写的数据

用户提交表单后立即去查,可能查不到(因为从库还没同步过来)。解决:对实时性要求高的场景(如支付结果),强制读主库;
或者对从库设置较短的同步间隔。

2. 从库IO线程或SQL线程报错

运行SHOW REPLICA STATUS\G,查看Last_IO_ErrorLast_SQL_Error
常见原因:

  • 防火墙没放通3306端口。
  • 复制用户密码错误或IP范围不对。
  • binlog格式不匹配(建议统一用ROW)。
  • 主从库的sql_mode不一致导致某些SQL执行失败。

3. 误写入从库

从库默认允许写入(除非你加了read-only=1)。
即使开启只读,super权限用户还是能写。
建议:始终在应用层明确区分读/写连接,不要依赖数据库层限制。

验证读写分离是否生效

方法一:检查主从复制状态

在从库上执行:

SHOW REPLICA STATUS\G

确认Slave_IO_RunningSlave_SQL_Running均为Yes

方法二:追踪SQL去向

在应用服务器上临时开启MySQL通用查询日志(生产环境慎用),或者使用抓包工具tcpdump。
例如,在从库服务器上执行:

tcpdump -i any port 3306 -X

然后用浏览器访问网站的一个查询页面,观察从库是否收到查询请求。

方法三:应用层面的监控

在代码中输出当前使用的数据库连接IP(如DB::connection()->getPdo()->query('SELECT @@hostname')),运行时刷新页面,查看打印的IP。
如果读请求显示的是从库IP,写请求显示主库IP,就说明分离成功。

结尾

完成以上配置后,你的网站数据库就实现了读写分离,压力被均匀分配。
记得先在测试环境跑通,确保主从复制稳定后再上生产。
遇到同步异常时,优先检查网络、权限和binlog配置。
读写分离只是第一步,后续还可以结合缓存(Redis)、分库分表等方案继续优化。
如果你在配置中碰到了问题,欢迎留言交流。

分享到:
上一篇
网站二级域名搭建子站点教程:从零开始分站部署
下一篇
网站缓存配置减轻服务器压力:一篇写给新手的实操指南
1
系统公告

泽御云五一特惠活动🔥

泽御云持证合规运营,资质齐全可查,长久稳定! 五一限时多重福利同步开启: ✅ 香港 2 核 2G 云服务器超值拼团,低价入手团长免费 ✅ 4 核 4G 多机房年付拼团,性价比拉满 ✅ 内蒙古新区限时 7 折(zeyuyunnmg)特惠,专属优惠码锁价续费 ✅ 全站通用 75 折优惠,老用户充值享专属赠金 官方站点:zeyuyun.com 合规资质齐全|售后有保障|活动限时错过不再有
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意