11gr2 oracle concepts(翻译) --第10章 事务

来源:互联网 发布:ubuntu什么系统 编辑:程序博客网 时间:2024/06/16 13:31

本章包括以下内容

事务简介

事务控制

自治事务

分布式事务

1.1  事务简介

事务是一个逻辑和原子的工作单元,它包含一条或者更多sql语句。事务是sql语句的组合,它们要么全部提交,要么全部回滚。oracle数据库分别每个事务一个唯一的标示符,叫做事务ID。所有的oracle事务都具有数据库事务的相关属性,及ACID属性,ACID的意思如下

·          原子性

事务中的所有工作要么全部执行,要不全不执行。没有部分事务。例如,一个事务开始更新100行,但是更新到20行失败了,数据库将回滚这20行

·          一致性

事务从数据库的一个一致性状态到另一个一致性状态

·          隔离性

在事务提交之前,事务内对数据的改变对其它事务是不可见的。例如,一个用户修改了hr.employees表,在没有提交之前,其它用户是看不到这些修改的。因此,看起来就像事务被序列化(串行)执行一样

·          持久性

事务的改变在提交之后具有永久性,在一个事物结束后,数据库应具有恢复机制,确保提交的事务不会丢失

使用事务是数据库管理系统和文件系统的一个最重要的区别之一

1.1.1事务的结构

一个事务由一个或者多个语句组成,准确的说,一个事务由如下内容构成

·          一个或者多个DML语句,这些语句构成了对数据库的原子改变

·          一个DDL语句

事务有一个开始,一个结束

1.1.1.1   事务的开始

当第一个开始运行时,一个事务就开始了。一个可执行的sql语句会产生一个对数据库实例的调用,包括DML、DDL和SET TRANSACTION语句。当一个事务开始时,oracle数据库分配事务一个可用的undo数据段(segemnt),用来为新事务记录undo实体。事务ID在undo段和事务表slot分配之后才分配,事务表slot的分配在第一个DML语句时完成。事务ID对一个事务来说,是唯一的,代表着undo段号,slot和序列号。

下面的例子执行一个update操作来执行一个事务,接着查询V$transaction来查看事务的详细信息

SQL> UPDATE hr.employees SET salary=salary;

107 rows updated.

 SQL> SELECT XID AS "txn id", XIDUSN AS "undo seg", XIDSLOT AS "slot",

  2  XIDSQN AS "seq", STATUS AS "txn status"

  3  FROM V$TRANSACTION;

 txn id             undo seg       slot        seq txn status

---------------- ---------- ---------- ---------- ----------------

0600060037000000          6          6         55 ACTIVE

1.1.1.2   事务的结束

事务在以下任意情况下都会结束:

·          用户使用COMMIT或者ROLLBACK (不加SAVEPOINT参数)。通过提交,用户隐式或者显式的把事务内的修改持久化。事务的修改持久化并且只有在事务提交之后对其它用户才是可见的。

·          用户运行一个DDL命令,例如CREATE,DROP,RENAME和ALTER,在每一个DDL语句的前后,都会隐式提交事务。如果当前事务包含DML语句,那么oracle首先提交事务,并且把当前DDL作为一个新的单一的事务进行提交

·          在大部分工具中,用户正常退出,都会隐式提交相关事务。用户退出时的提交行为和具体的应用有关,是可配置的

注意:在程序结束之前,应用程序应该总是显式提交或者取消事务

·          客户端异常结束,将导致事务通过事务表和undo段中的数据进行隐式回滚

当一个事务结束时,下一个可执行的sql将开始另一个新事物。下面的例子执行了一个update语句,开始了一个新事物,通过ROLLBACK命令结束了这个事务。接着,又通过一个    update开始了一个新的事务(注意,事务ID是不同的)

SQL> UPDATE hr.employees SET salary=salary;

107 rows updated.

 SQL> SELECT XID, STATUS FROM V$TRANSACTION;

 XID              STATUS

---------------- ----------------

0800090033000000 ACTIVE

 SQL> ROLLBACK;

 Rollback complete.

 SQL> SELECT XID FROM V$TRANSACTION;

 no rows selected

 SQL> UPDATE hr.employees SET last_name=last_name;

 107 rows updated.

 SQL> SELECT XID, STATUS FROM V$TRANSACTION;

 XID              STATUS

---------------- ----------------

0900050033000000 ACTIVE

 

1.1.2语句级别的原子性

数据库执行语句级别的原子性,这意味着一个sql语句是一个原子的工作单元,一个语句要么全部成功完成,要么完全失败。一个成功的语句和一个提交的事务是不同的。一个单一sql执行成功,如果数据库解析和运行作为一个整体单元没有错误,如果是多行更新,所有的行都被修改了。

如果一个sql在执行过程中报错,那么它是执行不成果,所有这条语句的照成的影响都将回滚。这个操作叫做语句级别的回滚。这个操作具有如下特性:

