Mysql读写分离的过期读问题

在数据库高可用架构中,读写分离是提升系统吞吐量的核心手段。其基本逻辑是:主库(Master)负责所有写入操作,从库(Slave)分担查询压力。然而,由于主从同步存在物理延迟,客户端可能在备库读到尚未同步的旧数据,这种现象被称为"过期读" 。

一、 读写分离的实现架构

实现读写分离主要有两种主流方案:

  1. 客户端直连 (Client-side)
  • 执行逻辑:应用代码内部实现负载均衡,配置主库和多个从库的 IP,根据请求类型分发。
  • 特点:性能损耗极低,架构简单;但运维成本高,主备切换时需要修改所有客户端配置 。
  1. 带 Proxy 的中间件架构 (Proxy-side)
  • 执行逻辑:应用只连接 Proxy,由 Proxy 负责 SQL 解析、路由分发和后端存活检测。
  • 特点:对应用透明,运维方便;但增加了网络延迟,且 Proxy 自身需要考虑高可用 。

二、 解决"过期读"的六种方案

为了在提升性能的同时保证数据准确,需要针对不同业务场景选择合适的"过期读"解决方案。

  1. 强制走主库方案
  • 策略:将查询请求分为"允许延迟"和"必须实时"两类。
  • 示例:用户刚修改完个人资料,其"个人中心"页面必须强制查主库以保证可见性;而其他用户浏览该资料时可走备库。
  1. Sleep 方案
  • 策略 :在写操作后,读操作前让客户端执行一次短时间的 sleep
  • 评价:这是一种不严谨的概率性方案。如果延迟超过 sleep 时间,依然会读到旧数据;反之则会浪费响应时间。
  1. 判断主备延迟方案
  • 在查询备库前,先通过以下方式确认同步进度:
    • 监控 SBM :确保 seconds_behind_master 为 0。
    • 对比位点 :确保已收到的日志位点 Read_Master_Log_Pos 等于已执行位点 Exec_Master_Log_Pos
    • 对比 GTID 集合 :确保备库已执行的集合 Executed_Gtid_Set 包含已收到的集合 Retrieved_Gtid_Set
  1. 配合半同步复制 (Semi-Sync) 方案
  • 策略:利用半同步复制保证主库返回成功前,至少有一个备库收到了 binlog。
  • 配合:结合"对比位点"法。只要备库收到的位点等于主库最新的位点,代表数据已到。
  • 局限:在一主多从架构下,如果请求落到了那个恰好没收到日志的备库,方案会失效 。
  1. MASTER_POS_WAIT 等位点方案
  • 物理流程
    1. 写操作完成后,通过 SHOW MASTER STATUS 获取主库当前的 FilePosition
    2. 客户端去备库执行 SELECT MASTER_POS_WAIT(File, Position, timeout)
    3. 如果函数返回 ≥0\ge 0≥0,说明备库已追平该点,可以安全读取。
  1. WAIT_FOR_EXECUTED_GTID_SET 等 GTID 方案
  • 这是目前最先进且精确的方案,基于 MySQL 5.7+ 的 GTID 机制
  • 物理流程
    1. 主库写入成功后返回该事务的 gtid 给客户端。
    2. 客户端去备库执行 SELECT WAIT_FOR_EXECUTED_GTID_SET(gtid, timeout)
    3. 备库会阻塞等待,直到该 GTID 被本地执行完成。
  • 优化 :设置 session_track_gtids=OWN_GTID,主库会在响应报文里自动带上最新的 GTID,简化开发逻辑 。
相关推荐
程序员阿鹏25 分钟前
如何实现MySQL分库分表?
数据结构·数据库·sql·mysql·缓存
风哥2号43 分钟前
数据库教程FGMT33‑MySQL主从复制项目实施与维护06(MySQL8.4/9.7 MGR组复制)
数据库·mysql
liangsheng_g1 小时前
Spring事务传播行为分派与挂起恢复源码实战
数据库·sql·spring
蓝速科技1 小时前
信创终端 POC 测试实战与选型避坑指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理
风哥2号1 小时前
数据库教程FGMT29‑Linux平台MySQL5.7安装配置与管理入门
数据库
杨云龙UP2 小时前
MySQL Host is blocked because of many connection errors 导致 JDBC 连接失败排查与解决
linux·运维·网络·数据库·sql·mysql·登录失败
这个DBA有点耶3 小时前
数据库数据同步解决方案怎么选?6款主流工具横向对比与信创选型指南
数据库·架构·dba
刃神太酷啦4 小时前
Redis 核心进阶:哨兵、集群、缓存问题与分布式锁详解----《Hello Redis!》(6)
linux·c语言·数据库·c++·redis·分布式·缓存
小雷信息医学4 小时前
不会写复杂代码也能发 SCI?手把手教你用 InSpireR 交互系统一键提取、合并与导出临床科研宽表【第三章】
数据库
程序员梅雨4 小时前
MySQL底层探索(一):什么是脏页?什么是冷热分离?
mysql·面试