Oracle 数据隔离

事务隔离级别与Oracle一致性读
  • 事务的隔离级别 

 

◆脏读:一个事务会读进还没有被另一个事务提交的数据,所以你会看到一些最后被另一个事务回滚掉的数据。

 

  ◆不可重复读:一个事务读进一条记录,另一个事务更改了这条记录并提交完毕,这时候第一个事务再次读这条记录时,它已经改变了。

 

  ◆ 幻影读:一个事务用Where子句来检索一个表的数据,另一个事务插入一条新的记录,并且符合Where条件,这样,第一个事务用同一个where条件来检索数据后,就会多出一条记录。

 

  • 一致性读

 

一致性读(Consistent Get)是Oracle一个非常优秀的特性.(当然它也是产生ora-1555错误的主要原因)在标准SQL中,为了防止并发事务中产生脏读,就需要通过加锁来控制.这样就会带来死锁、阻塞的问题,即时是粒度最小的行级锁,也无法避免这些问题.

 

为了解决这一矛盾,Oracle充分利用的回归段,通过会滚段进行一致性读取,即避免了脏读,又大大减少了系统的阻塞、死锁问题.

 

Oracle是如何实现一致性读的:

当Oracle更新数据块(Data Block Oracle中最小的存储单位)时,会在两个地方记录下这一更新动作.一个是在Redo Segment,.一个是回滚段UNDO Segment.并在数据块头部标示出来是否有修改数据.一个语句在读取数据快时,如果发现这个数据块是在它读取的过程中被修改的(即开始执行读操作时并没有被修改),就不直接从数据块上读取数据,而是从相应的回滚段条目中读取数据.这就保证了最终结果应该是读操作开始时的那一时刻的快照(snapshot),而不会受到读期间其他事务的影响.这就是Oracle的一致性读,也可以叫做多版本(Multi-Versioning).

 

 

 

### Oracle 数据库事务隔离级别 #### 什么是事务隔离级别? 事务隔离级别定义了一个事务与其他事务之间的可见性和交互程度。不同的隔离级别会影响并发事务的行为,从而决定数据一致性和性能之间的平衡。 在 Oracle 中,默认的事务隔离级别是 **READ COMMITTED**,这意味着一个事务只能看到在其之前已经提交的数据变化[^5]。 --- #### Oracle 支持的事务隔离级别 Oracle 提供了以下四种事务隔离级别: 1. **READ UNCOMMITTED** - 允许读取未提交的数据(脏读)。 - Oracle 不支持此隔离级别,因为其最低隔离级别为 READ COMMITTED[^5]。 2. **READ COMMITTED (默认)** - 只能读取已提交的数据。 - 同一事务内的多次查询可能会返回不同结果(不可重复读现象)。 - 此模式下不会发生脏读,但可能发生不可重复读和幻读[^5]。 3. **REPEATABLE READ** - 在同一事务中,第一次读取的结果在整个事务期间保持不变。 - Oracle 并不显式支持 REPEATABLE READ,但在某些情况下可以通过 `SET TRANSACTION ISOLATION LEVEL SERIALIZABLE` 实现类似效果。 4. **SERIALIZABLE** - 提供最高的隔离级别,确保事务完全独立运行。 - 所有查询都会反映事务开始时的状态,防止不可重复读和幻读。 - 性能开销较大,可能引发更多的锁等待或死锁问题。 --- #### 如何设置事务隔离级别? 可以使用 SQL 命令动态调整当前会话的事务隔离级别: ```sql SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 或者 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; ``` 需要注意的是,在 Oracle 中无法直接指定 `READ UNCOMMITTED` 和 `REPEATABLE READ` 的隔离级别。 --- #### 隔离级别带来的常见问题及其解决方法 | 问题 | 描述 | 解决方案 | |--------------|----------------------------------------------------------------------------------------|--------------------------------------------------------------------------| | 脏读 | 读取到其他事务尚未提交的数据 | 使用 READ COMMITTED 或更高隔离级别 | | 不可重复读 | 同一事务中两次读取相同记录得到不同结果 | 升级至 SERIALIZABLE 隔离级别;或者通过锁定机制(如 SELECT FOR UPDATE)实现逻辑上的重复读 | | 幻读 | 查询结果集中出现了新插入/删除的行 | 设置 SERIALIZABLE 隔离级别 | --- #### 面试题及相关解答 1. **问:Oracle 默认的事务隔离级别是什么?** - 答:默认隔离级别为 **READ COMMITTED**,意味着只允许读取已提交的数据[^5]。 2. **问:如何避免不可重复读的现象?** - 答:可通过升级事务隔离级别至 SERIALIZABLE 来避免不可重复读;另外也可以采用 `SELECT ... FOR UPDATE` 显式加锁的方式处理特定场景下的需求。 3. **问:Oracle 是否支持所有的 ANSI 定义的标准隔离级别?如果不支持,请说明具体差异。** - 答:Oracle 不支持全部标准隔离级别。其中 `READ UNCOMMITTED` 是不允许存在的概念,而 `REPEATABLE READ` 则需借助于 `SERIALIZABLE` 达成近似功能[^5]。 4. **问:如果两个用户同时修改同一条记录会发生什么情况?怎样避免冲突?** - 答:当第二个用户的更新尝试违反第一个已完成更改后的约束条件时,则会产生 ORA 错误提示丢失更新的情况。为了避免此类竞争状况的发生,建议利用乐观锁策略或是悲观锁手段加以管控,比如运用版本号字段配合 WHERE 子句验证原始值是否存在变更等方式达成目标。 --- ### 示例代码展示 下面是一个关于如何手动控制事务的例子: ```plsql BEGIN -- 开始一个新的串行化事务 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- 更新某张表中的部分数据 UPDATE employees SET salary = salary * 1.1 WHERE department_id = 50; -- 查看受影响行数 DBMS_OUTPUT.PUT_LINE('Updated ' || SQL%ROWCOUNT || ' rows.'); -- 如果一切正常则提交事务 COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; -- 出错时回滚整个事务 RAISE; END; / ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值