读写分离的只读端通常是从主库复制而来的副本。常见复制方式允许主库提交先于副本应用,因此副本读取可能看到旧状态。SQL 是 SELECT 并不意味着查询可接受陈旧:判断订单是否已支付、验证刚创建记录、显示用户刚刚修改的资料,都可能要求读到本次写入。路由应由业务一致性要求决定,而不是只靠语句动词判断。
为查询分类:可容忍陈旧的历史报表、搜索列表或聚合可考虑副本;读己之写、关键状态转换、权限和额度判断通常应走主库或具备明确的一致性读机制。明确每类查询允许的最大陈旧度、遇到副本落后时的回退行为以及失败时对用户的表达。没有定义容忍窗口,就没有可靠的副本路由规则。
事务中的读取依赖事务隔离级别、快照和同一会话状态。如果事务先在主库写入,再把 SELECT 单独路由到副本,不但可能读到旧数据,还可能脱离事务快照。临时表、会话变量、锁定读和依赖连接状态的查询同样不能任意切换连接。连接池与代理配置应明确事务开始后是否固定目标,并确保提交或回滚后状态被清理。
常见的读后写保护方式包括会话粘滞、提交后的一段时间内读主、由复制位置确认副本已追上后再读取,或将一致性要求作为请求上下文传递。每种方式都有成本:粘滞可能把更多流量留在主库;固定等待时间无法保证副本一定追上;位置确认需要数据库和驱动提供相应能力。选择前要明确适用范围和超时后的降级行为。
监控副本接收和应用进度、复制队列、事务应用速度、时间延迟和主库写入速率。单一“延迟秒数”指标是线索,不说明某条刚提交的记录何时可见;空闲期接近零的读数也无法预测突发写入后的追赶能力。观察采样连续性、积压增长与恢复速度,并结合实际业务探针检查关键变更在副本上的可见时间。多个副本还要分别观测,避免负载均衡将同一用户连续请求交给新鲜度不同的节点。
把所有 SELECT 丢给副本会破坏读己之写;把某次零延迟采样当作强一致保证也不成立。即使系统常态下复制非常快,副本故障或写入尖峰也可能让旧值窗口扩大。验收时应能指出每类查询的路由理由,并在副本滞后时得到符合业务规则的结果或明确降级,而不是出现间歇性状态回退。读写分离是容量与一致性之间的取舍,边界必须由应用主动表达。