找回密码
 立即注册
首页 业界区 业界 Oracle回滚与撤销(Undo)技术:从理论到实操全解析 ...

Oracle回滚与撤销(Undo)技术:从理论到实操全解析

施婉秀 昨天 21:50
在Oracle数据库中,回滚(Rollback)与撤销(Undo)是保障事务一致性、数据可恢复性的核心机制。Undo通过记录数据修改前的前镜像(Before Image),实现事务回滚、读一致性保障和故障恢复,其设计与实践直接影响数据库的稳定性和性能。
一、Undo技术核心理论

1.  Undo的定义与核心作用

Undo是Oracle用于记录数据修改前状态的精简信息,与Redo(重做日志)共同构成事务完整性保障体系。Redo保障故障时事务可恢复,Undo则实现三大核心功能:

  • 事务回滚:用户执行ROLLBACK时,通过Undo前镜像恢复数据原始状态。
  • 读一致性:多用户并发访问时,确保查询能获取同一时间点的一致数据,避免未提交数据可见。
  • 事务恢复:数据库实例故障后,SMON进程利用Undo数据回滚未提交的事务。
2.  Undo的存储内容与生成规则

Undo数据仅记录撤销事务必需的精简信息,不同操作生成的Undo量差异显著:

  • Insert操作:仅记录插入记录的ROWID,回滚时通过ROWID删除记录,生成Undo量最少。
  • Update操作:仅记录被更新字段的旧值(前镜像),回滚时用旧值覆盖新值,Undo量居中。
  • Delete操作:记录整行数据,回滚时通过反向操作恢复数据,生成Undo量最多。
这一特性决定了大规模删除操作(如大批量DELETE)应分批执行并分次提交,以减少Undo空间占用和性能冲击。
3.  Undo管理模式的演进

Oracle的Undo管理模式经历了从手动到自动的迭代,核心差异如下:

  • 手动管理(Oracle 9i之前):通过手动创建、配置回滚段(Rollback Segment)管理Undo数据,需手动指定事务使用的回滚段,维护成本高。
  • 自动管理(AUM,Oracle 9i及以后):引入自动撤销表空间(Undo Tablespace),Oracle自动分配、回收回滚段,支持动态扩展与收缩,通过初始化参数控制行为,降低维护成本。
AUM模式的核心参数包括:

  • undo_management:指定管理模式(AUTO为自动,MANUAL为手动)。
  • undo_tablespace:指定当前使用的Undo表空间。
  • undo_retention:事务提交后Undo数据的保留时间(秒),9iR2默认10800秒(3小时)。
  • undo_suppress_errors:自动模式下屏蔽不支持操作的报错(向后兼容参数)。
4.  读一致性与多版本模型

Oracle通过多版本模型(Multi-versioning Model)实现读写分离:写入不阻塞读取,读取不阻塞修改。其核心机制是一致性读(Consistent Read):

  • 当查询执行时,Oracle会检查数据块的提交SCN(系统变更号)。
  • 若数据块SCN晚于查询开始SCN,或数据处于未提交状态,Oracle会通过Undo表空间中的前镜像构造一致数据返回给用户。
例如:Session 2更新数据但未提交时,Session 1的查询会通过Undo中的前镜像获取原始数据,确保查询结果的一致性。
5.  关键性能指标:平均事务回滚率

平均事务回滚率(Rollback per Transaction %)是衡量Undo使用效率的核心指标,计算公式为:
[ Round(User rollbacks / (user commits + user rollbacks) ,4) \times 100% ]
该指标应接近0,若过高(如案例中38.22%),说明数据库存在大量无效操作,会严重占用Undo空间并降低性能,需排查应用逻辑或事务设计问题。
二、Undo核心机制深度解析

1.  块清除(Block Cleanouts)机制

事务提交后,Oracle需清除数据块上的事务信息(ITL槽、行级锁),分为两种模式:

  • 快速块清除(Fast Block Cleanout):若提交时数据块仍在Buffer Cache中,直接清除ITL信息,效率极高。
  • 延迟块清除(Delayed Block Cleanout):若数据块已写入数据文件,或修改块数量超过Buffer Cache的10%,则延迟至下次访问该块时清除。
