Oracle并发控制、事务管理学习笔记
(a)基本概念 锁的2种最基本、最简单的类型:排他锁(eXclusive lock,即X锁)、共享锁(Share lock,即S锁)。 不同级别的锁定协议及其作用:
申请的锁 及其作用 锁定协议 |
修改时申请X锁 |
读取时申请S锁 |
作用 |
||||
操作 结束 释放 |
事务 结束 释放 |
操作 结束 释放 |
事务 结束 释放 |
不 丢失 修改 |
不 脏读 |
可 重复读 |
|
一级锁定协议 |
是 |
是 |
|||||
二级锁定协议 |
是 |
是 |
是 |
是 |
|||
三级锁定协议 |
是 |
是 |
是 |
是 |
是 |
锁定对象的大小被称为锁定的粒度(granularity)。 如果在一个数据库管理系统中,同时支持多种锁定粒度供事务选择,这种锁定方法就被称为多粒度锁定(multiple granularity locking)。 多粒度锁定协议是指,允许对多粒度树中的节点单独地加锁,另外,对一个节点加锁还意味着对这个节点的各级子节点也加同样的锁。因此,可以用两种方法对多粒度树中的节点加锁:显式锁定、隐式锁定。显式锁定是在事务中明确指定要加在节点上的锁;隐式锁定是由于在其上级节点中加显式锁时而使该节点获得的锁。
具有意向锁的多粒度锁定方法能提高系统的并发度,减少加锁和解锁的开销。 意向锁的含义是,如果对一个节点加某种意向锁,则表示对它的所有下级节点加这种锁的意向;如果对一个节点加某种锁,则必须先对该节点的各级上级节点加这种意向锁。 有如下几种意向锁。 一、IS锁(Intended Share lock,意向共享锁) 二、IX锁(Intended eXclusive lock,意向排他锁) 三、SIX锁(Share Intended eXclusive lock,共享意向排他锁) 如果对一个节点加SIX锁,则表示对它加S锁,然后再加IX锁,即SIX=S+IX。例如,如果事务T对表A加SIX锁,则表示事务T要读取整个表(S锁的作用),同时还会更新某些记录(IX锁的作用)。 包括意向锁的各种锁之间的相容规则:(NL表示没有锁定)
T保持的锁 Ti想获取的锁 | NL | IS |
IX |
S | SIX | X |
IS | 可以 | 可以 | 可以 | 可以 | 可以 | 不可以 |
IX | 可以 | 可以 | 可以 | 不可以 | 不可以 | 不可以 |
S | 可以 | 可以 | 不可以 | 可以 | 不可以 | 不可以 |
SIX | 可以 | 可以 | 不可以 | 不可以 | 不可以 | 不可以 |
X | 可以 | 不可以 | 不可以 | 不可以 | 不可以 | 不可以 |
死锁是一种比较严重的、特殊的锁争用类型。在这种锁争用中,两个或两个以上的用户正在等待对方锁定的资源。因此,如果不进行某种干预,任意一个事务都无法完成。 诊断死锁方法有: *超时法。如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。 *等待图法。这是用离散数学的图论来诊断死锁的方法。事务的等待图是一个有向图G=(T,U)。T为正在运行的各个事务的节点的集合,U为有向边。如果T1 事务等待T2事务,则在T1、T2节点之间就有一条从T1指向T2的有向边。DBMS的并发控制子系统周期性地(如每隔1分钟)检测事务等待图。如果发现图中存在回路,则表示系统中出现了死锁。
(b)DDL锁 Oracle主要有2种锁:DDL锁(字典锁)、DML锁(数据锁)。 DDL锁能防止在用DML语句操作数据库表时,对表进行删除,或对表的结构进行更改。 DDL锁由Oracle自动加锁和释放。不能显式地给对象加DDL锁,即没有加DDL锁的语句。 DDL锁的类型与特征:
类型 | 加锁条件/原因 | 特征 |
共享DDL锁 | 当发布audit、grant、revoke、comment、create procedure、create function、create package等这种DDL语句时 | 1) 不能防止类似的DDL语句或任何DML语句操作对象,但能防止另一个用户改变或删除已引用的对象 2) 在DDL语句执行期间,该DDL锁一直保持,直到发生一个隐式的提交 |
排他DDL锁 | 当发布create table、alter table、drop table、delete from table、truncate table等这种DDL语句时 | 假如一个用户在表上具有锁,不管它是什么级别、什么类型的锁,另一个用户就不能在该表上加排他DDL锁 |
可分解的解析锁 (breakable parse lock) |
SQL共享池里的语句或PL/SQL对象具有一个用于它所引用的每一个对象的锁 | 用来保护SQL共享池里的各个语句或PL/SQL对象。假如被引用的对象改变了,该锁能检查语句是否失效。只要语句还在SQL共享池中,该锁就存在 |
(c)DML锁 根据锁定的粒度和意向,DML锁有几种模式。 RS(Row Share)或SS(Sub Share) RX(Row eXclusive)或SX(Sub eXclusive) S(Share) SRX(Share Row eXclusive)或SSX(Share Sub eXclusive) X(eXclusive) 可以从%ORACLE_HOME%/RDBMS /ADMIN目录中的dbmslock.sql脚本中找到DML锁的模式的相容规则。
==================
-- These are the various lock modes (nl -> "NuLl", ss -> "Sub Shared", -- sx -> "Sub eXclusive", s -> "Shared", ssx -> "Shared Sub eXclusive", -- x -> "eXclusive"). -- -- A sub-share lock can be used on an aggregate object to indicate that -- share locks are being aquired on sub-parts of the object. Similarly, a -- sub-exclusive lock can be used on an aggregate object to indicate -- that exclusive locks are being aquired on sub-parts of the object. A -- share-sub-exclusive lock indicates that the entire aggregate object -- has a share lock, but some of the sub-parts may additionally have -- exclusive locks. -- -- Lock Compatibility Rules: -- When another process holds "held", an attempt to get "get" does -- the following: -- -- held get-> NL SS SX S SSX X -- NL SUCC SUCC SUCC SUCC SUCC SUCC -- SS SUCC SUCC SUCC SUCC SUCC fail -- SX SUCC SUCC SUCC fail fail fail -- S SUCC SUCC fail SUCC fail fail -- SSX SUCC SUCC fail fail fail fail -- X SUCC fail fail fail fail fail
==================
(d)数据库级别锁定 Oracle可以在数据库、表、行这3个级别上使用锁。 锁定数据库有2种方法:将数据库设置成受限方式、将数据库更改成只读方式。 在shutdown数据库后,通过startup restrict命令来在启动数据库时将其设置成受限方式。也可以通过alter system enable restricted session或alter system disable restricted session语句来在打开数据库的情况下启用或禁用数据库的受限方式。当数据库处于受限方式时,只允许具有 restrictive session系统权限的用户(如sys用户)连接到数据库。已经连接的会话不受alter system enable restricted session语句的影响,只有试图进行连接的新的会话会被限制。 将数据库更改成read only(只读)方式后,只能查询数据而不允许对数据进行任何DML操作。 SQL> STARTUP MOUNT SQL> ALTER DATABASE OPEN READ ONLY; 如果要将数据库再按读写方式打开,可以用STARTUP FORCE命令重启数据库。
只读事务 set transaction read only语句可以将事务设置成只读事务,即将数据库"冻结"到该事务开始的那一点上,直至显式地发布了COMMIT或ROLLBACK命令或隐式提交(执行DDL)。在只读事务中所查询到的数据反映的是该事务开始时已经存在的数据库中的数据,即便在此同时其他事务更改并提交了数据库中的数据也是如此,但并不锁定数据库。
在显式提交或者回滚后、或执行ddl后,结束只读事务。 需要注意:因为只读事务的原理是读取undo中数据的前镜像来实现一致性读的,所以,只读事务运行时间不能过长,否则会报0ra-01555。
还有一点,只读事务下是不能对数据做修改的: suk@ORA10G> set transaction read only; suk@ORA10G> delete from test; delete from test * 第 1 行出现错误: ORA-01456: 不能在 READ ONLY 事务处理中执行插入/删除/更新操作
(e)表级锁定和行级锁定 在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。
当发布一个insert、update、 delete、select......for update语句时都会自动在被操作的表上加表级别的锁(即TM类型的锁)。也可以用Lock Table语句专门设置一个表级别的锁。表级别的锁被用于在操作表中数据期间(还没提交或回退事务),防止其他用户对表的结构进行更改。 Lock Table语句的语法是:LOCK TABLE [schema.]table_name IN lock_mode MODE [NOWAIT]; lock_mode表示锁的模式,取值是SHARE、ROW SHARE、ROW EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE;
当发布一个insert、update、 delete、select......for update语句时都会自动在被操作的行上加行级别的锁(即TX类型的锁)。行级别的锁被用于在操作表中数据期间(还没提交或回退事务),防止其他用户对正在操作的行的数据进行更改。
当Oracle 执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。要想获得某个表上的TX锁,事务必须首先获得该表上的TM锁。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可。TM锁包括了SS、SX、S、SSX、X 等多种模式,在数据行上只有X锁(排他锁)。
在Oracle中,查询(不带for update子句的select语句)语句不会锁定数据。即使一个事务已经锁定了几行记录或整个表,查询总是不需要为加锁而等待的。Oracle的查询是通过使用在撤销表空间中所存储的、数据被锁定之前的前映像,来不需要等待地、成功地执行的。这种读取前映像的方法提高了数据的并发度,还保证了事务不会读取到脏数据。 Select...For Update语句所加的锁与update语句所加的锁相同:一个行级别的EXCLUSIVE锁、一个表级别的ROW EXCLUSIVE锁。 Select...for update of column_list, 在多表连接锁定时,可以指定要锁定的是哪几张表,而如果表中的列没有在for update of 后面出现的话,就意味着这张表其实并没有被锁定,其他用户是可以对这些表的数据进行update操作的。这种情况经常会出现在用户对带有连接查询的视图进行操作场景下。用户只锁定相关表的数据,其他用户仍然可以对视图中其他原始表的数据来进行操作。
在Oracle中,锁的数量不受限制且不会自动升级。(有些数据库中,某个表上的行级锁达到一定数量后,这些行级锁就会被升级为该表上的1个表级锁,而取消这些行级锁)
(f)与锁相关的数据字典 V$LOCK视图/DBA_LOCKS视图:所有会话保持或申请的锁的信息 V$LOCKED_OBJECT视图:所有会话锁定的对象以及使用的锁的模式 DBA_WAITERS视图:显示所有被阻塞会话及其申请的锁和阻塞该会话的会话保持的锁的信息 DBA_BLOCKERS视图:显示阻塞了其他会话的那些会话
V$LOCK视图的各个列的说明如下:
列名 数据类型 说明 ADDR RAW(4) 在内存中锁定的对象的地址 KADDR RAW(4) 在内存中锁的地址 SID NUMBER 保持或申请锁的会话的标识号 TYPE VARCHAR2(2) 锁的类型:TX=行锁或事务锁;TM=表锁或DML锁;UL=PL/SQL用户锁 ID1 NUMBER 锁的第1标识号。TM锁,该值表示将要被锁定的对象的标识号;TX锁,该值表示撤销段号码的十进制值 ID2 NUMBER 锁的第2标识号:TM锁,该值为0;TX锁,该值表示交换次数 LMODE NUMBER 会话保持的锁的模式。0=None;1=Null;2=Row-S (SS);3=Row-X (SX); 4=Share;5=S/Row-X (SSX);6=Exclusive REQUEST NUMBER 会话申请的锁的模式。与LMODE中的模式相同 CTIME NUMBER 以秒为单位的,获得当前锁(或转换成当前锁的模式)以来的时间 BLOCK NUMBER 当前锁是否阻塞另一个锁。0=不阻塞;1=阻塞
(g)死锁 当Oracle检测到死锁后,会在跟踪文件中记录下死锁的信息。 Oracle跟踪文件分为三种类型,一种是后台报警日志文件,记录数据库在启动、关闭和运行期间后台进程的活动情况,如表空间创建、回滚段创建、某些alter命令、日志切换、错误消息等。在数据库出现故障时,应首先查看该文件,但文件中的信息与任何错误状态没有必然的联系。后台报警日志文件保存BACKGROUND_DUMP_DEST参数指定的目录中,文件格式为AL alert_SID.log。 另一种类型是DBWR、LGWR、SMON等后台进程创建的后台跟踪文件。后台跟踪文件根据后台进程运行情况产生,后台跟踪文件也保存在BACKGROUND_DUMP_DEST参数指定的目录中,文件格式为siddbwr.trc、sidsmon.trc等。 还有一种类型是由连接到Oracle的用户进程(Server Processes)生成的用户跟踪文件。这些文件仅在用户会话期间遇到错误时产生。 此外,用户可以通过执行oracle跟踪事件(见后面)来生成该类文件,用户跟踪文件保存在USER_DUMP_DEST参数指定的目录中,文件格式为oraxxxxx.trc,xxxxx为创建文件的进程号(或线程号)。 例如:
1 | SQL> SELECT USERENV('SID') FROM DUAL; USERENV('SID') -------------- 120 SQL> CREATE TABLE T1(COL CHAR); Table created. SQL> CREATE TABLE T2(COL CHAR); Table created. SQL> INSERT INTO T1 VALUES('A'); 1 row created. SQL> INSERT INTO T2 VALUES('A'); 1 row created. SQL> COMMIT; Commit complete. | SQL> SELECT USERENV('SID') FROM DUAL; USERENV('SID') -------------- 126 |
2 | SQL> UPDATE T1 SET COL='B' WHERE COL='A'; 1 row updated. | |
3 | SQL> UPDATE T2 SET COL='B' WHERE COL='A'; 1 row updated. | |
4 | SQL> UPDATE T1 SET COL='B' WHERE COL='A'; | |
5 | SQL> UPDATE T2 SET COL='B' WHERE COL='A'; | |
6 | UPDATE T1 SET COL='B' WHERE COL='A' * ERROR at line 1: ORA-00060: deadlock detected while waiting for resource SQL> |
用sys账户登陆, SQL> SHOW PARAMETER BACKGROUND_DUMP_DEST; NAME TYPE VALUE ------------------------------------------------------- background_dump_dest string e:/app/ww/diag/rdbms/mytest/mytest/trace 打开E:/app/ww/diag/rdbms/mytest/mytest/trace/alert_mytest.log,最后面有如下记录: Thu May 19 09:41:00 2011 ORA-00060: Deadlock detected. More info in file e:/app/ww/diag/rdbms/mytest/mytest/trace/mytest_ora_684.trc. 打开mytest_ora_684.trc可以看到详细死锁信息
(f) 检测锁争用 上面例子,第6步中oracle检测到死锁并产生ORA-00060错误放弃了会话126的第4步update操作后,会话120的第5步的表T2更新操作依然需要等待会话126的第3步的表T2更新操作提交或者回滚。可以用如下的SQL语句来查询阻塞的会话。
- COLUMN BLOCKERS FORMAT A20;
- COLUMN WAITERS FORMAT A50;
- SELECT SB.SID||':'||SB.SERIAL#||' '||SB.USERNAME BLOCKERS,
- SW.SID||':'||SW.SERIAL#||' '||SW.USERNAME||' '||SQLW.SQL_TEXT WAITERS
- FROM V$LOCK LB, V$LOCK LW, V$SESSION SB, V$SESSION SW, V$SQLAREA SQLW
- WHERE LB.ID1=LW.ID1
- AND LB.BLOCK=1
- AND LW.BLOCK=0
- AND LB.SID=SB.SID
- AND LW.SID=SW.SID
- AND SW.SQL_ID=SQLW.SQL_ID;
- BLOCKERS WAITERS
- -------------------- --------------------------------------------------
- 170:6 HR 155:14 HR UPDATE T2 SET COL='B' WHERE COL='A'
- SQL>
COLUMN BLOCKERS FORMAT A20; COLUMN WAITERS FORMAT A50; SELECT SB.SID||':'||SB.SERIAL#||' '||SB.USERNAME BLOCKERS, SW.SID||':'||SW.SERIAL#||' '||SW.USERNAME||' '||SQLW.SQL_TEXT WAITERS FROM V$LOCK LB, V$LOCK LW, V$SESSION SB, V$SESSION SW, V$SQLAREA SQLW WHERE LB.ID1=LW.ID1 AND LB.BLOCK=1 AND LW.BLOCK=0 AND LB.SID=SB.SID AND LW.SID=SW.SID AND SW.SQL_ID=SQLW.SQL_ID; BLOCKERS WAITERS -------------------- -------------------------------------------------- 170:6 HR 155:14 HR UPDATE T2 SET COL='B' WHERE COL='A' SQL>
当出现检测到锁争用的信息后,用户自己(执行commit语句或rollback语句,使事务结束,释放所加的锁。还可以使用 ALTER SYSTEM KILL SESSION 'sid, serial#' 语句来杀死会话,强行解决锁争用。
(g) Oracle中的事务和SQLServer中的事务的差异
原文:http://www.examda.com/oracle/zonghe/20101008/103744390.html
事务处理是所有大型数据库产品的一个关键问题,各数据库厂商都在这个方面花费了很大精力,不同的事务处理方式会导致数据库性能和功能上的巨大差异。
事务处理也是数据库管理员与数据库应用程序开发人员必须深刻理解的一个问题,对这个问题的疏忽可能会导致应用程序逻辑错误以及效率低下。
下面我们针对Oracle及SQL Server这 两种当前广泛使用的大型数据库产品,探讨一下它们在事务处理方面的一些差异。如没有特殊说明,本文内容适用的数据库产品版本为Oracle9i及SQL Server 2000,其中的示例SQL语句,对于Oracle是在SQL*Plus中执行,而对于SQL Server 2000是在osql中执行。
一.事务的概念
事务可以看作是由对数据库的若干操作组成的一个单元,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求。事务的一个典型例子是银 行中的转帐操作,帐户A把一定数量的款项转到帐户B上,这个操作包括两个步骤,一个是从帐户A上把存款减去一定数量,二是在帐户B上把存款加上相同的数 量。这两个步骤显然要么都完成,要么都取消,否则银行就会受损失。显然,这个转帐操作中的两个步骤就构成一个事务。
数据库中的事务还有如下ACID特征。
ACID分别是四个英文单词的首写字母,这四个英文单词是Atomicity、Consistency、Isolation、Durability,分别翻译为原子性、一致性、隔离性、持久性。
原子性:指事务中的操作,或者都完成,或者都取消。
一致性:指事务中的操作保证数据库中的数据不会出现逻辑上不一致的情况,一致性一般会隐含的包括在其他属性之中。
隔离性:指当前的事务与其他未完成的事务是隔离的。在不同的隔离级别下,事务的读取操作,可以得到的结果是不同的。
持久性:指对事务发出COMMIT命令后,即使这时发生系统故障,事务的效果也被持久化了。与此相反的是,当在事务执行过程中,系统发生故障,则事务的操作都被回滚,即数据库回到事务开始之前的状态。
对数据库中的数据修改都是在内存中完成的,这些修改的结果可能已经写到硬盘也可能没有写到硬盘,如果在操作过程中,发生断电或系统错误等故障, 数据库可以保证未结束的事务对数据库的数据修改结果即使已经写入磁盘,在下次数据库启动后也会被全部撤销;而对于结束的事务,即使其修改的结果还未写入磁 盘,在数据库下次启动后会通过事务日志中的记录进行“重做”,即把丢失的数据修改结果重新生成,并写入磁盘,从而保证结束事务对数据修改的永久化。这样也 保证了事务中的操作要么全部完成,要么全部撤销。
二.事务设置及类型的区别
在SQL Server中有三种事务类型,分别是:隐式事务、显式事务、自动提交事务,缺省为自动提交。
自动提交,是指对于用户发出的每条SQL语句,SQL Server都会自动开始一个事务,并且在执行后自动进行提交操作来完成这个事务,也可以说在这种事务模式下,一个SQL语句就是一个事务。
显式事务,是指在自动提交模式下以Begin Transaction开始一个事务,以Commit或Rollback结束一个事务,以Commit结束事务是把事务中的修改永久化,即使这时发生断电这样的故障。例如下面是SQL Server中的一个显式事务的例子。
Begin TranUpdate emp Set ename=’Smith’ Where empno=7369
Insert Into dept Values(60,’HR’,’GZh’)Commit
隐式事务,是指在当前会话中用Set Implicit_Transactions On命令设置的事务类型,这时任何DML语句(Delete、Update、Insert)都会开始一个事务,而事务的结束也是用Commit或Rollback。
在Oracle中没有SQL Server的这些事务类型,缺省情况下任何一个DML语句都会开始一个事务,直到用户发出Commit或Rollback操作,这个事务才会结束,这与SQL Server的隐式事务模式相似。
三.事务隔离级别
在SQL92标准中,事务隔离级别分为四种,分别为:Read Uncommitted、Read Committed、Read Repeatable、Serializable,其中Read Uncommitted与Read Committed为语句级别的,而Read Repeatable与Serializable是针对事务级别的。
在Oracle和SQL Server中设置事务隔离级别的语句是相同的,都使用SQL92标准语法,即:
Set Transaction Isolation Level Read Committed
上面示例中的Read Committed可以被替换为其他三种隔离级别中的任意一种。
1.SQL Server中的隔离级别及实现机制
在SQL Server中提供了所有这四种隔离级别。
下面我们讨论在SQL Server中,这几种隔离级别的含义及其实现方式。
Read Uncommitted:一个会话可以读取其他事务未提交的更新结果,如果这个事务最后以回滚结束,这时的读取结果就可能是错误的,所以多数的数据库应用都不会使用这种隔离级别。
Read Committed:这是SQL Server的缺省隔离级别,设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则,发生等待,但是其他会话可以修改这个事务中被读取的记 录,而不必等待事务结束,显然,在这种隔离级别下,一个事务中的两个相同的读取操作,其结果可能不同。
Read Repeatable:在一个事务中,如果在两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数增多,则两次 读取结果相同。换句话说,就是在一个事务中第一次读取的记录保证不会在这个事务期间发生改变。SQL Server是通过在整个事务期间给读取的记录加锁实现这种隔离级别的,这样,在这个事务结束前,其他会话不能修改事务中读取的记录,而只能等待事务结 束,但是SQL Server不会阻碍其他会话向表中添加记录,也不阻碍其他会话修改其他记录。
Serializable:在一个事务中,读取操作的结果是在这个事务开始之前其他事务就已经提交的记录,SQL Server通过在整个事务期间给表加锁实现这种隔离级别。在这种隔离级别下,对这个表的所有DML操作都是不允许的,即要等待事务结束,这样就保证了在 一个事务中的两次读取操作的结果肯定是相同的。
2.Oracle中的隔离级别及实现机制
在Oracle中,没有Read Uncommitted及Repeatable Read隔离级别,这样在Oracle中不允许一个会话读取其他事务未提交的数据修改结果,从而避免了由于事务回滚发生的读取错误。Oracle中的 Read Committed和Serializable级别,其含义与SQL Server类似,但是实现方式却大不一样。
在Oracle中,存在所谓的回滚段(Oracle9i之前版本)或撤销段(Oracle9i版本),Oracle在修改数据记录时,会把这些 记录被修改之前的结果存入回滚段或撤销段中,就是因为这种机制,Oracle对于事务隔离级别的实现与SQL Server截然不同。在Oracle中,读取操作不会阻碍更新操作,更新操作也不会阻碍读取操作,这样在Oracle中的各种隔离级别下,读取操作都不 会等待更新事务结束,更新操作也不会因为另一个事务中的读取操作而发生等待,这也是Oracle事务处理的一个优势所在。
Oracle缺省的设置是Read Committed隔离级别(也称为语句级别的隔离),在这种隔离级别下,如果一个事务正在对某个表进行DML操作,而这时另外一个会话对这个表的记录进 行读取操作,则Oracle会去读取回滚段或撤销段中存放的更新之前的记录,而不会象SQL Server一样等待更新事务的结束。
在Serializable隔离级别(也称为事务级别的隔离),事务中的读取操作只能读取这个事务开始之前已经提交的数据结果。如果在读取时, 其他事务正在对记录进行修改,则Oracle就会在回滚段或撤销段中去寻找对应的原来未经更改的记录(而且是在读取操作所在的事务开始之前存放于回滚段或 撤销段的记录),这时读取操作也不会因为相应记录被更新而等待。
四.DDL语句对事务的影响
1.Oracle中DDL语句对事务的影响
在Oracle中,执行DDL语句(如Create Table、Create View等)时,会在执行之前自动发出一个Commit命令,并在随后发出一个Commit或者Rollback命令,也就是说,DDL会象如下伪码一样执行:
Commit;DDL_Statement;
If (Error) then
Rollback;
Else
Commit;End if;
我们通过分析下面例子来看Oracle中,DDL语句对事务的影响:
Insert into some_table values(‘Before’);Creaate table T(x int);
Insert into some_table values(‘After’);Rollback;
由于在Oracle执行Create table语句之前进行了提交,而在Create table执行后也会自动发出Commit命令,所以只有插入After的行被回滚,而插入Before的行不会被回滚,Create table命令的结果也不会被回滚,即使Create table语句失败,所进行的Before插入也会被提交。如果最后发出Commit命令,因为插入Before及Create table的操作结果已经在之前提交,所以Commit命令影响的只有插入After的操作。
2.SQL Server中DDL语句对事务的影响
在SQL Server中,DDL语句对事务的影响与其他DML语句相同,也就是说,在DML语句发出之前或之后,都不会自动发出Commit命令。
在SQL Server 2000中,对于与上面Oracle同样的例子,最后发出Rollback后,数据库会回滚到插入Before之前的状态,即插入Before和After的行都会被回滚,数据表T也不会被创建。
如果最后发出Commit操作,则会把三个操作的结果全部提交。
五.用户断开数据库连接对事务的影响
另外,对应于Oracle的管理客户端工具SQL*Plus,在SQL Server 2000中是osql,两种管理工具都是命令行工具,使用方式及作用也类似,但是在SQL*Plus中,用户退出连接时,会自动先发出Commit命令, 然后再退出,而在osql中,如果用户退出连接,会自动发出Rollback命令,这对于SQL Server的自动提交模式没有什么影响,但如果处于隐式事务模式,其影响是显而易见的。对于两种数据库产品的其他客户端管理工具也有类似的不同之处。
posted on 2013-10-27 15:46 heartstage 阅读(517) 评论(1) 编辑 收藏 举报