事务

事务简介

 

一个事务(transaction)开始于用户执行的第一条修改数据的(executableSQL 语句(也可以使用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):

无可用空间 达到最大的数据扩展(maximum extent)限制 超出空间配额(space quota)限制

 

在不可恢复的空间分配模式下,以上条件将导致运行错误,并使 SQL 语句回滚(roll back)。

 

语句被挂起(suspend)将导致其所在事务(transaction)同时被挂起。事务所使用的所有资源在语句挂起期间都将被保留。

 

当产生错误的条件消除后(例如,管理员进行了处理,或其他查询使用的排序空间(sort space)已经被释放),被挂起(suspend)的语句将自动地恢复(resume)执行

 

 

事务管理概述

当一个事务(transaction)开始时,Oracle 为此事务分配一个可用的撤销表空间(undo tablespace)来记录其产生的回滚条目(rollback entry)。

 

一个事务(transaction)在满足以下条件之一时结束:

用户提交了 COMMIT 语句,或不包含 SAVEPOINT 子句的 ROLLBACK 语句。 用户执行了 CREATEDROPRENAME,或 ALTER DDL 语句。如果当前事务中包含 DML 语句,那么 Oracle 首先提交(commit)此事务,然后将 DLL 语句作为一个只包含一条 SQL 语句的新事务运行并提交。 用户断开了与 Oracle 的连接。当前事务将被提交。 用户进程异常结束。则当前事务被回滚(roll back)。

 

提示:

应用程序在退出时应该显示地进行提交(commit)或回滚(roll back)操作

 

 

事务提交

在一个修改了数据的事务(transaction)被提交之前,Oracle进行了以下操作:

Oracle 生成了撤销信息(undo information)。撤销信息包含了事务中各个 SQL 语句所修改的数据的原始值。 Oracle SGA 的重做日志缓冲区(redo log buffer)中生成了重做日志条目(redo log entry)。重做日志记录(redo log record)中包含了对数据块(data block)和回滚块(rollback block)所进行的修改操作。这些记录可能在事务提交之前被写入磁盘。 对数据的修改已经被写入 SGA 中的数据库缓冲区(database buffer)。这些修改可能在事务提交之前被写入磁盘。

·         提示:

已提交事务(committed transaction)中对数据的修改被存储在 SGA 的数据库缓冲区(database buffer)中,她们不一定立即被后台进程 DBWn 写入数据文件(datafile)内。Oracle将选择适当的时机进行写操作以保证系统的效率。因此写操作既可能发生在事务提交之前,也可能在提交之后。

当事务(transaction)被提交之后,Oracle进行以下操作:

撤销表空间(undo tablespace)内部的事务表(transaction table)将记录此次提交(commit),Oracle为此事务分配一个唯一的系统变化编号(system change numberSCN),并将其记录在事务表中。 重做日志写进程(The log writer processLGWR)将 SGA 内重做日志缓冲区(redo log buffer)中的重做日志条目(redo log entry)写入重做日志文件(redo log file)。同时还将此事务的 SCN 也写入重做日志文件。由以上两个操作构成的原子事件(atomic event)标志着一个事务成功地提交。 Oracle 释放加于表或数据行上的锁(lock)。 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博客 ” ,链接:http://blog.itpub.net/25956376/viewspace-710757/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25956376/viewspace-710757/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值