OCA/OCP认证考试指南全册(第3版) Oracle Database 12c(1Z0-061,1Z0-062,1Z0-063) (计算机与信息)
上QQ阅读APP看书,第一时间看更新

6.3 DML和撤消数据的生成

撤消数据是反转DML语句结果所需的信息。撤消数据通常被称为“回滚数据”,不过最好不要使用这种称呼。在过去的Oracle版本中,术语“回滚数据”与“撤消数据”可以交替使用,但是从9i版本开始,这两个术语就有所不同:它们的功能相同,但管理方式不同。回滚段的旧机制已过时很久了,所有数据库应使用自动撤消管理,它使用撤消段来存储撤消数据。

回滚某个事务意味着使用撤消段中的数据来构造一个与事务发生前相同的数据映像。为了满足ACID测试的要求,回滚通常是自动完成的,但是,通过给出查询过去某一时刻数据库的选项,闪回查询性能利用了撤消机制的功能。当然,任何用户都可以交互地使用ROLLBACK命令回滚已经执行但尚未提交的任何DML语句。

ACID测试提出了如下要求:首先,不论是在发生错误时自动进行回滚还是根据需要使用ROLLBACK命令进行回滚,Oracle都应当为反转未结束的事务而保留原有数据。这种回滚是持久的,并且对所有用户公开。其次,针对一致性要求,Oracle数据库必须能够提供一个查询,这个查询的结果与该查询开始时的数据库保持一致。此时,如果待查询数据块在该查询开始后发生了变化,那么运行这个查询的服务器进程会进入撤消段并构造这些数据块的“读一致”映像。这种回滚是临时的,并且只对于运行这个查询的会话是可视的。第三,撤消段也用于事务的隔离性,这可能是撤消数据最复杂的用法。隔离性原则要求任何事务都不能以某种方式依赖于其他未结束的事务。事实上,即使某个多用户数据库具有许多同时进行的事务,最终结果也必须像依次执行这些事务一样。使用撤消数据以及记录与表锁定能够保证事务的隔离性,也就是说不可能存在不兼容的事务。即使并发运行若干事务,隔离性也会要求最终结果必须像连续执行这些事务一样。

考点:

撤消段的使用与回滚段的使用相矛盾:根据UNDO_MANAGEMENT参数的不同设置,Oracle数据库要么使用撤消段,要么使用回滚段。

练习6-5 监控和管理撤消数据

本练习将研究数据库中的撤消配置和使用。可以使用SQL*Plus或SQL Developer。

(1) 以用户SYSTEM的身份连接到数据库。

(2) 使用如下查询,确定数据库正在使用撤消段还是回滚段:

        select value from v$parameter where name='undo_management';

这将返回值AUTO。否则,请发出此命令,然后重新启动实例:

        alter system set undo_management=auto scope =spfile

(3) 使用下面两个查询,确定已经创建的撤消表空间,以及正在使用哪一个:

        select tablespace_name from dba_tablespaces where contents='UNDO';
        select value from v$parameter where name='undo_tablespace';

(4) 确定数据库中使用的撤消段及其大小:

        select tablespace_name, segment_name, segment_id, status from
    dba_rollback_segs;
        select usn, rssize from v$rollstat;

注意,段的标识号在两个视图中具有不同的列名。

(5) 查看近来数据库中生成的撤消数据量:

        alter session set nls_date_format='dd-mm-yy hh24:mi:ss';
        select begin_time, end_time,
        (undoblks * (select value from v$parameter where  name='db_block_size'))
        undo_bytes from  v$undostat;

6.4 监视和管理撤消数据

撤消段的一个主要特性是其被自动管理,不过,我们必须对Oracle管理撤消段进行某些限制。考虑到数据库中活动的种类与数量,我们需要设置某些实例参数,并针对特定目标调整撤消表空间的大小。

6.4.1 与撤消相关的错误条件

管理撤消的原则十分简单:首先,应当始终存在允许所有事务继续进行的足够撤消空间;其次,应当始终存在保证查询成功的足够撤消数据。第一个原则要求撤消表空间大到足以应付撤消需求的最坏情况。我们应当为最坏情况(事务工作负荷所生成的有效撤消数据的最大使用)分配足够的空间。需要注意的是,最坏情况不一定出现在最大并发事务期间。在存在许多小事务的正常运行期间,且这些事务生成的撤消数据总量少于一个月末批量作业所生成的数据时,也可能出现最坏情况。第二个原则要求在撤消表空间内存在额外空间,这些空间能够存储读一致性可能需要的未过期撤消数据。

如果某个事务耗尽了撤消空间,那么这个事务就会由于Oracle错误“ORA-30036 unable to extend segment in undo tablespace”而失败。导致这个问题的语句会被回滚,但是指定事务的剩余部分会保持不变并不被提交。在撤消表空间内为撤消段分配空间的算法表明:当且仅当撤消表空间被活动撤消数据完全填满时才会引发这个错误条件。

