当前位置: 首页 > news >正文

并发事务~

一、并发事务出现的场景大致可以划分为以下 3 种:

1、读-读:即并发事务相继读取相同的记录。

读取操作本身不会对记录有一毛钱影响,并不会引起什么问题,所以允许这种情况的发生。

2、写-写:即并发事务相继对相同的记录做出改动。

我们前边说过,在这种情况下会发生脏写的问题,任何一种隔离级别都不允许这种问题的发生。所以在多个未提交事务相继对一条记录做改动时,需要让它们排队执行,这个排队的过程其实是通过锁来实现的。

3、读-写:即一个事务进行读取操作,另一个进行改动操作。

这种情况下,主要可能导致以下三类问题(严重性递增):

  • 脏读 (Dirty Read):
    • 问题描述:一个事务 (T1) 读取了另一个未提交事务 (T2) 修改的数据。随后,T2 可能会回滚(撤销修改),导致 T1 读取的数据实际上从未在数据库中有效存在(即“脏”数据)。
    • 危害:T1 基于无效的数据进行了操作,可能导致业务逻辑错误。
    • 示例:T2 更新账户 A 余额为 +100(但尚未提交);T1 读取账户 A 余额为 +100;T2 因为某种原因回滚,账户 A 实际余额未变;T1 基于读到的 +100 余额进行操作出错。
  • 不可重复读 (Non-Repeatable Read):
    • 问题描述:在同一个事务 (T1) 中,多次读取同一行数据(例如SELECT ... WHERE id=1),在 T1 未结束期间,另一个事务 (T2)提交了对该行数据的修改(UPDATE 或 DELETE),导致 T1 前后两次读取的结果不一致。
    • 危害:破坏了一个事务内逻辑一致性的预期。在一个事务里读取同一个东西,值变了。
    • 示例:T1 第一次查询账户 A 余额为 500;此时 T2 提交了对账户 A 的更新,余额变为 400;T1 第二次查询账户 A 余额,发现变成 400 了,与第一次不一致。
  • 幻读 (Phantom Read):
    • 问题描述:在同一个事务 (T1) 中,多次执行相同的范围查询(例如SELECT ... WHERE value > 100),在 T1 未结束期间,另一个事务 (T2)提交并插入 (INSERT) 或删除 (DELETE) 了某些符合该查询条件范围的数据行,导致 T1 前后两次查询得到的行数或结果集发生了变化(即使同一个 id 的值没变)。
    • 危害:破坏了一个事务内逻辑一致性的预期。范围查询的结果集在事务过程中“凭空”多出了或消失了行,如同幻影。
    • 示例:T1 查询所有余额大于 100 的账户,得到 5 条记录;此时 T2 提交了一个新账户的 INSERT,该账户余额为 200;T1 再次查询余额大于 100 的账户,得到 6 条记录。或者 T2 删除了一条记录,第二次查询返回更少的行。

重要区别:                                                                                 

  • 脏读 vs 不可重复读:脏读读取的是未提交的数据;不可重复读读取的是已提交的数据,但同一个行记录的值在事务过程中被其他事务修改了。                                                 
  • 不可重复读 vs 幻读:不可重复读关注的是同一个行记录的值是否被修改或删除;幻读关注的是满足查询条件的行数/结果集是否因插入或删除操作而改变(新的、之前不存在的行“出现”或“消失”)。                                                                               

