首页/数据/数据库速查/读写分离的收益与坑
主从复制与高可用53 条

读写分离的收益与坑

读写分离的核心风险是延迟读:写完立刻读可能读到旧数据;套路有「写后读主库」「强制主库标记」「会话粘连」三招,按业务容忍度选。

数据库速查数据更新于 2026-10-13

读写分离的核心风险

读写分离把查询压力分散到从库,代价是延迟读:刚写完立刻查从库可能读到旧数据,这类问题在用户侧表现为「提交了但没显示」。常见套路有三种:写后短窗强制读主库、用注释或代理规则给关键查询打主库标记、会话粘连保证同一会话读一致。选哪种取决于业务对延迟的容忍度。

基本信息

适用一主多从 + 中间件(ProxySQL、MyCat)或应用层数据源路由
收益读扩展、降低主库压力、报表查询隔离
风险延迟导致读到旧值,缓存双删类逻辑要一并重审
兜底半同步复制可缩小延迟窗口,但仍不保证实时一致

常见方案与代价

方案适用场景代价
写后短窗读主库下单、支付等写完立刻要读的场景窗口内主库压力上升,需要统一封装
关键查询强制主库对账、库存扣减校验等强一致查询需在 SQL 或代理规则里显式标注,易漏
会话粘连同一用户会话内读一致要求高负载均衡变差,连接利用率下降
从库追平校验可接受毫秒级补偿的场景实现复杂,超时后仍要回主库
直连从库的报表查询延迟容忍高的统计与导出需明确标注延迟容忍并监控追平

代理层强制主库示例

代理层强制主库示例
-- ProxySQL:为特定语句打标走写组(示例,规则按业务调整)
INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply)
VALUES (10, 1, '^SELECT.*FOR UPDATE', 10, 1);
LOAD MYSQL QUERY RULES TO RUNTIME;      # 规则装载到运行时
SAVE MYSQL QUERY RULES TO DISK;         # 持久化,避免重启丢失
-- 应用侧另一种做法:在 SQL 注释里打标,由中间件识别
--   SELECT /* master */ balance FROM account WHERE id = 1;

典型使用场景

  • 读多写少的业务用从库分流,主库只承担写入
  • 报表与导出走从库,避免大查询拖慢在线交易
  • 活动高峰扩容只读节点,弹性提升查询吞吐
  • 用户提交表单后立刻跳转详情页,用写后读主保证不出现空数据
  • 跨机房读取就近路由,按延迟容忍度决定是否允许读从库
一致性要求高的报表与对账应直连从库并单独监控追平时间,而不是依赖业务默认读从库;默认策略一旦是「读从库」,少数强一致场景会被长期忽视。
延迟读会在缓存双删逻辑上放大问题:缓存删了、从库还没追上,回源又读到旧值并写回缓存,脏数据存活时间可能被显著拉长。

易错点

  • 写后立刻查从库:用户看到提交成功却查不到数据,是最常见的投诉来源
  • 全局默认读从库:少数强一致场景被忽略,等到对账差异出现才发现
  • 中间件规则写错方向(把强一致查询路由到从库):错误发生在配置层,日志与代码都看不出来
  • 用半同步复制当作绝对一致保证:超时退化为异步后仍会读到旧值,关键读还是要显式走主库

数据来源与参考

  • ProxySQL 官方文档
  • MySQL 8.0 Reference Manual: Replication

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