数据库读写分离和事务的关系

问题:

数据库是读写分离架构,事务中的读操作没有强制走主库,这个时候是不是会有读延迟,读的操作比写操作慢,导致没有及时读到其他事务写的数据

总结

  • 读写分离和主从架构是一个概念,主库写,从库读,主从同步
  • 主从同步分成异步、半同步两种方式
  • 产生事务时,会强制走主库,事务中的读操作和写操作都会强制走主库

https://blog.csdn.net/qq_46371374/article/details/149513968

https://www.cnblogs.com/wxg1990/articles/19465535

https://www.cnblogs.com/88223100/p/On-the-pitfalls-of-MySQL-read-write-separation-and-corresponding-solutions.html

https://www.jianshu.com/p/8b43bbf52dc6

https://zhuanlan.zhihu.com/p/29166694


在读写操作处于同一事务时,读写分离通过事务绑定主库强制读主库策略运作,确保事务的原子性和一致性。以下是具体运作机制和解决方案:

一、核心运作机制

  1. 事务绑定主库
    当事务开始时,所有读写操作(包括SELECT查询)均路由到主库执行。例如:
    • 用户提交订单(写操作)和查询订单状态(读操作)在同一个事务中,系统会强制将查询请求也发送到主库,避免从库数据延迟导致的不一致。
    • 事务结束后,后续非事务性读操作可重新路由到从库。
  2. 主从数据同步
    主库执行完事务后,通过异步复制 (默认)或半同步复制 (可选)将数据变更同步到从库:
    • 异步复制:主库写入binlog后立即返回成功,不等待从库确认。性能高,但可能丢失少量数据(如主库崩溃时未同步的日志)。
    • 半同步复制:主库至少等待一个从库确认收到binlog后才返回成功。牺牲少量性能,但提升数据安全性。

二、事务中的读写分离解决方案

方案1:强制读主库(推荐)
  • 适用场景:对数据一致性要求极高的业务(如支付、订单状态查询)。
  • 实现方式
    • 代码层面 :通过注解或框架配置,强制事务中的读操作走主库。例如:

      复制代码

      java

      复制代码
      `@Transactional // 开启事务
      public void submitOrder(Order order) {
          orderMapper.insert(order); // 写操作(主库)
          Order result = orderMapper.selectById(order.getId()); // 强制读主库
      }`
    • 中间件层面:使用ShardingSphere等中间件,自动识别事务中的读操作并路由到主库。

方案2:同步复制(牺牲性能保一致)
  • 适用场景:金融交易等绝对不允许数据丢失的场景。

  • 配置示例 (MySQL):

    复制代码

    ini

    复制代码
    `# 主库配置
    sync_binlog=1          # 每次事务提交前将binlog刷盘
    innodb_flush_log_at_trx_commit=1 # 每次事务提交前将redo log刷盘
    
    # 从库配置(半同步复制)
    rpl_semi_sync_master_enabled=1
    rpl_semi_sync_master_wait_for_slave_count=1`
  • 缺点:主库响应时间增加,吞吐量下降。

方案3:延迟读取(折中方案)
  • 适用场景:对实时性要求不高,但需避免主从延迟的业务(如用户评论展示)。
  • 实现方式
    • 写操作后,延迟一段时间(如500ms)再执行读操作,给从库留出同步时间。
    • 通过缓存(如Redis)暂存写操作结果,读操作优先从缓存获取。

三、关键问题与对策

  1. 主从延迟导致的数据不一致
    • 问题:事务提交后,从库未同步完成,此时读从库会得到旧数据。
    • 对策
      • 强制读主库(方案1)。
      • 使用**GTID(全局事务标识)**追踪事务同步状态,确保读操作只发生在已同步的从库上。
  2. 事务跨主从库的分布式事务问题
    • 问题:若事务涉及多个主库或跨库操作,需保证ACID特性。
    • 对策
      • 使用XA协议 (两阶段提交)或TCC模式(补偿事务)实现分布式事务。
      • 避免跨库事务,通过业务设计将操作限制在单个库内。

四、实际案例

电商平台订单支付场景

  1. 用户提交订单(写主库)。
  2. 系统扣减库存(写主库)。
  3. 查询订单状态(强制读主库,避免从库延迟)。
  4. 支付成功后,异步更新从库数据(如用户积分、商品销量)。

技术栈

  • 数据库:MySQL(主从复制+半同步)。
  • 中间件:ShardingSphere(读写分离+事务路由)。
  • 缓存:Redis(暂存热点数据,减轻数据库压力)。
相关推荐
全栈老石3 小时前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
倔强的石头_1 天前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou642 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤3 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区4 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1774 天前
《从零搭建NestJS项目》
数据库·typescript
加号35 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏5 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐5 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再5 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip