学习目标
- 描述撤消数据的目的
- 实现自动撤销管理
- 创建和配置undo段
- 获取undo段信息
之前管理撤销数据被称为管理回滚数据
undo数据
在 Oracle 数据库中,UNDO 数据(撤销数据)用于确保事务的一致性和原子性。UNDO 数据记录了数据库中数据修改操作的逆操作(即撤销操作)。当事务被回滚、撤销,或者在数据库恢复时,UNDO 数据发挥了重要作用。
1. UNDO 数据的作用
UNDO 数据在 Oracle 中主要有两个用途:
-
事务回滚:如果事务被回滚(例如,用户执行
ROLLBACK
命令,或者由于错误回滚),数据库需要撤销在该事务中所做的所有更改。UNDO 数据提供了这些撤销操作的必要信息,确保数据库恢复到事务开始之前的状态。 -
数据库恢复和一致性:在多个事务并发执行的环境中,UNDO 数据也帮助保证数据库的一致性。例如,在一个事务修改数据之后,另一个事务可能会查询这些数据。如果第一个事务被回滚,UNDO 数据可以让第二个事务看到的是回滚之前的数据状态,从而避免读取到不一致的数据(读一致性)。
2. UNDO 数据的存储
UNDO 数据通常存储在一个专用的表空间中,称为 UNDO 表空间(undo tablespace
)。这个表空间用于存储所有的撤销信息。UNDO 表空间是 Oracle 数据库中非常重要的组件之一,其大小和管理策略直接影响数据库的性能和事务的处理能力。
-
UNDO 表空间:当创建数据库时,Oracle 会自动创建一个默认的 UNDO 表空间(通常是
UNDOTBS1
)。你可以根据需要创建更多的 UNDO 表空间。 -
UNDO 段 (Undo Segment):UNDO 表空间由多个 UNDO 段组成,每个段用于存储特定事务的撤销信息。
-
UNDO 扩展 (Undo Extent):UNDO 数据是按块(extent)进行分配的。每个 UNDO 段由多个 UNDO 扩展组成,扩展是最小的存储单位。
3. UNDO 数据的管理
UNDO 数据的管理不仅仅是空间分配的问题,还包括如何设置和维护 UNDO 表空间的大小、回滚行为、自动管理等参数。Oracle 提供了一些机制来优化和管理 UNDO 数据。
3.1 UNDO 表空间的自动管理
在 Oracle 中,UNDO 表空间可以使用两种方式进行管理:
-
手动管理 (Manual Undo Management):使用此模式时,数据库管理员需要手动创建和管理 UNDO 段,指定每个段的大小和数量。这种方式提供了更细粒度的控制,但需要更多的配置和管理。
-
自动管理 (Automatic Undo Management):这是 Oracle 默认的 UNDO 管理模式。在此模式下,Oracle 会自动创建和管理 UNDO 段,确保有足够的空间存储所有事务的撤销数据。使用自动管理时,DBA 不需要干预段的创建和空间的分配。
自动管理方式下,Oracle 使用 UNDO_RETENTION
参数来控制撤销信息的保留时间。UNDO_RETENTION
决定了撤销数据的最短保留时间,以确保回滚的事务可以正确恢复。这个时间值不代表数据保留的实际时间,只是指撤销数据的最小保留时间。
3.2 UNDO 表空间的大小和调整
UNDO 表空间的大小非常关键,因为它直接影响到事务的处理能力。如果 UNDO 表空间不足以存储所有事务的撤销信息,Oracle 会产生错误或开始覆盖旧的撤销数据,导致事务的回滚失败或者出现数据一致性问题。
-
调整 UNDO 表空间大小:可以通过调整
UNDO_RETENTION
参数、增加 UNDO 表空间的大小(例如通过ALTER DATABASE DATAFILE
或ALTER TABLESPACE
),或者创建更多的 UNDO 数据文件来调整。 -
UNDO_RETENTION:这个参数指定了撤销信息的最小保留时间。一般来说,可以根据系统的负载和事务的回滚需求来调整它。
ALTER SYSTEM SET UNDO_RETENTION = 3600; -- 设置撤销数据的保留时间为 1 小时
在自动管理模式下,Oracle 会尝试保持 UNDO 数据至少在这个时间范围内可用,但这并不意味着 UNDO 数据会保留固定的时间;如果空间不足,系统会尽量保持数据的一致性。
3.3 UNDO 数据的清理
UNDO 数据并不会无限期保留,而是会在某些条件下被清理。Oracle 会自动清理不再需要的 UNDO 数据。例如,当事务提交或回滚时,相关的 UNDO 数据会被标记为过时,并最终被删除。
- 提交事务后:当一个事务成功提交时,相关的 UNDO 数据不再需要,可以被清除。
- 回滚事务后:如果一个事务被回滚,UNDO 数据会被释放,但它可以保留一段时间,以便其他并发事务可以访问旧数据(例如,进行快照读取)。
当数据库启动时,Oracle 会自动清理掉在前一次会话期间已经过时的 UNDO 数据。
3.4 查看 UNDO 数据
DBA 可以使用以下视图来查看与 UNDO 相关的信息:
-
DBA_UNDO_EXTENTS:显示当前 UNDO 表空间中的所有 UNDO 扩展信息。你可以查看这些扩展的使用情况、空间大小和状态。
SELECT * FROM DBA_UNDO_EXTENTS;
-
DBA_UNDO_SEGMENTS:显示所有 UNDO 段的详细信息,包括每个段的状态、大小、当前事务数等。
SELECT * FROM DBA_UNDO_SEGMENTS;
-
V$UNDOSTAT:显示 UNDO 数据的使用情况,例如已用空间、撤销操作的数量等。这些信息对监控和优化 UNDO 管理非常有用。
SELECT * FROM V$UNDOSTAT;
4. 管理 UNDO 数据时的常见问题和注意事项
-
UNDO 表空间不足:如果 UNDO 表空间不足,Oracle 会覆盖旧的 UNDO 数据,导致事务回滚失败或者数据不一致。在这种情况下,需要增加 UNDO 表空间的大小或调整
UNDO_RETENTION
参数,确保有足够的空间来存储撤销数据。 -
长时间运行的查询和事务:如果长时间运行的查询或事务未提交,它们会占用 UNDO 表空间,并且可能会阻塞对同一数据的其他事务。DBA 可以通过监控长事务,及时提交或回滚这些事务,以减少对 UNDO 数据的占用。
-
自动扩展:可以设置 UNDO 数据文件的自动扩展选项(例如,
AUTOEXTEND
),这样当表空间空间不足时,Oracle 可以自动增加数据文件的大小,以保证事务的顺利进行。ALTER DATABASE DATAFILE '/path/to/undo01.dbf' AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED;
-
UNDO 数据的回收:在某些情况下(例如,系统繁忙、频繁的事务回滚),UNDO 数据会快速增长。如果 UNDO 数据不再需要,Oracle 会在后台回收这些数据,但在高负载环境下,回收过程可能会受到影响。
UNDO 数据 的概念和具体管理细节
1. UNDO 数据的核心概念
1.1 事务的原子性和一致性
在数据库中,事务是一组操作,要么完全执行,要么完全不执行。为了保证这一点,原子性(Atomicity)和一致性(Consistency)是两个核心概念:
-
原子性:确保事务的所有操作要么完全成功,要么完全失败。如果事务中的某个操作失败,数据库会回滚,撤销所有前面的操作。
-
一致性:事务必须使数据库从一个一致的状态转变到另一个一致的状态。这意味着每个事务的执行必须遵循数据库的完整性约束。
为了实现这两个特性,Oracle 使用了 UNDO 数据。UNDO 数据记录了每个修改操作的反向操作,它保证了在事务回滚时能够恢复到原始状态。
1.2 UNDO 数据的作用
-
事务回滚:当事务需要回滚时,Oracle 会使用 UNDO 数据来撤销事务中的所有修改。例如,如果一个事务插入了数据,UNDO 数据会记录删除这些数据的操作。
-
读一致性:UNDO 数据也用于在事务并发执行时保证读取一致性。即使某个事务修改了数据,其他事务仍然能够读取到数据修改前的状态,这通过使用 快照隔离 实现。Oracle 通过 UNDO 数据来确保读取时的数据一致性,避免读取到不完整或临时的变更。
-
数据库恢复:如果数据库崩溃或出现故障,Oracle 会使用 UNDO 数据来回滚所有尚未提交的事务,从而恢复到崩溃前的一致状态。
2. UNDO 数据的存储与管理
2.1 UNDO 表空间 (UNDO Tablespace)
在 Oracle 数据库中,所有的 UNDO 数据都会存储在一个专门的表空间中,这就是 UNDO 表空间。
-
UNDO 表空间:用于存储所有事务的撤销信息。每个 Oracle 数据库实例都会有一个或多个 UNDO 表空间。
-
默认表空间:在安装数据库时,Oracle 会自动创建一个默认的 UNDO 表空间,通常名为
UNDOTBS1
。你也可以创建多个 UNDO 表空间。 -
UNDO 数据文件:UNDO 表空间包含多个数据文件,存储着 UNDO 数据的物理内容。这些数据文件通过配置
DB_CREATE_FILE_DEST
参数来指定。
2.2 UNDO 段 (Undo Segment)
UNDO 表空间并非是一个单一的空间,而是由多个 UNDO 段 组成的。每个 UNDO 段代表一个逻辑的撤销单元,用来存储一个事务的撤销操作。
-
UNDO 段的作用:每个事务开始时,Oracle 会为该事务分配一个 UNDO 段,并将事务的撤销信息写入其中。当事务提交或回滚时,Oracle 会清理相应的 UNDO 段。
-
UNDO 段的生命周期:每个 UNDO 段的生命周期与事务的生命周期相同,当事务提交时,UNION 段会被标记为可回收;如果事务回滚,相关的 UNDO 数据会被用于撤销所有修改。
2.3 UNDO 扩展 (Undo Extent)
UNDO 数据是按 扩展(extent)进行分配的。每个 UNDO 段由多个 UNDO 扩展组成。每个扩展通常包含一个固定数量的数据块(例如,1MB 或 2MB),这些数据块用于存储撤销操作的具体数据。
- 扩展的分配:在 UNDO 表空间中,随着事务的进行,Oracle 会动态分配扩展来存储 UNDO 数据。当某个 UNDO 段的空间不足时,Oracle 会为它分配新的扩展。
UNDO 和 REDO
1. UNDO 和 REDO 的定义
-
UNDO 数据:用于撤销已经执行的事务操作,使数据库回到事务开始之前的状态。也就是说,UNDO 数据记录了事务修改操作的逆向操作,比如删除操作的撤销是“插入一条记录”,更新操作的撤销是“将值恢复为原值”。
-
REDO 数据:用于重做已经提交的事务操作。如果数据库崩溃并且部分事务没有持久化到磁盘时,REDO 数据将被用来确保已提交的事务在恢复时不会丢失。REDO 数据记录了事务对数据库所做的修改(包括插入、删除、更新等),这些操作如果在系统崩溃后丢失,REDO 数据将使数据库恢复到事务提交后的状态。
2. UNDO 和 REDO 的区别
特性 | UNDO 数据 | REDO 数据 |
---|---|---|
作用 | 用于回滚(撤销)未提交的事务,恢复到事务之前的状态 | 用于恢复(重做)已提交的事务,确保事务的持久性 |
存储内容 | 存储事务修改的反向操作 | 存储事务修改的实际操作 |
使用时机 | 事务回滚或数据库恢复时使用 | 数据库崩溃恢复时使用,确保已提交事务不会丢失 |
是否依赖提交 | 与事务是否提交无关,任何未提交的事务都会有 UNDO 数据 | 只有事务提交后,才会生成 REDO 数据 |
3. UNDO 和 REDO 如何协同工作
在 Oracle 中,UNDO 和 REDO 的协同工作确保了数据库在事务处理中具有原子性、持久性和恢复能力。它们的工作机制可以通过以下几个方面来理解:
3.1 事务的执行过程
当一个事务执行时,数据库会同时记录 UNDO 和 REDO 数据:
-
REDO 数据:在事务修改数据时,Oracle 会将这些修改的操作(例如插入、删除、更新)记录为 REDO 日志。无论事务是否成功提交,REDO 数据都会被写入到重做日志文件(redo log)中。
-
UNDO 数据:在事务修改数据时,Oracle 会在内存中的撤销段中记录这次修改的“逆操作”,以便在事务回滚时能够撤销这些修改。UNDO 数据会被写入到UNDO 表空间,用于存储回滚信息。
3.2 提交事务时
-
当事务提交时,REDO 数据会被持久化到重做日志文件中,这确保了事务的持久性。即使数据库崩溃,重做日志可以帮助数据库恢复到事务提交后的状态。
-
UNDO 数据会被标记为过期,并可以被回收,因为已经提交的事务不需要回滚。
3.3 回滚事务时
-
当事务回滚时,UNDO 数据被使用,它会将数据恢复到事务开始前的状态。回滚操作是基于撤销日志(UNDO 日志)来进行的。
-
REDO 数据不会被使用,因为回滚并不涉及重做任何已提交的操作,它只是撤销已执行的操作。
3.4 数据库崩溃恢复时
在数据库崩溃的情况下,数据库必须确保所有已提交的事务不丢失,并且回滚所有未提交的事务。此时,UNDO 和 REDO 的配合至关重要:
-
REDO 数据:当数据库恢复时,Oracle 会扫描 重做日志文件,重新执行已提交事务的操作,确保事务提交后所做的更改被持久化。也就是说,重做日志可以确保数据库中所有已提交事务的数据更新不会丢失。
-
UNDO 数据:在恢复过程中,Oracle 会通过扫描 UNDO 表空间,回滚所有未提交的事务,将其撤销到事务开始之前的状态。通过使用 UNDO 数据,未提交的事务所做的更改不会影响数据库的最终状态。
3.5 写前日志(WAL,Write-Ahead Logging)
在 Oracle 中,事务的写前日志机制保证了 REDO 数据 会先写入到重做日志文件,再将修改的数据写入到数据文件。这是为了确保即使系统崩溃,未提交的事务的修改数据也可以通过 REDO 数据恢复。
写前日志的顺序:
- 事务开始并进行修改操作。
- REDO 数据先写入到重做日志文件。
- 数据页(块)会被修改并写入磁盘。
- 如果事务提交,REDO 数据会被完全持久化,表示事务成功提交。
4. 具体的操作流程和例子
我们可以用一个简单的例子来具体说明 UNDO 和 REDO 的工作过程:
假设有一个事务 T1
,它修改了表 EMP
中某个员工的薪水:
UPDATE emp SET salary = 5000 WHERE empno = 100;
4.1 事务执行前
- REDO:数据库记录了这条 更新操作,确保即使崩溃后,事务提交后这个更改不会丢失。
- UNDO:数据库记录了更新操作的反向操作,即将
salary
恢复为原来的值。
4.2 事务提交时
- REDO:事务提交后,REDO 数据会被持久化到重做日志文件中,以确保在恢复过程中这次更新可以重新执行。
- UNDO:此时,UNDO 数据不再需要,并可以被回收。
4.3 事务回滚时
- 如果事务没有提交,用户调用
ROLLBACK
,那么:- UNDO:Oracle 会使用 UNDO 数据,将
empno = 100
的薪水恢复到更新前的值。 - REDO:不会使用 REDO 数据,因为回滚并不涉及对已提交事务的任何操作。
- UNDO:Oracle 会使用 UNDO 数据,将
4.4 系统崩溃后恢复
- 如果在事务
T1
提交后系统崩溃,恢复过程如下:- REDO:数据库会扫描重做日志,重新应用事务
T1
的修改,确保薪水为 5000。 - UNDO:如果有未提交的事务(例如,修改了其他员工薪水的事务
T2
),它们会被回滚到原始状态,确保未提交事务的数据不会被持久化。
- REDO:数据库会扫描重做日志,重新应用事务
5. UNDO 和 REDO 的同步与优化
在实际应用中,UNDO 和 REDO 的写入会遵循 异步和同步的机制:
-
REDO 日志:通常会异步写入磁盘(即先写入内存,后写入磁盘)。这样做可以提高性能,但同时也需要保证数据的可靠性,避免丢失已提交事务的更改。
-
UNDO 数据:因为涉及到撤销操作,它的写入通常是同步的,确保在事务回滚时,所有撤销信息都能够被正确地存储和应用。