一主多从仅分流读压力,无法支撑百万级并发;写请求仍集中于主库,需配合sql优化、缓存、连接池等整套方案才有效。

一主多从不是并发能力的“开关”,而是读压力的分流器
直接说结论:单靠一主多从无法支撑百万级并发,它只解决“读多”部分的压力分摊,写请求仍全部压在主库。如果你的业务写QPS已超3000,或者存在大量长事务、大事务更新,主库很快会成为瓶颈,甚至拖垮整个复制链路。真正能扛住百万并发的,是“SQL优化 + 缓存 + 读写分离 + 连接池治理 + 应用层降级”这一整套组合拳,一主多从只是其中一环,且必须配合其他手段才有效。
主库必须禁用 autocommit=0 并严格控制事务粒度
常见错误是开发习惯性开启长事务(比如在应用里手动 BEGIN 后迟迟不 COMMIT),导致主库 binlog 堆积、从库 SQL Thread 卡在某个事务里不动,最终出现秒级甚至分钟级延迟。更危险的是,长事务会持续持有行锁或间隙锁,阻塞其他写入,主库 CPU 和锁等待陡增。
- 所有写操作必须走短事务:单条
INSERT/UPDATE/DELETE尽量不跨表、不带子查询、不触发复杂触发器 - 批量写入拆成 500–1000 行/批,每批独立事务提交,避免单事务写入超 2s
- 监控
SHOW PROCESSLIST中State为Waiting for table metadata lock或Updating超 1s 的连接,立即告警 - 主库
my.cnf中显式设置autocommit=1,禁止应用层意外关闭自动提交
从库不能只配 read_only=1,还要关掉 binlog 和 innodb_flush_log_at_trx_commit
很多团队以为设了 read_only=1 就安全了,其实没关 binlog 会导致从库磁盘写放大——它既要写 relay log,又要写自己的 binlog(哪怕不用),IO 压力翻倍;而默认 innodb_flush_log_at_trx_commit=1 在高并发读场景下,会让从库频繁刷 redo log,严重拖慢 SELECT 响应。
- 从库配置必须包含:
read_only=1、skip_log_bin(或注释掉log_bin)、innodb_flush_log_at_trx_commit=2 - 不要在从库上开
general_log或slow_query_log,日志 IO 会吃掉可观的 IOPS - 如果用的是 MySQL 8.0+,确认
replica_parallel_workers > 0(如设为 4~8),启用并行复制缓解单线程 SQL Thread 延迟
客户端路由必须区分“强一致性读”和“最终一致性读”
最常被忽略的一点:不是所有读都能甩给从库。用户刚下单成功,立刻查订单详情,如果读从库可能查不到(主从延迟);支付回调后查账户余额,若读从库可能余额未更新,引发资损。这类场景必须强制走主库。
- 在 DAO 层或中间件中打标:对
SELECT ... FOR UPDATE、涉及最新写入结果的查询(如“我的最新订单”)、金融类余额/状态类查询,强制路由到主库 - 对报表、搜索聚合、用户资料页等容忍秒级延迟的读,才发往从库
- 避免用
SELECT SLEEP(1)类“等延迟过去再读”的土办法——不可靠,且增加响应时间 - 上线前用
SHOW SLAVE STATUS\G中的Seconds_Behind_Master和Exec_Master_Log_Pos对比主库SHOW MASTER STATUS,实测典型延迟范围(通常 50–500ms),据此制定路由策略
主从延迟不是配置问题,是数据流本质决定的:binlog dump → 网络传输 → relay log 写入 → SQL 解析执行,每一步都可能卡顿。真正难处理的,是那些既要求低延迟又不能写主库的场景——这时候该考虑引入 GTID + WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS,但代价是读请求变重,得权衡。