·          sql语句执行失败,只会造成语句失败之前的工作的丢失,sql语句执行失败,不会影响事务中之前成功执行的sql。例如

·          rollback的影响,就像语句从来没从来没发生过

任何原子语句造成的影响,例如语句引发的触发器,也被作为原子语句的一部分,要么全部成功,要么全被回滚。语句级别的错误导致的回滚的一个例子是:试图插入重复的主键。对统一数据的争用,导致死锁,也可以导致语句级别的回滚。然而,语句解析期间由于语法等导致的解析错误,由于语句还没有开始运行,不会导致语句级别的回滚。

1.1.3系统改变号(SCNs)

system changenumber (SCN) 是oracle数据库逻辑的,内部的时间戳。SCNs能够用来记录数据库内发生的事件的顺序,SCNs是实现数据库ACID属性的必要条件。oracle使用SCN用来记录所有的改变都已经写入磁盘的时间点,这用来避免带来不必要的redo。数据库也使用SCNs记录没有redo存在的时间点,在这个时间点,恢复工作需要停止

SCNs是一个单调增长的序列。oracle把SCN当作类似钟表的用途,SCN是一个逻辑的时间点,重复获取会返回相等或者更大的数值。如果一个时间的SCN比另一个SCn低,说明时间发生的时间更早。一个时间可能共享相同的SCN,意味着在数据库看来,这些事件是同时发生的。

每个事务都有一个SCN,例如,一个事务更新了一行,数据库在更新发生时,会记录事务的SCN,事务内的其它修改具有同一个SCN,当事务提交时,数据库会为此次提交记录SCN。

oracle在SGA中增长SCNs。当事务修改一个数据时,数据库会向undo块中写入新的事务SCN。LGWR进程向在线日志文件写入事务相关提交记录。提交记录中有唯一的事务SCN。oracle也使用SCNs用于实例恢复和介质恢复介质

1.2  事务控制

事务控制管理事务内的DML语句的数据改变,并组合事务内的DML语句。一般来说,应用程序的设计者比较关心事务控制,用来保证相关工作是一个逻辑单元,数据能保持一致性

事务控制包括下面的语句

·          COMMIT语句结束事务,并使事务的改变持久化。COMMIT也会擦除事务内的所有savepoint点,并释放事务相关的锁定

·          ROLLBACK语句取消当前事务已经完成的工作。导致丢弃了所有上次提交或者回滚后的所有数据改变。    ROLLBACK TO SAVEPOINT 取消所有上一个savepoint点的所有数据改变,不会结束整个事务。

·          SAVEPOINT记录事务中的一个时间点,用于后面可能的回滚

1.2.1事务名

事务名是可选的,用户用来记录事务的标识符。你可以使用SET TRANSACTION .. NAME语句定义,这个语句必须是事务的第一条语句。

事务名能有如下好处:

·          可以用来轻松监控长时间运行的事务,也可用于有问题的分布式事务

·          可以和事务ID一起用于程序中查看事务。例如,管理员可以通过事务名,在OEM中监控系统活动

·          通过事务名,可在视图V$TRANSACTION中找到特定的事务

1.2.2活动事务

活动事务时已经开始,当没有提交或者回滚的事务。事务在提交或者回滚前,所有的数据改变都是临时的。在事务结束前,数据的状态如下

·          oracle已经在SGA区生成了undo数据,undo中保存着事务中sql语句修改前的旧数据

·          oracle在SGA中log buffer中生成了redo。redo中记录了数据块的改变和undo块的改变

·          SGA数据库缓冲区中数据的改变。已经提交的事务修改的数据,存储在sga中的数据缓冲区中,并不是立刻被DBWR进程写入磁盘中的数据文件。写磁盘的操作可能在提交之前或者之后发生

·          修改的数据行被锁定。其它用户不能修改相关的数据行,也看不到未提交的数据修改

1.2.3保存点

保存点savepoint,事务内部的记录点。它和SCN关联,把一个长事务分成多个小部分。如果你在长事务中使用savepoint,可以在后面的时间点回滚到该savepoint。因此当你出错,你没必要回滚整个事务,只是到某个savepoint就可以了

回滚到保存点

为提交事务回滚到某个保存点,意味着保存点后的所有修改都会取消。而不是取消整个事务。事务仍旧是活动的,可以继续执行。

事务等待

如例子所述,如果事务等待某些资源,在资源持有的事务回滚到某个保存点后,可能仍会等待资源。

1.2.4事务回滚

未提交的事务的回滚将会取消事务内的sql语句的所有的数据修改,事务回滚之后,事务的所有影响将不再存在。

如果不是回滚到某个保存点,而是整个事务回滚,oracle数据库将做如下操作

·          使用undo段,取消事务内的所有操作:每个活动事务在事务表中都有一个活动条目,条目指向undo数据(和应用程序的操作相反)。数据库从undo段里读取相关数据,反向执行相关操作,接着标记undo条目被应用了。因此,如果一个事务插入了一行,那么回滚操作删除这一行。如果一个事务更新了一行,那么回滚反向取消这个更新。如果一个事务删除了一行,回滚插入一行。

