一.事务的概念
数据存储的逻辑单位是数据块,数据操作的逻辑单位是事务。
事务(transaction)是用户的一组操作序列,由一条或多条 SQL 语句组成。
事务处理是 RDBMS 的核心。
事务管理技术主要包括数据库的恢复技术和并发控制技术,这也是 RDBMS 的重要组成部分。
处理一个事务时,Oracle 的执行过程如下:
服务器进程获取该事务 SQL 语句,检查共享池,查看是否包含有此 SQL 语句的共享 SQL 区;
如果没有,则分配新的 SQL 区,并对该 SQL 语句进行分析处理。如果有,则到下一步;
检查该用户是否有访问相关数据的权限,有则进行下一步,无则返回并提示权限不足;
锁定该 SQL 语句所涉及到的操作对象;
服务器进程将数据从数据文件中读入至 SGA 中(如果数据不在 SGA 中),并在 SGA 中进行操作;
为该事务自动产生递增的 SCN ,以保持一致性,同时将 SCN 记录在控制文件、数据文件头部、数据块头部及重做日志中;
LGWR 将将重做日志缓存中的重做日志和 SCN 写入联机重做日志文件中;
释放事务中各个 SQL 语句所占用的系统资源,并解除所有操作对象的锁定;
事务成功执行则返回成功代码,否则返回错误提示代码;
将事务标记为已完成;
DBWR 定期将数据高速缓存中的“脏数据”写入数据文件中;
Oracle 中,事务控制的基本语句有如下几个:
COMMIT,提交事务
ROLLBACK,回退事务
SAVEPOINT,设置保存点
ROLLBACK TO SAVEPOINT,回退至保存点
SET TRANSACTION,设置事务属性
SET CONSTRANTS,设置当前事务中约束检查的属性。
二.事务的生命周期
Oracle 的特点是没有“事务开始”的语句。这个也是我才知道,因为以前在 Oracle 中并没有接触过事务(突然想起看到的存储过程中也没有使用事务处理的)。而且,用户不需要也不能显示的开始一个事务。
三.事务的开始:
连接到数据库,并执行第一条 DML 语句时;
事务提交之后,即一个事务结束时;
四.事务的结束:
执行一条 COMMIT 或 ROLLBACK 语句时;
执行一条会自动提交事务的语句时;
执行一条 DML 语句失败的时候,此时会自动回退事务;
下列情况会自动提交事务:
执行一条 DDL 语句之后;
执行一条 DCL 语句之后;
与数据库的连接断开时;
如果使用客户端如 sqlplus 等工具连接数据库后,若是正常断开连接(使用 exit 或 disconnect 或 connect 另一个数据库),则事务会自动 COMMIT 。如果客户端异常终止,那么事务将会自动 ROLLBACK 。
除此之外,Oracle 中还能够设定是否进行自动提交(使用命令 SET AUTOCOMMIT ON/OFF)。一旦设置自动提交之后,用户的每次执行 INSERT、UPDATE、DELETE 命令成功后,系统都会自动 COMMIT 。默认是关闭的。
五.事务提交
事务提交时,Oracle 的工作如下:
为该事务自动产生递增的 SCN;
LGWR 将将重做日志缓存中的重做日志和 SCN 写入联机重做日志文件中;
释放事务中各个 SQL 语句所占用的系统资源,并解除所有操作对象的锁定;
给用户返回一个成功提示的代码;
将事务标记为已完成;
DBWR 定期将数据高速缓存中的“脏数据”写入数据文件中;
六.事务回退
事务回退时,Oracle 的工作如下:
通过读取已生成的 undo 信息,撤销所有已执行的更改;
释放事务中各个 SQL 语句所占用的系统资源,并解除所有操作对象的锁定;
给用户返回一个错误提示的代码;
将该事物标记为已完成;
七.保存点设置/回退
保存点是事务中的标志,可将一个大型的事务划分为几个小部分。
使用保存点可以只回退到事务中的指定保存点的位置,而无需回退整个事务。
使用下列语句来设置/回退至保存点:
SAVEPOINT savepoint_name;
ROLLBACK TO [SAVEPOINT] savepoint_name;
需要注意的是,保存点只是事务中的标志,并不表示事务的结束。只有在使用 COMMIT 或是 ROLLBACK 后,用户的事务处理才算结束。
当回退到保存点时,Oracle 的工作如下:
撤销保存点之后所有已执行的更改;
释放表村点之后各个 SQL 语句所占用的系统资源,并解除相关对象的锁定;
给用户返回一个成功会退到保存点的提示代码;
接下来,用户就可以继续执行当前事务了。
八.事务的属性
我们可以使用以下语句设置事物的属性,实际上是对事务性质的控制:
SET TRANSACTION READ WRITE
设置事务的可读写性,是事务的默认设置,以便在事务中使用 DML 语句修改数据。
SET TRANSACTION READ ONLY
设置事务的只读属性,在此事务中只能使用下列语句:SELECT、LOCK TABLE、SET ROLE、ALTER SYSTEM、ALTER SESSION。为了结束只读事务,必须运行 COMMIT 或 ROLLBACK 语句。
可用于保持一致性的数据存取(如报表),确保查询到的数据只是事务开始时就存在于数据库中的数据。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
设置事务的隔离等级为 READ COMMITTED,是事务的默认设置,保证事务中的 DML 语句所操作的数据是在该语句之前就已提交了的数据。提供了语句级的读一致性。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
设置事务的隔离等级为 SERIALIZABLE,保证事务读取的数据是事务开始时就存在于数据库中的数据。但与只读事务不同的是,事务中允许使用 DML 语句修改数据,并能够看到更改结果。
九.设置事务约束检查的属性
设置事务约束检查的属性适用于设置事务中所涉及到的约束的检查时间。以避免由于约束而导致事务失败的情况发生。
使用下列语句对约束进行设置:
SET CONSTRAINTS { constraint_name1 [, constraint_name2 ] ... | ALL } { IMMEDIATE | DEFERRED };
其中, constraint_name 表示该事物涉及的一个或多个约束的名称, ALL 表示事务所涉及到的所有约束。IMMEDAITE 表示在事务中的每条 DML 语句执行完毕之后就立刻检查, DEFERRED 表示在事务提交的时候才进行检查。
十.事物的状态和性质
事务从开始到成功完成或出错,中间经过一下几个不同的状态:事务初态、活动状态、失败状态、终止状态、提交状态。
事物的性质主要有以下几点:
·原子性:即事务不可再分,一个事务,执行的结果要么全部成功并提交,要么失败并回退。
·一致性:一个事务操作前后,数据库中的数据都应处于逻辑上的一致性状态。即事务操作前后,数据库中的数据应当满足所有的约束条件及业务规则。
·隔离性:一个事务的执行,不会受到其它事务的干扰。即事务内部所使用、操作的数据与其它事务是隔离的,在提交之前,只有执行该事物的用户能够看到修改后的数据,而且用户只能看到修改之前的数据。
SQL 92 标准中定义了 4 种事务隔离等级(Read Uncommitted,Read Committed,Repeatable Read,Serializable),用于指定在并发事务情况下,对 3 种读现象(dirty read,non-repeatable read,phantom read)的处理能力。而在 Oracle 中,仅提供了 Read Committed、Serializable 两种标准隔离等级,另外提供了 Read Only 隔离等级。使用这些隔离等级,Oracle 可以实现语句级读一致性(Read Committed),事务级读一致性(Read Only)。具体的一致性实现方法请参考 SCN 的分配,使用过程。
·持久性:一个事务一旦提交成功,那么它对数据的修改也就永久的保存下来。当在数据库中执行 INSERT、UPDATE、DELETE 修改数据时,Oracle 同时生成 redo 和 undo 信息。当事务提交时,虽然“脏数据”不会立即写入数据库,但是对数据的操作会写入重做日志文件,只有当写入成功时,才会返回给用户提交成功的代码。因此,只要成功写入重做日志文件,那么也就不用担心数据的修改会丢失了。
事务设计的注意事项:
·减少提交次数:由于数据库在事务提交之前基本上已经完成 99% 的工作,所以提交 1 行 DML 与提交 1000 行 DML 所占用的时间基本上是相同的。
·逻辑单位的安排:事务中具有相关性的一组数据修改应当安排在一个逻辑单位内进行提交,以便在降低风险的同时防止数据完整性出现问题。另外,如果撤销表空间设置过小,也应当合理安排逻辑单位的大小,否则会将撤销表空间用完,并报“ORA-30036: 无法按 XX 扩展段 (在还原表空间 ‘undospace_name’ 中) ”错误。
·选择合适的隔离等级:默认的隔离等级是 Read Committed 。但是如果需要保证数据是事务开始之前已提交的数据,那么可以使用 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 语句显示设置成串行化事务。
来源:http://wanghui471116899.blog.163.com/blog/static/22837153201062210041201/