延迟块清除可能导致查询时产生额外Redo,若Undo数据已被覆盖,还可能触发ORA-01555错误。
2.  Undo保留策略与Guarantee模式


  • 非保障模式(No Guaranteed):Oracle 9i默认模式,当Undo表空间不足时,会覆盖已提交事务的Undo数据,忽略undo_retention设置。
  • 保障模式(Guarantee):Oracle 10g引入,通过ALTER TABLESPACE undotbs1 RETENTION GUARANTEE启用,强制保留undo_retention指定时间的Undo数据。若空间不足,新事务会失败而非覆盖旧数据,可有效避免ORA-01555错误。
3.  Undo技术的版本演进


  • Oracle 9i:引入AUM自动管理模式,简化回滚段维护,新增undo_retention参数。
  • Oracle 10g:增强Undo保留策略,支持自动调整undo_retention(设置为0时启用),引入In Memory Undo(IMU)减少I/O开销,新增闪回版本查询与闪回事务查询。
  • Oracle 11g:优化回滚段命名规则(包含创建时间戳),引入闪回数据归档(Flashback Data Archive),支持Undo数据长期归档与任意时间点追溯。
三、Undo技术实操案例

1.  案例1:AUM模式下Undo表空间创建与配置

需求

创建自动管理的Undo表空间,设置保留时间为4小时,启用Guarantee模式避免Undo数据被提前覆盖。
实操步骤


  • 创建Undo表空间
  1. CREATE UNDO TABLESPACE UNDOTBS2
  2. DATAFILE '/opt/oracle/oradata/test/undotbs2.dbf' SIZE 200M
  3. AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
复制代码

  • 切换当前Undo表空间
  1. ALTER SYSTEM SET undo_tablespace=UNDOTBS2 SCOPE=BOTH;
复制代码

  • 配置Undo保留时间与Guarantee模式
  1. ALTER SYSTEM SET undo_retention=14400; -- 4小时(单位:秒)
  2. ALTER TABLESPACE UNDOTBS2 RETENTION GUARANTEE;
复制代码

  • 验证配置
  1. SELECT tablespace_name, contents, retention FROM dba_tablespaces WHERE tablespace_name='UNDOTBS2';
复制代码
预期结果:RETENTION字段显示为GUARANTEE,确认配置生效。
2.  案例2:利用闪回查询恢复误删除数据

需求

某业务误删除了emp表中empno=7788的记录并提交,需通过闪回查询(Flashback Query)恢复数据。
实操步骤


  • 确认当前SCN(系统变更号)
  1. SELECT dbms_flashback.get_system_change_number FROM dual;
  2. -- 假设返回SCN:12930142214
复制代码

  • 闪回查询删除前的数据
  1. -- 尝试不同SCN找到删除前的状态
  2. SELECT * FROM emp AS OF SCN 12929941968 WHERE empno=7788;
复制代码

  • 恢复误删除数据
  1. -- 创建临时表存储恢复数据
  2. CREATE TABLE emp_recov AS SELECT * FROM emp AS OF SCN 12929941968 WHERE empno=7788;
  3. -- 将数据插入原表
  4. INSERT INTO emp SELECT * FROM emp_recov;
  5. COMMIT;
复制代码

  • 验证恢复结果
  1. SELECT * FROM emp WHERE empno=7788;
复制代码
关键说明:闪回查询依赖Undo数据未被覆盖,若出现ORA-01555错误,需检查undo_retention设置或启用Guarantee模式。
3.  案例3:处理ORA-01555错误(快照过旧)

问题现象

执行长查询时提示:ORA-01555: snapshot too old: rollback segment number 6 with name "_SYSSMU6$" too small,原因是Undo数据被覆盖,无法构造一致性读。
解决方案


  • 临时解决方案:延长Undo保留时间并启用Guarantee模式
  1. ALTER SYSTEM SET undo_retention=28800; -- 8小时
  2. ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;
复制代码

  • 长期解决方案:扩展Undo表空间容量
  1. ALTER DATABASE DATAFILE '/opt/oracle/oradata/test/undotbs1.dbf' RESIZE 500M;
  2. ALTER DATABASE DATAFILE '/opt/oracle/oradata/test/undotbs1.dbf' AUTOEXTEND ON NEXT 100M;
复制代码

  • 优化查询:拆分长查询为多个短查询,减少一致性读窗口。
4.  案例4:重建过度扩展的Undo表空间

问题现象

Undo表空间因大事务过度扩展至27GB,且无法自动收缩,导致磁盘空间耗尽。
实操步骤


  • 确认当前Undo表空间状态
  1. SELECT file_name, bytes/1024/1024 AS size_mb FROM dba_data_files WHERE tablespace_name='UNDOTBS1';
复制代码

  • 创建新的Undo表空间
  1. CREATE UNDO TABLESPACE UNDOTBS3 DATAFILE '/opt/oracle/oradata/test/undotbs3.dbf' SIZE 100M AUTOEXTEND ON;
复制代码

  • 切换至新Undo表空间
  1. ALTER SYSTEM SET undo_tablespace=UNDOTBS3 SCOPE=BOTH;
复制代码

  • 等待旧Undo表空间回滚段离线
  1. SELECT usn, status FROM v$rollstat;
  2. -- 直至所有旧回滚段状态变为OFFLINE
复制代码

  • 删除旧Undo表空间释放空间
  1. DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS;
复制代码
四、Oracle Undo 常见问题排查手册

ORA-01555:快照过旧(Snapshot Too Old)

现象

执行查询时提示:ORA-01555: snapshot too old: rollback segment number X with name "XXX" too small,长查询、统计分析任务易触发。
核心成因


  • Undo数据被覆盖:事务提交后,Undo数据未满足undo_retention时间就被新事务覆盖(非Guarantee模式下)。
  • 延迟块清除:查询触发延迟块清除时,需读取Undo获取提交SCN,但Undo数据已丢失。
  • sqlldr直接加载(direct=true):加载数据不产生Undo,Cached Commit SCN导致访问时出错。
排查步骤


  • 检查Undo核心参数配置:
    1. show parameter undo; -- 查看undo_management、undo_retention、undo_tablespace
    2. select tablespace_name, contents, retention from dba_tablespaces where tablespace_name like 'UNDO%'; -- 确认是否启用Guarantee模式
    复制代码
  • 分析Undo表空间状态:
    1. select file_name, bytes/1024/1024 as size_mb from dba_data_files where tablespace_name='UNDOTBS1'; -- 查看表空间大小
    2. select usn, rssize/1024/1024 as rssize_mb, hwmsize/1024/1024 as hwmsize_mb from v$rollstat; -- 查看回滚段占用
    复制代码
  • 统计事务提交/回滚情况:
    1. select name, value from v$sysstat where name in ('user commits', 'user rollbacks'); -- 计算回滚率
    复制代码
  • 跟踪块清除行为(可选):
    1. alter system set event="10203 trace name context forever" scope=spfile; -- 重启数据库后生效,生成块清除跟踪文件
    复制代码
解决方案


  • 调整undo_retention参数(需确保Undo表空间足够):
    1. alter system set undo_retention=28800; -- 设为8小时(根据业务最长查询时间调整)
    复制代码
  • 启用Undo保留Guarantee模式:
    1. alter tablespace undotbs1 retention guarantee;
    复制代码
  • 扩展Undo表空间或取消自动扩展限制:
    1. alter database datafile '/opt/oracle/oradata/undotbs1.dbf' resize 500M;
    2. alter database datafile '/opt/oracle/oradata/undotbs1.dbf' autoextend on next 100M;
    复制代码
  • 优化查询与事务:

    • 拆分长查询为多个短查询,减少一致性读窗口。
    • 大批量DELETE/UPDATE操作分批执行并分次提交。

  • 避免sqlldr直接加载:改用常规加载模式(direct=false),或加载后立即备份Undo数据。
Undo表空间过度扩展且无法收缩

现象

Undo表空间占用磁盘空间过大(如数十GB),即使无大事务也无法自动收缩,导致磁盘空间耗尽,触发ORA-1653(表空间无法扩展)。
核心成因


  • AUM模式特性:Oracle自动管理Undo表空间时,只动态扩展回滚段,不主动收缩已分配的空闲空间。
  • 大事务影响:曾执行大批量数据操作,导致回滚段过度扩展,后续无足够压力触发收缩。
  • 配置不当:Undo表空间启用自动扩展(autoextend on),且无最大大小限制。
