知识卡片
读写分离的脏数据处理策略:从简单粗暴到基于会话逐级精细
内容
用复制做读写分离(写走主库、读分担到备库)天然有一个后果:备库复制是 异步的,读到的数据可能比主库”旧”,如何决定”哪些读可以容忍这种脏数据、 哪些不行”,有一系列复杂度递增的策略可选,越精细的策略能把更多读流量 安全地导向备库,但实现和维护成本也更高。最简单的是”按查询类型分离”: 写死一份”不能容忍脏数据”的查询清单,这类查询固定走主库,其余的走 备库——实现最简单,但因为大多数查询其实都对”数据是否绝对最新”敏感, 真正能被导向备库的查询很少,备库利用率不高。往上一级是”按脏数据容忍度 分离”:应用主动检查当前复制延迟,判断备库数据”够不够新”,常见于报表类 场景(只要求数据是昨晚的即可,不关心是否分秒不差)。再往上是”按会话 分离”:不追踪具体延迟数值,而是判断当前用户自己有没有刚做过写操作—— 用户不需要立刻看到别人的最新数据,但一定要看到自己刚做的修改,所以给 会话打一个”最近写过”的标记,标记期内这个用户的读固定走主库,过期后再 恢复走备库;书中把这个策略称为在”实现简单”和”效果精细”之间性价比最高 的折中方案,是推荐的默认选择。最精细的是”按版本/全局版本分离”:给数据 对象打版本号或提交时的binlog坐标,读备库前对比备库当前进度和这个版本 标记,只有备库确认追上了才读备库,否则读主库——精确到”这一条具体数据” 而不是整个会话级别,但需要额外维护版本追踪逻辑。这个策略谱系体现的 共同思路是:脏数据问题没有一个万能解,选择哪种策略本质上是在”备库 利用率”和”实现/维护复杂度”之间找一个符合当前业务对新鲜度要求的平衡点。
结构图:
flowchart TD
A[按查询类型分离<br/>简单但备库利用率低] --> B[按脏数据容忍度分离<br/>看复制延迟是否够新]
B --> C[按会话分离<br/>推荐的性价比折中]
C --> D[按版本/全局版本分离<br/>最精细但实现复杂度最高]
参考来源
- 位置:《高性能MySQL:第3版》第11章"可扩展的MySQL"11.3.1节"直接
连接"(源文件:_epub-src/OEBPS/Text/part0018.xhtml)
- 结论依据:原文明确列出"基于查询分离""基于脏数据分离""基于会话
分离""基于版本分离""基于全局版本/会话分离"五种读写分离策略,并
评价"基于会话的分离方法……是我们通常推荐的策略,因为它是在简单和
有效性之间的一种很好的妥协",直接支撑各策略复杂度递增及会话分离
为折中推荐方案的结论。
- 原始内容:基于会话分离……可以在会话层设置一个标记位,表明做了
更新,就将该用户的查询在一段时间内总是指向主库……这是我们通常
推荐的策略,因为它是在简单和有效性之间的一种很好的妥协。