二、SQL 标准事务隔离级别及其解决的问题

  为了解决读写冲突导致的问题,SQL 标准定义了四种隔离级别,隔离性由低到高,解决的问题也逐步增多:

  • 读未提交 (Read Uncommitted):
    • 最低隔离级别。
    • 可能出现的问题:脏读、不可重复读、幻读。
    • 解决问题:无。它完全不做任何并发控制(除了可能防止某些最极端的损坏如更新丢失),性能最高但数据一致性风险最大。一般不推荐使用。
  • 读已提交 (Read Committed):
    • 大部分主流数据库的默认隔离级别(如 Oracle, PostgreSQL, SQL Server)。注意:MySQL InnoDB 默认是 Repeatable Read,这与标准不同。
    • 可能出现的问题:不可重复读、幻读。
    • 解决问题:脏读。
    • 原理简述:一个事务只能读取到其他事务已经提交的修改。通常通过在每次 SELECT 时获取一个短暂的读锁(或者通过 MVCC,读取当前已提交的最新快照)来实现,读取完成后立即释放锁。
  • 可重复读 (Repeatable Read):
    • MySQL InnoDB 存储引擎的默认隔离级别。
    • 可能出现的问题:
      • SQL 标准定义:幻读。
      • MySQL InnoDB 的实际实现:通过 MVCC 和 Next-Key Locking 机制,基本避免了幻读。这在 MySQL 中是一个重要的特性和优化。
    • 解决问题:脏读、不可重复读(并且在 MySQL InnoDB 中,基本解决了幻读)。
    • 原理简述:在整个事务执行过程中,第一次读取某行数据时会建立一个快照(MVCC),后续对该行的读取都基于这个快照,其他事务提交的 UPDATE 对该事务不可见。同时,为了防止新行插入造成的幻读,会对查询涉及的范围加间隙锁 (Gap Lock) 或 Next-Key Lock。但已提交的其他事务的 INSERT 可能影响该事务中后续的 INSERT/UPDATE 操作(数据行冲突)。
  • 串行化 (Serializable):
    • 最高隔离级别。
    • 可能出现的问题:无(完全隔离,所有问题都解决)。
    • 解决问题:脏读、不可重复读、幻读。
    • 原理简述:通过强制所有事务串行执行来实现(类似于单线程)。具体实现可能是在 SELECT 读取的范围自动加上共享锁 (Shared Lock),或者在涉及写入的冲突时通过锁竞争强制串行。性能开销最大。

三、隔离级别与问题总结表

也就是说:

  • READ UNCOMMITTED隔离级别下,可能发生脏读、不可重复读和幻读问题。
  • READ COMMITTED隔离级别下,可能发生不可重复读和幻读问题,但是不可以发生脏读问题。
  • REPEATABLE READ隔离级别下,可能发生幻读问题,但是不可以发生脏读和不可重复读的问题。
  • SERIALIZABLE隔离级别下,各种问题都不可以发生。
http://www.dtcms.com/a/283868.html

相关文章:

  • 一种融合人工智能与图像处理的发票OCR技术,将人力从繁琐的票据处理中解放
  • 视频安全新思路:VRM视频分片错序加密技术
  • 小架构step系列17:getter-setter-toString
  • 智能视频分析:多行业安全防控的“AI之眼”
  • 嵌入式学习-PyTorch(7)-day23
  • Flutter Android打包学习指南
  • 如何下载视频 (pc端任何视频均可下载)
  • 英伟达Cosmos研究团队开源DiffusionRenderer (Cosmos): 神经逆向与正向渲染与视频扩散模型
  • 视频码率是什么?视频流分辨率 2688x1520_25fps采用 h264格式压缩,其码率为
  • Web攻防-PHP反序列化Phar文件类CLI框架类PHPGGC生成器TPYiiLaravel
  • blender 导入的fbx模型位置错乱
  • 【3D大比拼第一集】--max,maya,c4d,blender的命令搜索功能
  • iOS App 电池消耗管理与优化 提升用户体验的完整指南
  • 【力扣 中等 C】97. 交错字符串
  • 量化环节:Cont‘d
  • 题解:CF1829H Don‘t Blame Me
  • 相位中心偏置天线的SAR动目标检测
  • 代码随想录算法训练营第二十三天
  • Apache SeaTunnel配置使用案例
  • 【Leetcode】栈和队列算法题(逆波兰表达式、二叉树层序遍历、最小栈、栈的压入弹出序列)
  • 贪心算法(排序)
  • 如何通过ATS/HTTPS数据防篡改来加密视频?
  • 部署-k8s和docker的区别和联系
  • 川翔云电脑:云端算力新标杆,创作自由无边界
  • STM32上移植Lua解析器
  • 性能优化实践:Modbus 在高并发场景下的吞吐量提升(二)
  • ClickHouse 多表 JOIN 时 SELECT * 语法错误解析与解决方案
  • Web3智能合约技术论述
  • GraphQL的N+1问题如何被DataLoader巧妙化解?
  • 阿里京东美团即时零售大战,品牌商如何从被动到主动?