排查步骤


  • 确认表空间占用情况:
    1. select tablespace_name, sum(bytes)/1024/1024/1024 as gb from dba_data_files group by tablespace_name having tablespace_name like 'UNDO%';
    复制代码
  • 检查回滚段状态(是否有超大回滚段):
    1. select usn, name, rssize/1024/1024/1024 as gb, shrinks from v$rollstat a, v$rollname b where a.usn=b.usn order by rssize desc;
    复制代码
  • 验证自动扩展配置:
    1. select file_name, autoextensible, maxbytes/1024/1024 as max_mb from dba_data_files where tablespace_name like 'UNDO%';
    复制代码
解决方案


  • 重建Undo表空间(推荐,彻底释放空间):
    1. -- 1. 创建新Undo表空间
    2. create undo tablespace undotbs2 datafile '/opt/oracle/oradata/undotbs2.dbf' size 100M autoextend on next 50M maxsize 1000M;
    3. -- 2. 切换至新表空间
    4. alter system set undo_tablespace=undotbs2 scope=both;
    5. -- 3. 等待旧表空间回滚段离线(状态变为OFFLINE)
    6. select usn, status from v$rollstat;
    7. -- 4. 删除旧表空间
    8. drop tablespace undotbs1 including contents;
    复制代码
  • 临时解决方案(不重建表空间):

    • 取消自动扩展:alter database datafile '/opt/oracle/oradata/undotbs1.dbf' autoextend off;
    • 手动收缩数据文件(需表空间有足够空闲):alter database datafile '/opt/oracle/oradata/undotbs1.dbf' resize 1000M;

  • 长期预防:

    • 初始配置合理的Undo表空间大小,避免无限制自动扩展。
    • 监控大事务,提前拆分执行。

回滚段损坏(ORA-00600 [4194])

现象

数据库启动失败或运行缓慢,告警日志提示ORA-00600: internal error code, arguments: [4194], [X], [Y],SMON进程持续尝试恢复回滚段,CPU占用过高。
核心成因


  • 异常关闭数据库:使用shutdown abort强制关闭,导致Undo段事务信息不一致。
  • Undo表空间损坏:存储介质故障、文件丢失导致回滚段数据损坏。
  • 回滚段过度使用:长时间未提交的大事务导致回滚段异常。
排查步骤


  • 查看告警日志定位损坏回滚段:
    1. tail -f $ORACLE_BASE/admin/$ORACLE_SID/bdump/alert_$ORACLE_SID.log
    复制代码
    日志中会显示“Undo Segment X Onlined”或“SMON: about to recover undo segment X”。
  • 确认回滚段状态:
    1. select segment_name, tablespace_name, status from dba_rollback_segs where status<>'ONLINE';
    复制代码
  • 检查Undo表空间文件完整性:
    1. select name, status from v$datafile where tablespace_name like 'UNDO%';
    复制代码
解决方案


  • 标记损坏回滚段并强制启动数据库:
    1. -- 1. 修改初始化参数文件(init<sid>.ora)
    2. _corrupted_rollback_segments='_SYSSMU11$','_SYSSMU12$' -- 填入告警日志中损坏的回滚段名称
    3. -- 2. 用修改后的参数文件启动数据库
    4. startup pfile=init<sid>.ora
    复制代码
  • 重建Undo表空间:
    1. -- 1. 创建新Undo表空间
    2. create undo tablespace undotbs_new datafile '/opt/oracle/oradata/undotbs_new.dbf' size 100M;
    3. -- 2. 切换表空间
    4. alter system set undo_tablespace=undotbs_new;
    5. -- 3. 删除损坏的旧表空间
    6. drop tablespace undotbs_old including contents;
    复制代码
  • 清理参数文件:
    1. -- 移除_corrupted_rollback_segments参数,生成新spfile
    2. create spfile from pfile;
    3. shutdown immediate;
    4. startup;
    复制代码
  • 数据一致性检查:
    启动后执行全库导出(exp/expdp),重建数据库并导入数据,避免残留不一致。
块清除相关性能问题

现象

事务提交后查询仍有延迟,AWR报告显示“consistent gets”过高,或出现短暂锁等待,跟踪文件显示大量“Block cleanout”记录。
核心成因


  • 延迟块清除:大批量操作后提交,数据块已写出到文件,需下次访问时清除ITL信息和锁标记。
  • 快速块清除限制:修改块数量超过Buffer Cache的10%,超出部分无法快速清除。
