事务简介
一个事务(transaction)开始于用户执行的第一条修改数据的(executable)SQL 语句(也可以使用SET TRANSACTION 或DBMS_TRANSACTION 包来显示地开
始一个事务),结束于之后进行的提交(commit)或回滚(roll back)操作。使用 COMMIT 或 ROLLBACK 语句能够显式地结束事务,而提交一个 DDL 语句可以隐式地结束事务。
注:一定要显式地使用COMMIT 或ROLLBACK 来终止你的事务;否则,你使用的工具/环境就会从中挑一个来结束事务。如果正常地退出SQL*Plus 会话,而没有提交或回滚事务,SQL*Plus 就会认为你希望提交前面做的工作,并为你完成提交。另一方面,如果你只是退出一个Pro*C 程序,就会发生一个隐式的回滚。
SET TRANSACTION:这条语句允许你设置不同的事务属性,如事务的隔离级别以及事务是只
读的还是可读写的。使用手动undo 管理时,还可以使用这个 来指示事务使用某个特定的undo段,不过不推荐这种做法。
语句级回滚
如果在一个 SQL 语句在执行过程中发生了错误,那么此语句对数据库产生的影响将被回滚(roll back)。回滚后就如同此语句从未执行过。这种操作被称为语句级回滚(statement-level rollback)。例如向一个表中插入数据造成主键(primary key)值重复即为此类错误. 一个 SQL 语句执行失败只会使此语句所做的数据修改无效,而不会导致当前事务(transaction)中此语句之前的语句所做的数据修改失效
可恢复的空间分配问题
当一个持续时间较长的数据库操作在执行过程中遭遇空间分配失败时,Oracle 可以将此操作暂时挂起(suspend),并在空间分配问题解决后恢复(resume)其执行。当发生空间分配问题时,Oracle 数据库服务器不会立即给执行此操作的用户返回错误提示,而是等待管理员解决此问题。当空间分配问题被纠正后,挂起的操作可以自动地恢复执行
只有在客户端使用 ALTER SESSION 语句的语法显式地将会话(session)设定为可恢复( resumable)后,SQL 语句才能运行在可恢复模式下(resumable mode)。
当满足以下条件之一时,运行于可恢复的空间分配模式下的语句将被挂起(suspend):
在不可恢复的空间分配模式下,以上条件将导致运行错误,并使 SQL 语句回滚(roll back)。
语句被挂起(suspend)将导致其所在事务(transaction)同时被挂起。事务所使用的所有资源在语句挂起期间都将被保留。
当产生错误的条件消除后(例如,管理员进行了处理,或其他查询使用的排序空间(sort space)已经被释放),被挂起(suspend)的语句将自动地恢复(resume)执行
事务管理概述
当一个事务(transaction)开始时,Oracle 为此事务分配一个可用的撤销表空间(undo tablespace)来记录其产生的回滚条目(rollback entry)。
一个事务(transaction)在满足以下条件之一时结束:
提示:
应用程序在退出时应该显示地进行提交(commit)或回滚(roll back)操作
事务提交
在一个修改了数据的事务(transaction)被提交之前,Oracle进行了以下操作:
·
提示:
已提交事务(committed
transaction)中对数据的修改被存储在 SGA 的数据库缓冲区(database buffer)中,她们不一定立即被后台进程 DBWn 写入数据文件(datafile)内。Oracle将选择适当的时机进行写操作以保证系统的效率。因此写操作既可能发生在事务提交之前,也可能在提交之后。
当事务(transaction)被提交之后,Oracle进行以下操作:
事务回滚
回滚(rolling back)的含义是撤销一个未提交事务(uncommitted transaction)中已执行的 SQL 语句对数据的修改。Oracle使用撤销表空间(undo tablespace)(或回滚段(rollback segment))来存储被修改的数据的原始值。而重做日志(redo log)内则保存了对数据修改操作的记录。
用户可以回滚(roll back)整个未提交事务(uncommitted transaction)。除此之外,用户还可以部分回滚未提交事务,即从事务的最末端回滚到事务中任意一个被称为保存点(savepoint)的标记处
事务中的保存点
用户在事务(transaction)内可以声明(declare)被称为保存点(savepoint)的标记。保存点将一个大事务划分为较小的片断。
被部分回滚的事务(transaction)依然处于活动状态,可以继续执行。
一个事务(transaction)在等待其他事务的过程中,进行回滚(roll back)到某个保存点(savepoint)的操作不会释放行级锁(row lock)。为了避免事务因为不能获得锁而被挂起,应在执行 UPDATE 或 DELETE 操作前使用 FOR UPDATE ... NOWAIT 语句。(以上内容讲述的是回滚保存点之前所获得的锁。而在保存点之后获得的行级锁是会被释放的,同时保存点之后执行的 SQL 语句也会被完全回滚)。(for update ….nowait:)
完整性约束和事务
默认情况下,完整性约束会在整个SQL 语句得到处理之后才进行检查。也有一些可延迟的约束允许将完整性约束的验证延迟到应用请求时(发出一个SET CONSTRAINTS ALL IMMEDIATE 命令)才完成,或者延迟到发出COMMIT 时再检查。
注意,这里我用的是“SQL 语句”而不只是“语句”。如果一个PL/SQL 存储过程中有多条SQL 语句,那么在每条SQL 语句执行之后都会立即验证其完整性约束,而不是在这个存储过程完成后才检查它。
那么,为什么约束要在SQL 语句执行之后才验证呢?为什么不是在SQL 语句执行期间验证?这是因为,一条语句可能会使表中的各行暂时地“不一致”,这是很自然的。尽管一条语句全部完成后的最终结果是对的,但如果查看这条语句所做的部分工作,会导致Oracle 拒绝这个结果。例如,假设有下面这样一个表:
ops$tkyte@ORA10G> create table t ( x int unique );
Table created.
ops$tkyte@ORA10G> insert into t values ( 1 );
1 row created.
ops$tkyte@ORA10G> insert into t values ( 2 );
1 row created.
现在,我们想执行一个多行UPDATE:
ops$tkyte@ORA10G> update t set x = x+1;
2 rows updated.
如果Oracle 每更新一行之后都检查约束,那么无论什么时候,UPDATE 都有一半的可能性(50%的
机会)会失败。由于会以某种顺序来访问T 中的行,如果Oracle 先更新X=1 这一行,那么X 就会临时地
有一个重复的值,这就会拒绝UPDATE。由于Oracle 会耐心等待语句结束(而不是在语句执行期间检查约束),所以这条语句最后会成功,因为等到语句完成时已经不存在重复值了。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25956376/viewspace-710757/ ,如需转载,请注明出处,否则将追究法律责任。