可重复读

本文详细介绍了DB2数据库中的隔离级别概念,特别是可重复读(Repeatable Read)隔离级别,探讨了其如何防止脏读、不可重复读等问题,并通过实例解释了其在实际应用场景中的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《循序渐进DB2-系统管理、运行维护与应用案例》第10章锁和并发,本章首先介绍了通用的事务概念,并指出DB2在用户读取、写入数据时的加锁策略、锁模式、兼容性等。本章还介绍了在并发控制中常碰到的4种数据异常现象,同时讲述了DB2如何使用锁克服这些问题的。本节为大家介绍可重复读(RR-Repeatable Read)。

AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验

10.3  隔离级别(Isolation Levels)

维护数据库的一致性和数据完整性,同时又允许多个应用程序同时访问同一数据,这样的特性称为并发性。DB2数据库用来尝试强制实施并发性的方法之一是通过使用隔离级别,它决定在第一个事务访问数据时,如何对其他事务锁定或隔离该事务所使用的数据。DB2使用下列隔离级别来强制实施并发性:

可重复读(Repeatable Read)

读稳定性(Read Stability)

游标稳定性(Cursor Stability)

未提交读(Uncommitted Read)

可重复读隔离级别可以防止所有现象,但是会大大降低并发性(可以同时访问同一资源的事务数量)。未提交读隔离级别提供了最大的并发性,但是"脏读"、"幻像读"和"不可重复读"都可能出现。默认的隔离级别是CS。

10.3.1  可重复读(RR-Repeatable Read)

可重复读隔离级别是最严格的隔离级别。在该隔离级别下,一个事务的影响完全与其他并发事务隔离,脏读、不可重复的读、都不会发生。当使用可重复读隔离级别时,在事务执行期间会锁定该事务以任何方式引用的所有行。因此,如果在同一个事务中发出同一个SELECT语句两次或更多次,那么产生的结果数据集总是相同的。因此,使用可重复读隔离级别的事务可以多次检索同一行集,并对它们执行任意操作,直到提交或回滚操作终止该事务。但是,在事务存在期间,不允许其他事务执行会影响这个事务正在访问的任何行的插入、更新或删除操作。为了确保这种行为不会发生,锁定该事务所引用的每一行-- 而不是仅锁定被实际检索或修改的那些行。因此,如果一个事务扫描了1000行,但只检索10行,那么它所扫描的1000行(而不仅是被检索的10行)都会被锁定。

那么在现实环境中可重复读隔离级别是如何工作的呢?假定如家酒店使用DB2数据库跟踪如家酒店的客房信息,包括房间预订和房价信息,还有一个基于Web的应用程序,它允许顾客按"先到先服务"的原则预订房间。如果旅馆预订应用程序是在可重复读隔离级别下运行的,当顾客扫描某个日期段内的可用房间列表时,您(旅馆经理)将无法更改那些房间在指定日期范围内的房价。同样,其他顾客也无法进行或取消将会更改该列表的预订(直到第一个顾客的事务终止为止)。图10-6说明了这种行为。

 
(点击查看大图)图10-6  可重复读隔离级别的示例

在使用可重复读隔离级别时,一个事务中所有被读取过的行上都会被加上S锁,直到该事务被提交或回滚,行上的锁才会被释放。这样可以保证在一个事务中即使多次读取同一行,得到的值也不会改变。另外,在同一事务中即使以同样的搜索标准重新打开已被处理过的游标,得到的结果集也不会改变。可重复读相对于读稳定性而言,加锁的范围更大。对于读稳定性,应用程序只对符合要求的所有行加锁;而对于可重复读,应用程序将对所有被扫描过的行都加锁。

可重复读(RR)会锁定应用程序在工作单元中引用的所有行。利用"可重复读",在打开游标的相同工作单元内一个应用程序发出一个SELECT语句两次,每次都返回相同的结果。利用"可重复读",不可能出现丢失更新、脏读和幻像读的情况。


在该工作单元完成之前,"可重复读"应用程序可以尽可能多次地检索和操作这些行。但是,在该工作单元完成之前其他应用程序均不能更新、删除或插入可能会影响结果表的行。"可重复读"应用程序不能查看其他应用程序的未落实更改。

### 关于 openGauss 中不可重复的问题及其解决方案 #### 不可重复的概念 不可重复是指在同一事务中多次执行相同的查询时,返回的结果集不一致的现象。这通常是由于其他并发事务修改了当前事务正在访问的数据并提交所致。 #### openGauss 的隔离级别与不可重复的关系 openGauss 支持两种主要的隔离级别:已提交(Read Committed)和可重复(Repeatable Read)。两者的区别在于如何处理快照的获取频率以及是否允许不可重复现象的发生[^1]。 - **已提交(Read Committed)** 在此隔离级别下,每次 SQL 查询都会重新获取最新的数据快照。这意味着如果其他事务在此期间更新了某些记录,则当前事务可能会看到这些变化。因此,在已提交模式下,不可重复问题是被接受的,因为该级别的设计目标是确保只取到已经提交的数据,而不会关注同一事务内的结果一致性[^2]。 - **可重复(Repeatable Read)** 可重复通过在整个事务生命周期内固定一次初始快照来防止不可重复的情况发生。一旦事务开始,它将持续使用这个固定的快照直到结束为止,从而保证即使有其他事务对相同数据进行了更改并提交,本事务仍然能够保持其视图不变,有效解决了不可重复问题。 #### 解决方案概述 为了彻底消除不可重复的风险,建议将数据库会话设置为更高的隔离等级——即“可重复”。这样可以利用 MVCC 和快照技术保障整个事务过程中所见数据的一致性。然而需要注意的是提高隔离级虽然增强了数据安全性但也可能带来性能开销增加等问题所以在实际应用当中应权衡考虑业务需求与系统效率之间的关系做出合理选择。 ```sql -- 设置事务隔离级别为 REPEATABLE READ SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; ``` #### 动态规划与遗传算法在多表连接中的作用 尽管上述讨论集中在隔离级别上以解决不可重复问题,但值得一提的是 openGauss 还采用了先进的优化策略如动态规划和遗传算法用于复杂查询特别是涉及多个表格间的联接操作时寻找最优执行计划。这对于大规模数据分析场景尤为重要因为它可以帮助减少因不当索引或者错误估计而导致额外资源消耗的可能性同时进一步提升整体吞吐量表现[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值