排查步骤


  • 查看块清除相关统计:
    1. select name, value from v$sysstat where name like '%cleanout%';
    复制代码
  • 启用10203事件跟踪块清除过程:
    1. alter system set event="10203 trace name context forever" scope=spfile;
    2. shutdown immediate;
    3. startup;
    复制代码
  • 分析数据块ITL状态:
    1. alter system dump datafile <file_id> block <block_id>; -- 转储疑似块,查看ITL信息
    复制代码
解决方案


  • 优化提交策略:

    • 大批量操作分批次提交,每次提交块数量不超过Buffer Cache的5%。
    • 提交后主动访问数据块(如执行全表扫描),触发快速清除。

  • 调整Buffer Cache大小:
    增大Buffer Cache,减少数据块频繁写出,提升快速清除比例。
  • 避免长时间未提交事务:
    及时提交或回滚事务,减少ITL槽占用和延迟清除压力。
闪回查询失败(ORA-00376/ORA-01466)

现象

执行闪回查询(as of scn/timestamp)时提示:

  • ORA-00376: file X cannot be read at this time(Undo表空间离线)
  • ORA-01466: unable to read data - table definition has changed(表结构变更)
核心成因


  • Undo数据丢失:Undo表空间离线、数据被覆盖或文件损坏。
  • 表结构变更:闪回时间点后表被修改(如添加字段、删除分区)。
  • SCN无效:指定的SCN超出Undo数据保留范围。
排查步骤


  • 检查Undo表空间状态:
    1. select tablespace_name, status from dba_tablespaces where tablespace_name like 'UNDO%';
    2. alter tablespace undotbs1 online; -- 若离线则启用
    复制代码
  • 验证SCN有效性:
    1. select dbms_flashback.get_system_change_number from dual; -- 当前SCN
    2. select first_change#, next_change# from v$archived_log; -- 归档日志中的SCN范围
    复制代码
  • 确认表结构变更记录:
    1. select object_name, operation, timestamp from dba_objects where object_name='EMP' and object_type='TABLE';
    复制代码
解决方案


  • 启用闪回数据归档(Oracle 11g+):
    1. -- 1. 创建归档表空间
    2. create tablespace fbra datafile size 200M segment space management auto;
    3. -- 2. 创建闪回归档区(保留1个月)
    4. create flashback archive dataarchive tablespace fbra retention 1 month;
    5. -- 3. 为表启用归档
    6. alter table emp flashback archive dataarchive;
    复制代码
  • 恢复Undo数据:
    若Undo表空间损坏,通过RMAN恢复或使用冷备份还原。
  • 调整闪回时间点:
    选择表结构未变更、SCN有效的时间点重新查询:
    1. select * from emp as of scn 12929941968; -- 替换为有效SCN
    复制代码
Undo参数配置不当

现象

Undo管理异常,如:

  • 无法切换Undo表空间,提示ORA-30019。
  • undo_retention设置不生效,Undo数据提前被覆盖。
  • 手动管理模式下无法创建回滚段。
核心成因


  • undo_management参数冲突:自动模式(AUTO)下执行手动管理操作(如指定回滚段)。
  • undo_suppress_errors参数设置错误:自动模式下屏蔽了不支持操作的报错,导致配置无效。
  • 参数未生效:修改动态参数后未重启数据库(部分参数需重启)。
排查步骤


  • 查看完整Undo参数配置:
    1. show parameter undo; -- 重点检查undo_management、undo_tablespace、undo_suppress_errors
    复制代码
  • 验证参数生效状态:
    1. select name, value, isdefault, issys_modifiable from v$parameter where name like 'undo%';
    复制代码
解决方案


  • 修正参数配置:
    1. -- 切换为自动管理模式
    2. alter system set undo_management=AUTO scope=spfile;
    3. -- 指定有效Undo表空间
    4. alter system set undo_tablespace=UNDOTBS1 scope=both;
    5. -- 禁用错误屏蔽(推荐)
    6. alter system set undo_suppress_errors=FALSE scope=both;
    复制代码
  • 重启数据库使参数生效:
    1. shutdown immediate;
    2. startup;
    复制代码

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册