一、什么是事务
事务(Transaction)是用户定义的一个数据库操作序列,是一个不可分割的整体。这些操作要求全部完成或者全部不完成。事务是对数据库进行操作的最基本的逻辑单位,它可以是一组SQL语句、一条SQL语句或整个程序,通常情况下,一个应用程序里包含多个事务。此外,事务还是回复和并发控制的基本单位。
二、事务的特性
事务具有以下4个最重要的特性,按照特性组合成为ACID属性。
2.1、原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的所有数据的增删改操作要么全部执行,要么全部都不执行。
2.2、一致性(Consistency)
事务完成时,要使所有的数据都保持一致的状态,换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
2.3、隔离性(Isolation)
即使每个事务都能确保一致性和原子性,但如果有几个事务并发执行,如果在执行的过程中发生了事务间的交叉,也会导致数据库发生不一致的情况。事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
2.4、持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
三、数据异常
因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常:
3.1、脏读
当一个事务修改数据时,另一事务读取了该数据,但是第一个事务由于某种原因取消对数据修改,是数据返回了原始状态,这时第二个事务读取的数据与数据库中的数据不一致,这就叫脏读。
3.2、不可重复读
是指一个事务读取数据库中的数据后,另一个事务则更新了数据,当第一个事务再次读取其中的数据时,就会发现诗句已经发生了改变,这就是不可重复读取。不可重复读取所导致的结果就是一个事务前后两次读取的数据不相同。
3.3、幻读
如果一个事务基于某个条件读取数据后,另一个事务则更新了同一个表中的数据,这时第一个事务再次读取数据时,根据搜索的条件返回了不同的行,这就是幻读。
四、事务隔离级别
针对读取数据时可能产生的不一致现象,在SQL92标准中定义了5个事务的隔离级别:
- NO_TRANSACTION : 不支持事务
- READ_UNCOMMITTED : 允许脏读、不可重复读、幻读
- READ_COMMITTED : 允许不可重复读、幻读,不允许脏读
- REPEATABLE : 允许幻读,不允许脏读、不可重复读
- SERIALIZABLE : 脏读、不可重复读、幻读都不允许
Oracle默认的隔离级别是READ_COMMITTED
Oracle支持上述5中隔离级别中的两种:READ_COMMITTED和SERIALIZABLE。
Oracle中还定义了READ ONLY和READ WRITE隔离级别:
- READ ONLY : 事务中不能有任何修改数据库中数据的操作语句,是SERIALIZABLE的一个子集。
- READ WRITE : 它是默认设置,该选项表示在事务中可以有访问语句、修改语句、但不经常使用。
五、事务状态
对数据库进行操作的各种事务共有5种状态:
5.1活动状态
事务在执行时的状态叫活动状态
5.2部分提交状态
事务中最后一条语句被执行后的状态叫部分提交状态。事务虽然已经完成,但由于实际输出可能在内存中,在事务成功前可能会发生硬件故障,有时不得不中止,进入中止状态。
5.3失败状态
事务不能正常执行的状态叫失败状态。导致失败状态发生的可能原因与硬件原因或逻辑错误,这样事务必须回滚,就进入了中止状态。
5.4提交状态
事务在部分提交后,将往硬盘上写入数据,最后一条信息写入后的状态叫提交状态,进入提交状态的事务就成功完成了。
5.5中止状态
事务回滚,并且数据库已经恢复到事务开始执行前的状态叫中止状态。
注意:提交状态和中止状态的事务统称为已决事务,处于活动状态、部分提交状态和失败状态的事务称为未决事务。
六、事务控制命令
6.1、设置事务
6.1.1、设置只读事务
如果将事务设置为只读,将不建立回滚信息,适合以SQL查询语句组成的事务。
set transaction read only;
6.1.2、设置读写事务
设置事务为读写事务,是事务的默认方式,将建立回滚信息
set transaction read write
6.1.3、设置read committed事务
设置事务为read commited,允许不可重复读、幻读,不允许脏读
set transaction isolation level read committed
6.1.4、设置serializable事务
设置事务为serializable,不允许重复读、幻读、脏读
set transaction isolation level serializable
6.1.5、设置单个回话的事务
alter session set transaction isolation level read committed
注意:这些事务之间是互斥的,不能同时设置两个或两个以上的选项。
6.2、事务提交
在Oracle数据库管理系统中,为了保证数据的一致性,在SGA内存中将为每个客户机建立工作区,客户机对数据库进行操作处理的事务都在工作区内完成,只有在输入事务提交命令后,工作区内的修改内容才写入到数据库上,称为物理写入,这样可以保证在任意的客户机没有物理提交修改以前,其他客户机读取的数据库中的数据时完整的、一致的。
6.2.1、提交前的SGA的状态
在事务提交前,Oracle SQL语句执行完毕,SGA内存中的状态如下:
- 回滚缓冲区生成回滚记录,回滚信息包含所有已经修改值的旧值。
- 日志缓冲区生成该事务的日志,在事务提交前已经写入物理磁盘。
- 数据库缓冲区被修改,这些修改在事务提交后才写入物理磁盘。
6.2.2、提交的工作
事务的提交将完成下列主要工作:
- 在相关的事务表中记录提交的事务,给每个事务富裕唯一的一个系统变更号(System Change Number,SCN),将其记录在表中。
- SGA数据缓冲区内的数据写入物理数据表。
- 由LGWR(日志写入进程),将SGA日志缓冲区内的日志项写入联机日志文件。
- 解除对记录和表的封锁。
- 标记该事务已经完成。
6.2.3、提交的方式
事务有3种提交方式:
- 显示提交:使用commit命令是当前事务生效。
- 自动提交:认为设置自动提交:set autocommit on,只针对当前连接
- 隐式提交:
- (1)正常执行完成的DDL语句:create、alter、drop
- (2)正常执行完成的DCL语句:grant、revoke
- (3)正常退出的SQLPlus或者SQL Developer等客户端
- (4)正常关闭数据库
6.3、事务回滚
事务回滚是指撤销未提交事务中SQL命令对数据所做的修改,已经提交的事务不能进行回滚。整个事务的回滚将完成如下主要工作:
- 利用回滚段中存储的数据来撤销未提交事务中SQL命令所做的修改
- 解除对所有数据的事务封锁
- 结束事务
6.4、事务回滚点
回滚点又称为保存点,即指在含有较多SQL语句的事务中间设定的回滚标记,其作用类似于调试程序的中断点。利用保存点可以将事务划分成若干小部分,这样就不必回滚整个事务,可以回滚到指定的保存点,有更大的灵活性。
回滚到指定保存点将完成如下工作:
- 回滚保存点之后的部分事务。
- 删除再改保存点之后建立的全部保存点,该保存点保留,以便更多次回滚。
- 解除保存点之后表的封锁或行的封锁。
6.4.1建立保存点
savepoint sp_test01
6.4.2使用保存点
rollback to sp_test01
注意:以上介绍的使用rollback命令回滚事务称之为显示回滚,还有一种回滚叫隐式回滚。如果系统在事务执行期间发生错误、死锁和中止等情况时,系统将自动完成隐式回滚。