在线客服

数据库读写分离中哪些查询不该直接发往只读库

⏱️2026-10-11 16:28 👁️1

🔀 路由依据是新鲜度要求

读写分离的只读端通常是从主库复制而来的副本。常见复制方式允许主库提交先于副本应用,因此副本读取可能看到旧状态。SQL 是 SELECT 并不意味着查询可接受陈旧:判断订单是否已支付、验证刚创建记录、显示用户刚刚修改的资料,都可能要求读到本次写入。路由应由业务一致性要求决定,而不是只靠语句动词判断。

为查询分类:可容忍陈旧的历史报表、搜索列表或聚合可考虑副本;读己之写、关键状态转换、权限和额度判断通常应走主库或具备明确的一致性读机制。明确每类查询允许的最大陈旧度、遇到副本落后时的回退行为以及失败时对用户的表达。没有定义容忍窗口,就没有可靠的副本路由规则。

🔗 会话和事务不能随意拆开

事务中的读取依赖事务隔离级别、快照和同一会话状态。如果事务先在主库写入,再把 SELECT 单独路由到副本,不但可能读到旧数据,还可能脱离事务快照。临时表、会话变量、锁定读和依赖连接状态的查询同样不能任意切换连接。连接池与代理配置应明确事务开始后是否固定目标,并确保提交或回滚后状态被清理。

常见的读后写保护方式包括会话粘滞、提交后的一段时间内读主、由复制位置确认副本已追上后再读取,或将一致性要求作为请求上下文传递。每种方式都有成本:粘滞可能把更多流量留在主库;固定等待时间无法保证副本一定追上;位置确认需要数据库和驱动提供相应能力。选择前要明确适用范围和超时后的降级行为。

📊 解释副本延迟指标

监控副本接收和应用进度、复制队列、事务应用速度、时间延迟和主库写入速率。单一“延迟秒数”指标是线索,不说明某条刚提交的记录何时可见;空闲期接近零的读数也无法预测突发写入后的追赶能力。观察采样连续性、积压增长与恢复速度,并结合实际业务探针检查关键变更在副本上的可见时间。多个副本还要分别观测,避免负载均衡将同一用户连续请求交给新鲜度不同的节点。

业务分类示例:新闻列表可接受短暂延迟;用户刚保存的设置、刚创建的支付记录状态以及影响授权的字段应使用读己之写路径或显式等待机制。

🧪 路由验证步骤

  1. 为查询标注一致性等级、允许陈旧窗口、失败策略和是否依赖会话状态,形成显式路由规则。
  2. 注入或模拟副本落后,执行写后立即读、连续翻页、事务内读写和高频状态查询,检查读到旧值时的业务处理。
  3. 验证会话粘滞和提交后读主规则的生命周期、超时与异常清理,避免长期粘主导致主库压力不可控。
  4. 对比副本积压、读主比例、关键流程旧值率、查询延迟和主库资源,确认一致性需求和容量目标同时满足。

✅ 常见误区与验收

把所有 SELECT 丢给副本会破坏读己之写;把某次零延迟采样当作强一致保证也不成立。即使系统常态下复制非常快,副本故障或写入尖峰也可能让旧值窗口扩大。验收时应能指出每类查询的路由理由,并在副本滞后时得到符合业务规则的结果或明确降级,而不是出现间歇性状态回退。读写分离是容量与一致性之间的取舍,边界必须由应用主动表达。