考点:

如果DML语句用尽了撤消空间,则将回滚其已成功的部分。事务的其余部分保持完好,且不提交。

如果查询遇到自从查询启动以来更改过的块,它将访问撤消段来查找数据的旧版本。在访问撤消段时,如果所查找的撤消数据已被重写,则针对一致性读取的查询将失败,并出现广为人知的Oracle错误ORA-1555:“snapshot too old”。

如果对于事务量和查询长度而言,撤消表空间不够大,则Oracle将进行选择:使事务成功而让查询失败,出现ORA-1555错误;或者使查询成功,而让事务失败,出现ORA-30036错误。默认行为是使事务成功,允许它们重写未过期的撤消。

6.4.2 用于撤消管理的参数

有四个初始化参数可以控制撤消:

● UNDO_MANAGEMENT

● UNDO_TABLESPACE

● UNDO_ RETENTION(参见“配置撤消数据的保留时间”)

● TEMP_UNDO_ENABLED(参见“临时撤消数据”)

UNDO_MANAGEMENT参数默认为AUTO,也可以将其设置为MANUAL。也就是说, Oracle根本不会使用撤消段。这样做是为了实现向后兼容性,如果应用该设置,那么必须完成大量创建和调整回滚段的工作。因此,不要这样做。Oracle 强烈建议将该参数设置为AUTO,从而启用撤消段的使用。UNDO_MANAGEMENT参数是静态的,这意味着如果该参数发生变化,那么变化只有在重新启动实例之后才会生效。另外两个参数是动态的,它们可以在实例运行的同时被修改。

如果使用“UNDO_MANAGEMENT=AUTO”,那么必须指定UNDO_TABLESPACE参数。这个参数指定了一个作为撤消表空间(活动撤消表空间)创建的表空间,同时其内部的所有撤消段都会被自动联机(即供使用)。

6.4.3 调整与监视撤消表空间

撤消表空间应当足够大,这样才能存储最坏情况下并发事务生成的所有撤消数据,这些数据是活动的撤消数据以及运行时间最长的查询所需的足够的未过期撤消数据。在更高级的环境中,最好还应当添加允许闪回查询的空间。这个算法十分简单:首先计算在最高工作负荷时生成撤消的速度,然后再乘以耗时最长的查询的时间长度。查询V$UNDOSTAT视图可以得到需要知道的所有信息。

虽然撤消数据文件的可自动扩展功能能够确保事务永远不会耗尽所有空间,但是Oracle不会仅仅为了实现UNDO_RETENTION目的而对这些数据文件进行扩展,因此查询仍可能失败,并给出“snapshot too old”错误。无论如何,我们都不应依赖自动扩展性能,撤消表空间在最开始时就应当具有正确的大小。

图6-5使用SQL *Plus显示了撤消配置和用法。这些信息也可以在Database Express以图形格式获得。要想进入该界面,可以在数据库主页上,选择Storage 下拉菜单中的Undo Management链接。

图6-5 撤消配置和活动

图中的第一条语句把会话的日期显示格式设置为显示小时、分钟和秒数。接着SQL *Plus SHOW命令显示4个实例参数的设置,这些参数的名称都包含字符串undo。这4个参数都设置为其默认值:禁用临时撤消,撤消管理为自动(使用撤消段,而不是过时的回滚段),保留目标是900秒,撤消表空间是UNDOTBS1,它是在使用DBCA创建数据库时创建的表空间。对V$UNDOSTAT视图的查询显示在10分钟的时间内捕获的撤消活动。在所显示的半小时内,撤消生成的峰值是一个10分钟时间段内捕获281 117块,生成了908个事务。最长的查询是1393秒。最后,查询DBA_DATA_FILES显示,撤消表空间的数据文件是540 800块,大约4GB,这假定数据库使用默认的块尺寸8KB来创建。

进行一些简单的算术计算,说明生成撤消的峰值速率为约500块/秒,所以如果最长的查询约1000秒(比较接近UNDO_RETENTION设置),就需要约500 000块的撤消表空间,才能确保撤消总是可以保留与最长查询相同的时间。这个数据库的撤消配置能很好地匹配工作负载。

V$UNDOSTAT视图总是称为撤消顾问,因为它允许为给定的工作负载预测撤消数据可以保留的时长。Database Express很好地表达了这个信息,如图6-6所示。

图6-6 Database Express中的撤消配置

撤消顾问窗口中的曲线表示,如果撤消表空间是5GB,就能把撤消数据存储1500~4000秒(根据活动的情况)。较大或较小的尺寸会增加或减少撤消数据的保留时间。

6.4.4 临时撤消

临时撤消段用于存储在全局临时表上执行DML所生成的撤消数据。全局临时表的定义可以对所有会话(全局)可见,但其中的行是插入它们的会话所私有的。行的保留时间是到执行COMMIT为止,或者会话中断为止(临时)。

