一、UNDO
UNDO 段是用于存储还原数据的特殊段,在发生实例故障的时候,UNDO 段用来对数 据进行恢复。本章内容包括介绍 UNDO 段的工作原理,并进行自动和手工的 UNDO 段的管理
1.1 UNDO 段的作用
RDBMS(关系数据库管理系统)必须要提供一致性的数据,以确保不会丢失数据或导致数据混乱。例如,当用户去银行取款时,需要在用户储蓄账户上减去取款额,而在银行支出账户上增加取款额,以使得收支平衡。当使用关系数据库处理以上过程时,储蓄账户、支出账户分别对应于数据库表。当用户提款时,分别会在储户表、支出账户表上使用 UPDATE 语句执行增减款操作,最终提交事务,以确保收支平衡。
大家设想一下,假设当在储蓄账户上减去取款额之后,因为机器断电导致数据库停止工作,怎么办?你可能会想这会导致收支不平衡,不会的,关系数据库通过事务(Transaction)实现了数据一致性。因为断电时事务尚未完成,所以将来在启动数据库时系统会自动回退未提交操作,并最终保证数据的一致性。从数据库的角度看,如果储蓄账户执行了 UPDATE 操作后出现断电,那么当重新启动数据库时系统会自动执行还原操作,将修改的数据恢复成原有数据。此时大家可能会问,那么原有数据存放在哪儿呢?当执行 INSERT、UPDATAE、 DELETE
等 DML 操作时,服务器进程会将原有数据(称为 UNDO 数据)存放到 UNDO 段中,UNDO 段是专门用于存储还原数据的段。UNDO 数据也被称为回滚(ROLLBACK)数据,它用于确保数据的一致性。当执行 DML 操作(INSERT、UPDATE、DELETE 等)时,操作前的数据被称为 UNDO 记录。例如,当执行“UPDATE emp SETsal=1000WHERE empno=7788”语句时,假定雇员 7788 原有工资为 800,原有数据 800 就是 UNDO 数据,并且该数据会被存放到还原段中,而新数据 1000 则会存放到 EMP 数据段中。还原段用于在进程更改数据库中的数据时保存数据的旧值(可能还原的数据)。它按数据被修改之前的原样存储数据的位置及数据本身(如图 9-1 所示)。许多并发事务处理可以写入一个 UNDO 段。
UNDO 段有如下几个用途,如图 9-2 所示。
1)事务处理回退
当某事务处理修改表中某行时,被修改的列的旧值(要还原的数据)将存储在 UNDO 段中,新数据被存入到数据段中。如果将该事务处理回退,即执行 ROLLBACK 命令,则 Oracle 服务器通过将还原段中的值写回到该行来恢复原始值。例如用户 A 在执行了语句“UPDATE emp SET sal=1000 WHERE empno=7733”后发现应该修改 7868 号雇员的工资而丌是 7733 号雇员的工资,那么通过执行“ROLLBACK”语句可以取消事务,此时系统将回滚段中的 UNDO 数据 800 从 UNDO 段中又写回数据段中。
2)事务处理恢复
事务恢复是由 ORACLE SERVER 自动完成的。如果实例在事务处理正在进行时失败(INSTANCEFAILURE) ,那么 Oracle 服务器需要在数据库再次打开时回退所有未提交的事务。这种回退操作是事务处理恢复的一部分。之所以有可能恢复事务处理,原因在于对还原段所做的更改同样受重做日志文件的保护。
3)读一致性
当用户检索数据库数据时,Oracle 总是使提用户只能看到被提交过的数据(读取提交)或者特定时间点的数据(SELECT 语句时间点),这样可以确保数据的一致性。读一致性是由 ORALCE 提供的,并且该特征是通过 UNDO 记录来实现有。还原段中的旧值(要回退的数据)用于保证数据的读一致性。Oracle 服务器保证一条语句所看到的数据来自一致的时间,即使其它事务处理修改了该数据。例如,当 Oracle 服务器开始执行 SELECT 语句时,首先确定当前系统更改号(SCN),并确保这个 SCN之前未提交的任何修改不会被这条语句处理。如果在这次查询开始时某行有未提交的数据更改,Oracle 服务器会从还原段检索这些更改的旧值,并显示该旧值,如:
图 9-3 所示:
1.2 自动 UNDO 空间管理
在 Oracle9i 以前,管理 UNDO 数据需要 DBA 建立专门的还原段,但这种方法相当复杂;为了简化UNDO 数据的管理,从 Oracle9i 开始,管理 UNDO 数据有两种方法,一种是自动管理模式,通过 UNDO 表空间可以自动管理 UNDO 数据,另外一种是手工管理方式,即使用 UNDO 段管理 UNDO 数据。顾名思义,UNDO 表空间是指之门存放 UNDO 数据的表空间,并且只能存放回滚段而不能存放其它的数据段。当使用UNDO 表空间时,Oracle 会自动在该表空间上建立还原段,以供事务操作使用。UNDO 表空间上的还原段,按照这样的方式命名:_SYSSMUn$,比如:_SYSSMU10$、_SYSSMU11$ 等。
如果使用自动管理模式,则必须要将初始化参数 UNDO_MANAGEMENT 设置为 AUTO。这样,当启动Oracle 服务器之后,Oracle 会使用 UNDO 表空间自动管理 UNDO 数据,并且 Oracle 自动选择第一个可用 的 UNDO 表 空 间 存放 UNDO 数 据 。 在 有多 个 UNDO 表 空 间 时, 可 以 通 过 设 置 初 始 化 参数UNDO_TABLESPACE 选择使用的 UNDO 表空间。但是如果没有 UNDO 表空间可用,则 Oracle 会使用SYSTEM 还原段存放 UNDO 记录。
1.2.1 UNDO 空间管理参数
自动管理模式相关的初始化参数和意义如下。
1)UNDO_MANAGEMENT
该参数用于指定数据库 UNDO 数据的管理模式。该参数可以设置为 AUTO 和 MANUAL 这两个值中的任一个值,并且必须在初始化参数文件中设置。UNDO_MANAGEMENT 不能在数据库启动后进行动态更改。
- AUTO 模式可以将数据库设置为自动还原管理,并需要 UNDO 表空间。
- 在 MANUAL 模式(缺省值)下,可以根据需要在数据库中创建和管理还原段,这不以前的 Oracle 服务器版本中的操作相同。如果数据库中叧有一个 UNDO 表空间,并且将 UNDO_MANAGEMENT 设置为 AUTO,则 UNDO_TABLESPACE 参数是可选的;Oracle 服务器将自劢选择 UNDO 表空间的。
2)UNDO_TABLESPACE
该参数用于指定在自动管理模式下要使用的 UNDO 表空间。此参数可以在初始化文件中设置,或使用ALTER SYSTEM 命令来劢态改变。语句如下: ALTER SYSTEM SET UNDO_tablespace=UNDOTBS;
3)UNDO_SUPPRESS_ERRORS
使用 UNDO_SUPPRESS_ERRORS,用户可以避免在自动还原管理模式下执行手劢还原管理模式操作(例如,ALTERROLLBACK SEGMENTONLINE)时出现错误。通过设置这个参数,用户可以在将所有应用程序和脚本 转 换 成 自 动 还 原 管 理 模 式 前 使 用 还 原 表 空 间 功 能 。 例 如 , 如 果 有 一 个 使 用 SETTRANSACTION USEROLLBACK SEGMENT 语句 的 应用 程 序,则 可 以 向该 应用 程 序添 加 语 句 ALTER SESSION SET
UNDO_SUPPRESS_ERRORS=true 以避免 ORA-30019 错误。ORA-30019:在自动还原模式下执行了非法的回退段。4)UNDO_RETENTION
该参数用于指定保留 UNDO 数据的时间,以便提供读一致性,默认值为 900s。如果执行查询的时间很长,尽 可 能 保 留 更 多 的 还 原 数 据 , 但 是 需 要 UNDO 表 空 间 的 数 据 文 件 也 越 大 。 以 秒 为 单 位 定 义 的UNDO_RETENTION 参数可以在初始化文件中设置,或使用 ALTER SYSTEM 命令来动态态修改。
本地撤消模式
本地撤消模式意味着每个容器都有自己的撤销表空间。在此模式下,Oracle 数据库会自动为 CDB 中的每个容器创建一个撤消表空间。对于 Oracle RAC CDB,在本地撤消模式下,每个 PDB 的每个实例都有一个活动的撤消表空间。
本地撤消模式为每个容器提供了更高的隔离,并提高了某些操作的效率,例如拔出容器或在容器上执行时间点恢复。此外,需要支持某些操作的本地撤消模式,例如重新定位 PDB 或克隆处于开放读/写模式的 PDB。当 CDB 处于本地撤消模式时,以下情况适用:
- 对当前容器具有适当权限的任何用户都可以为容器创建撤消表空间。有关所需权限的信息,请参见 Oracle 数据库 SQL 语言参考。
- 撤消表空间在静态数据字典视图和 CDB 中每个容器中的动态性能(V $)视图中都可
共享撤消模式
共享撤消模式意味着单实例 CDB 有一个活动的撤消表空间。对于 Oracle RAC CDB,每个实例都有一个活动的撤消表空间。
当 CDB 处于共享撤消模式时,以下情况适用:
- 只有具有相应权限且当前容器为 CDB 根的普通用户才能创建撤消表空间。
- 当前容器不是 CDB 根时,尝试创建撤消表空间失败并返回错误。
- 当前容器是 CDB 根时,撤消表空间在静态数据字典视图和动态性能(V $)视图中可见。当前容器是 PDB,应用程序根目录或应用程序 PDB 时,撤消表空间仅在动态性能视图中可见。
· SELECT PROPERTY_NAME, PROPERTY_VALUE
· FROM DATABASE_PROPERTIES
· WHERE PROPERTY_NAME = 'LOCAL_UNDO_ENABLED';1.2.2UNDO 空间管理
1、创建 undo 表空间:
CREATE UNDO TABLESPACE undotbs_02
DATAFILE '/u01/app/oracle/undo0201.dbf' SIZE 2M REUSE AUTOEXTEND ON;2、alter undo tablespace
ALTER TABLESPACE undotbs_01
ADD DATAFILE '/u01/oracle/oracle/undo0201.dbf ' AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED;3、switch undo tablespace
ALTER SYSTEM SET UNDO_TABLESPACE = undotbs_01;4、drop undo tablespace
DROP TABLESPACE undotbs_01;1.2.3 管理临时 undo
临时撤消记录存在数据库的临时表空间中,因此不会记录在重做日志中。启用临时撤消后,临时表空间使用的某些段会存储临时撤消,这些段称为临时撤消段。启用临时撤消后,可能需要增加临时表空间的大小以考虑撤消记录。
启用临时撤消可带来以下好处:
- 临时撤消可以减少撤消表空间中存储的撤消量。撤消表空间中的较少撤消可以让撤消保留期的记录的到达更实际的要求。
- 临时撤消会减小重做日志的大小。性能得到改善,因为重做日志中写入的数据较少,而解析重做日志记录的组件(如 LogMiner)性能更好,因为要解析的重做数据较少。
- 临时撤消使用 Oracle Active Data Guard 选项对物理备用数据库中的临时表启用数据操作语言(DML)
操作。但是,必须在主数据库上发出创建临时表的数据定义语言(DDL)操作。您可以为特定会话或整个系统启用临时撤消。使用 ALTER SESSION 语句为会话启用临时撤消时,会话会创建临时撤消,而不会影响其他会话。使用 ALTER SYSTEM 语句为系统启用临时撤消时,所有现有会话和新会话都会创建临时撤消。当会话第一次使用临时对象时,TEMP_UNDO_ENABLED 将为会话的其余部分设置初始化参数的当前值。因此,如果为会话启用了临时撤消,并且会话使用临时对象,则无法为会话禁用临时撤消。同样,如果为会话禁用临时撤消并且会话使用临时对象,则无法为会话启用临时撤销。
注意:仅当数据库的兼容级别为 12.0.0 或更高时,才能启用临时撤消。
- 要为会话启用临时撤消,请运行以下 SQL 语
ALTER SESSION SET TEMPUNDOENABLED = true;- 要禁用会话的临时撤消,请运行以下 SQL 语句:
ALTER SESSION SET TEMP_UNDO_ENABLED = FALSE;- 要为系统启用临时撤消,请运行以下 SQL 语句:
ALTER SYSTEM SET TEMP_UNDO_ENABLED = TRUE;为系统启用临时撤消后,会话可以使用该 ALTER SESSION 语句禁用临时撤
- 要禁用系统的临时撤消,请运行以下 SQL 语句:
ALTER SYSTEM SET TEMP_UNDO_ENABLED = FALSE;1.2.4 相关视图:
==============================================================