·          释放事务持有的所有锁

·          擦除事务内的所有保存点

·          结束事务

回滚的时长是数据修改的函数,也就是说修改的数据越多,回滚的工作量越大,时间越长

1.2.5事务提交

提交结束当前的事务,使事务中的所有改变持久化。事务提交时,发生如下动作:

·          为提交生成一个SCN,和undo表空间关联的内部事务表记录提交的事务,相关的唯一的事务SCN关联并记录在事务表中

·          LGWR进程把redo buffer中的剩余的redo记录写入日志文件,并把事务SCN也写入,这些原子时间构成了事务的提交操作

·          释放锁定的相关行和表:等待相关所有的锁的用户,可以继续执行他们的工作

·          删除保存点savepoint

·          实施提交清除:如果事务修改的数据块仍然缓存在SGA中,如果没有其它事务修改这些数据块,那么数据库将从数据块移除锁相关的事务信息。理想情况下,提交清除数据块,接下来的select操作就不需要执行这些操作了。

注意:块清除操作会生成redo,查询操作会生成redo,会导致数据库在下一个检查的checkpoint写数据块操作

·          oracle标记事务结束

事务提交后,其它用户可以看到这些修改

一般说来,提交操作很快,和事务的大小关系不大。事务的提交时间不随着事务修改数据的增长而增长。提交中最耗时的部分是LGWR进程写IO操作,然而,由于LGWR增量的写入redo buffer中的内容到磁盘中,提交时写操作的时间大大减少了。

在返回提交成功之前,事务会等待LGWR进程同步写redo信息到磁盘中。为了减少事务提交的延迟,应用开发者可以异步写入日志,事务不必等待redo写入磁盘完成,而是立即返回提交结果

1.3  自主事务

自主事务是一个独立的事务,可以被其它事务调用,也叫做主事务。你可以在自治事务内挂起调用的事务,执行sql操作,提交或者回滚它们,接着执行调用的事务。自治事务通常用在需要独立执行的场景下,而不管调用的事务是否成功提交。例如股票交易事务中,你想提交用户数据,而不管股票交易情况,另外,你想记录相关错误信息,而不管事务是否回滚。

自治事务具有如下特点:

·          自治事务看不到主事务未提交的修改,和主事务之间不共享锁和其它资源

·          自治事务的修改在提交后才是可见的,因此,用户之后在主事务提交之后才能查到更新的数据

·          自治事务可以开始其它自治事务,不限制自治事务被调用的等级和数量

在PL/SQL中,自治事务在在AUTONOMOUS_TRANSACTION定义的范围内执行,在这个上下文中,可以是顶级匿名PL/SQL块,和PL/SQL子程序和触发器。

1.4  分布式事务

分布式数据库是一个分布式系统,应用程序看来,是一个数据源。分布式事务是使用database link,在一个或者多个分布式数据库中更新数据。数据库连接描述了一个数据库实例如何连接另一个连接。

不象本地的数据库事务,分布式事务在多个数据库中修改数据,、。分布式事务比较复杂,需要在多个数据库协调管理提交和回滚操作。即使网络和系统出了问题,数据库也的保证数据一致性。

1.4.1两阶段提交

两阶段提交确保分布式事务中的所有数据库要不全部提交,要么全部回滚。这个机制已能保护隐式的DML操作的一致性约束,远程过程调用和触发器。

多个数据库中的两阶段提交,一个数据库协调管理整个分布式事务。初始节点叫做全局协调者。协调者问其它数据库是否准备提交,如果任何一个回答否,整个事务会回滚。如果都说是,协调者发布消息,使所有的数据都提交。

两阶段提交机制对用户是透明的,实际上,用户不关系或者不需要知道事务是否是分布式的。事务的提交操作自动触发两阶段提交机制,在应用程序内使用两阶段提交不需要而外的语法等

1.4.2不确定的事务

当两阶段提交的事务发生系统和网络问题是,会产生不确定事务。例如两个数据库报告协调数据库他们准备提交事务,协调数据库在收到相关消息后,实例出现问题了。这两个数据库将hang,并等待相关通知。

RECO后台进程自动的处理不确定的事务,问题修复或者网络重新建立后,RECO进程自动的提交或者回滚不确定的事务,确保不同的节点处于一致性状态。

如果问题持续很长时间,oracle数据库运行本地管理员手工提交或者取消处于不确定状态的分布式事务。这个选项使本地数据库管理员释放相关锁资源等。如果数据库必须要恢复到过去的某个时间点,数据库恢复功能能使远端的数据库管理员返回数据库到过去的某个时间点。这个操作确保全局数据库处于一致性状态。

 

参考文档:

http://docs.oracle.com/cd/E11882_01/server.112/e40540/transact.htm#i6564

原创粉丝点击