暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

浅谈 Oracle 事务处理(上)

SQL干货分享 2021-08-13
1089

(CSDN博主:写代码也要符合基本法)
各位看官老爷大家好,今天我们来简单了解一下有关数据库事务处理(Transaction)的一些基本概念

事务
事务的定义是一个独立的逻辑工作单元:它由特定的一系列必须作为一个整体一起成功或失败的 SQL 语句组成
每个事务都有一个很清楚的起点,即第一个可执行的 SQL 语句开始执行时,以及一个确定的结束点:当事务的工作进行了提交或回滚之后
已经开始但还没有将其工作提交或回滚的事务是活动事务,活动事务中的所有修改在提交之前都是不确定的,如果事务失败了或进行了回滚,则这些不确定的修改将不复存在

编写合理的事务代码的关键就是准确地将事务边界设定在一个逻辑工作单元中,并确保一个事务之内的所有运算都作为一个整体来处理

事务的属性
事务被赋予四大属性,简称 ACID 属性
  • 原子性 Atomicity

在物质的微观结构中,认为原子是不可再分的,在数据库中,事务也被赋予不可再分的属性:事务中的所有任务都必须执行或者都不执行,不存在部分事务
  • 一致性 Consistency

所谓数据库的一致性状态,指的就是在同一时刻,不同用户读取同样的数据,应当保证他们获得同样的有效结果
而事务的一致性,就是说事务必须将数据库从一个一致性状态带到另一个一致性状态,不能造成有效数据读取结果的混乱
这里需要注意的是,一致性状态强调的是确定的数据:比如说用户甲正在修改某条数据,尚未提交,此时用户乙需要读取这条数据,那么他会从临时表中得到甲修改前的数据,事实上其它所有的用户都只能读到修改前的数据,因为甲现在并没有提交或回滚,根据事务的原子性来说,其所做改动尚未生效
但是唯独甲可以读取到自己修改后的结果,那么此时难道违反了数据库的一致性状态了吗?当然没有,虽然甲现在能读到数据修改后的结果,但此时这个结果对于包括甲在内的所有用户来说,都是不确定的,因为它还没有提交或者回滚,此时对于甲来说,真正确定的数据其实还是他修改前的
所以事务的一致性,是指一个事务结束时,数据库从一个一致性状态来到了另一个一致性状态,对于所有用户来说确定的数据是唯一的

  • 隔离性 Isolation

事务的隔离性是指:一个事务所带来的影响直到该事务提交之前对其它事务来说都是不可见的

根据前文的描述,事务的隔离性保障了数据库的一致性状态

  • 持久性 Durability

经过提交的事务所进行的修改是永久性的,也就是说在事务被提交的那一刹那,事务所做过的修改将直接覆盖到磁盘当中,相关数据被彻底修改,此时数据再想恢复,就只能通过数据库的其它机制(例如日志)来找回,而没有任何指令能够轻松地回退修改了

事务隔离级别
ANSI/ISO SQL 标准定义了四个不同的事务隔离级别:未提交读、提交读、可重复读以及序列化
  • 未提交读(Read-uncommitted)允许其它事务读取本事务未提交之前的修改

  • 提交读(Read-committed)指 DBMS 对选定对象的写锁一直保持到事务结束,读锁将在 SELECT 操作后马上释放

  • 可重复读(Repeatable read)指在事务进行期间会锁定以任何方式引用的所有行,以保证在事务中第二次或更多次执行同一个查询时,总能得到同样的结果集

  • 序列化(Serializable)锁定整个范围的键,并一直持有锁,直至任务完成。序列化隔离级别下需要多个事务顺序执行

标准还为这四种隔离级别定义了某个特定隔离级别允许或者不允许的三种现象:脏读、不可重复读及幻读
  • 脏读(Dirty read)即读取到一个未提交的事务,由脏读建立的结果集应被看做是非常不可信的,因为它可能表示的是从来没有真正存在过的信息的视图

  • 不可重复读(Nonrepeatable read)指当事务第二次执行同一个查询时,由于另外的事务在此期间提交了更新而得到了不同的结果

  • 幻读(Phantom read)是指在本事务中第二次执行同一个查询时,由于另外的事务在此期间插入了新的行而得到了更多的结果

这里需要注意区分不可重复读和幻读的差别:两种现象都是指事务当中前后两次执行同样的查询得到了不一样的结果,这里不可重复读强调的是结果集范围没变,但其中的数据变了,而幻读强调的是读取到了更大体量的结果集,因为别的事务在此期间插入了符合该查询条件的新数据
随着隔离级别的提升,事物之间的隔离水平也相应提高,使得数据的一致性也就越高
默认地,Oracle 中的事务在其它用户提交工作后马上就允许读取,这意味着除非你将自己的事务隔离级别特意设定为只读或序列化,否则就可能发生不可重复读或幻读
只有序列化的事务完全没有发生这三种现象的可能性,它还允许进行更新,但是,序列化事务会降低数据库的并发度
如果你需要可重复读取并需要在事务中更新数据,将你的事务设置成在序列化模式下执行是你唯一的选择;如果事务需要可重复读但不会更新数据,那么你可以将事务设置为只读模式(READ ONLY),这将在事务完成之前或者系统超过其撤销保留周期之前保证可重复读
Oracle 不支持未提交读隔离级别,也不能改变数据库来让它支持,也就是说 Oracle 不会发生脏读
(未完待续)

文章转载自SQL干货分享,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论