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

问题:

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

总结

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

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(暂存热点数据,减轻数据库压力)。
相关推荐
TGITCIC1 小时前
2026数据分析Agent最新落地方向解析
数据库·数据分析·ai大模型·ai智能体·ai数据·ai问数·ai sql
wangqiaowq2 小时前
SQL Server 对非聚簇索引的 INCLUDE 列数量和大小有限制
数据库
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-核心业务流程图
java·数据库·spring boot·软件工程
松涛和鸣2 小时前
DAY49 DS18B20 Single-Wire Digital Temperature Acquisition
linux·服务器·网络·数据库·html
海边的Kurisu2 小时前
苍穹外卖日记 | Day3 公共字段填充、菜品模块
数据库
摆烂z3 小时前
mysql通过binlog恢复数据
数据库·mysql
老邓计算机毕设3 小时前
SSM学期分析与学习行为分析系统c8322(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学习·ssm 框架·学期分析·学习行为分析
学Linux的语莫3 小时前
python创建redis连接池
数据库·redis·缓存
运维有小邓@3 小时前
Log360 的可扩展架构(三):数据流管道
数据库·架构