全局临时表常常对开发人员有用。它们提供了一个存储位置,可存储对中间结果集有用的数据,而无须考虑在不再需要这些数据时清理它们的问题,也无须确保会话不干扰(甚至查看)其他会话创建的数据。从数据库的角度看,全局临时表很容易管理。在创建(和删除)段时,它们自动存在于一个临时的表空间中。

临时表的性能通常优于永久表,原因有两个:

● I/O是直接的。会话读写其临时段时,无需通过缓冲区缓存,也不涉及数据库写入器。

● 在全局临时表上不生成重做数据。没有必要生成重做数据。重做的目的是使修改变成永久的数据,而全局临时表不存储永久数据。

撤消数据由DML在临时表上执行时生成。这是必须的,因为要应用通常的事务规则。它在生成重做数据之后完成,因为即使表可能是一个临时段,撤消段也不是。在早期的版本中,这会带来两个问题:

● 性能下降,因为撤消段输入/输出(I/O)通过缓冲区缓存进行,会生成相关联的重做数据。

● 不可能在只读数据库中对临时表执行事务;该表不可能存在于读写表空间中,但撤消段可能。

版本12c有一个功能,允许在临时表空间中创建临时撤消段。这可以显著提高在临时表上执行事务的性能,且不破坏事务的完整性,这还意味着,事务可以在只读数据库上执行,例如Data Guard物理备用数据库。

6.4.5 创建和管理撤消表空间

就数据文件管理而言,撤消表空间与其他任何表空间没有差别:它可以添加文件,调整文件大小,使文件联机和脱机,也可以移动或重命名文件。但无法指定任何有关存储的选项:无法指定自动段空间管理,无法指定统一的区间大小。要创建撤消表空间,需要使用关键字UNDO:

        CREATE UNDO TABLESPACE tablespace_name
        DATAFILE datafile_name SIZE size [ M | G | T ]
         [ RETENTION NOGUARANTEE | GUARANTEE ] ;

默认方式下,此表空间并不确保撤消保留。可以在创建表空间时指定该特性,也可以在后期设置:

        ALTER TABLESPACE tablespace_name
        retention [ GUARANTEE | NOGUARANTEE ] ;

考点:

如果创建时不在 datafile 子句中指定自动扩展特性,那么,不会将撤消表空间的数据文件设置为自动扩展。但是,如果使用DBCA(Database Configuration Assistant)创建了数据库,则将启用撤消表空间的自动扩展(使用无限制的最大大小)特性。与任何数据文件一样,可以随时启用或禁用自动扩展。

除了自动创建的撤消段之外,无法在撤消表空间中创建段。开始时,将有一个在撤消表空间中创建的10个撤消段组成的池。如果并发事务数超过10个,将创建更多的段。Oracle将监视并发事务率,并且根据需要调整段数。

一般而言,无论数据库中有多少个撤消表空间,每次都仅使用一个。此表空间中的撤消段将处于“联机”状态(表示可供使用),而其他任何表空间中的段将处于“脱机”状态,表示不使用它们。如果更改了撤消表空间,那么,旧撤消表空间中的所有撤消段将脱机,而新撤消表空间中的所有撤消段将联机。以下两种情况除外:

● 在RAC(Real Application Cluster)数据库中,打开数据库的每个实例都必须有自己的撤消表空间。可以针对每个实例将UNDO_TABLESPACE参数设置为不同值来加以控制。每个实例都使相应的撤消段联机。

● 如果通过更改UNDO_TABLESPACE参数来更改撤消表空间,那么,在事务完成前,任何以前指定的在更改时支持事务的表空间中的段一直处于联机状态。

练习6-6 使用撤消表空间

本练习要创建一个撤消表空间,并使用它。下面是要执行的步骤:

(1) 以SYSTEM的用户身份用SQL *Plus连接实例。

(2) 创建一个撤消表空间:

        create undo tablespace undo2 datafile 'a_path_and_filename'
        size 100m;

对于数据文件的路径和名称,可使用适合自己环境的任何值。

(3) 运行如下查询,为数据库中的每个表空间返回一行:

        select tablespace_name, contents, retention from dba_tablespaces

注意新的表空间有内容UNDO,表示它只能用于撤消段,保留时长是NOGUARANTEE。

(4) 运行如下查询,为数据库中的每个回滚或撤消段返回一行:

        select tablespace_name, segment_name, status
        from dba_rollback_segs;

注意在新的撤消表空间中会自动创建10个撤消段,但它们都是脱机的。

(5) 调整实例,以使用新的撤消表空间。使用SCOPE子句确保该修改不是永久的:

        alter system set undo_tablespace=undo2 scope=memory

(6) 重新运行第4步的查询。新表空间中的撤消段会变成联机状态,以前活动的撤消表空间变成脱机状态。

(7) 进行整理:把undo_tablespace参数设置回其初始值,再删除新的撤消表空间。记住使用子句INCLUDING CONTENTS AND DATAFILES。