Oracle RAC灾备环境UNDO表空间管理终极指南:解决备库修改难题与性能优化实战

问题1:ORACLE RAC的DG备库也是RAC,如何修改备库的UNDO默认表空间,直接alter 提示ORA-02097和ORA-01682

备库处于 MOUNT(或 READ ONLY WITH APPLY)状态,数据文件尚未写开,Oracle 怕你把 UNDO 指向一个"目前还不存在或没在线"的表空间,于是抛出

bash 复制代码
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-01682: unable to extend/allocate the undo segment in the specified undo tablespace

这两个错误说"现在不能改",并非表空间本身有问题。

RAC 环境下每个实例本来就应该使用自己独占的 UNDO 表空间,主库通常已经给每个 THREAD 配好,备库端只要数据文件存在、线程参数正确,不需要也不允许手动去改。

问题2:主库节点1将默认UNDO表空间改为了undotbs3,是不是主库已经同步给备库,备库重启就生效了?

是的,只要主库的修改已经同步到备库的控制文件和 SPFILE,备库重启后就会直接生效,不需要再手动做任何"ALTER SYSTEM"。

或者你也可以在备库修改

复制代码
alter system set undo_tablespace='UNDOTBS3' sid='abc1' scope=spfile;

具体分两种情况:

主库用 SCOPE=BOTH SID='xxx' 修改了本节点的 UNDO_TABLESPACE

修改会写进 redo,DG 恢复进程会把这条 ALTER SYSTEM 记录一起应用到备库的控制文件和 SPFILE。

备库此时处于 MOUNT 状态,参数虽然已写进 SPFILE,但 内存值并未生效(实例未打开)。

重启备库实例(或整个 RAC 节点)后,实例按 SPFILE 里的新值打开,新的 UNDO 表空间就被启用。

在备库节点只执行了 ALTER SYSTEM SET ... SCOPE=SPFILE SID='xxx'

同样只是把值写进 SPFILE,内存不变;必须重启该实例才能看到新值生效

参考文档

How to set the Undo_tablespace in PDB in Physical Standby RAC Database. (Doc ID 2726173.1)

问题3:如何手动释放UNDOTBS1表空间中的数据?

undo 表空间里的段(undo segment)完全由系统自管;

DBA 不能手工 drop/extent/释放其中的数据。

唯一能把 UNDOTBS1 真正"清空"或"释放"的方法只有:

新建一个 undo 表空间(例如 UNDOTBS3);

把实例切换到新表空间;

-- 在主库节点 1 上:

复制代码
CREATE UNDO TABLESPACE undotbs3
  DATAFILE '+DATA'
  SIZE 10G AUTOEXTEND ON NEXT 1G MAXSIZE 31G;

ALTER SYSTEM SET undo_tablespace='UNDOTBS3' SCOPE=BOTH SID='abc1';

表空间UNDOTBS3显示为空;

sql 复制代码
SELECT
seg.tablespace_name "Tablespace Name",
ts.bytes/1024/1024 "TS Size(MB)",
ue.status "UNDO Status",
count(*) "Used Extents",
round(sum(ue.bytes)/1024/1024, 2) "Used Size(MB)",
round(sum(ue.bytes)/ts.bytes*100, 2) "Used Rate(%)"
FROM dba_segments seg, DBA_UNDO_EXTENTS ue,
(SELECT tablespace_name, sum(bytes) bytes
   FROM dba_data_files GROUP BY tablespace_name) ts
    WHERE ue.segment_NAME=seg.segment_NAME and seg.tablespace_name=ts.tablespace_name
    GROUP BY seg.tablespace_name, ts.bytes, ue.status ORDER BY seg.tablespace_name;

这种就不能删表空间UNDOTBS3

备库再用UNDOTBS1的时候千万别删除主库的UNDOTB1,否则DG备库会报错的,导致备库不能同步。

备库生效

若主库用了 SCOPE=BOTH,备库 SPFILE 已更新,只需

在备库节点 1

srvctl stop instance -db orcldg -node orcldg1

srvctl start instance -db orcldg -node orcldg1

最后 drop 旧表空间(让 Oracle 自动回收数据文件)

sql 复制代码
DROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;

Oracle的gv$undostat字段解释

在Oracle数据库中,GV$UNDOSTAT 视图非常重要,它提供了整个数据库集群(RAC环境)中所有实例的UNDO表空间使用情况和事务活动的统计信息,主要服务于自动Undo管理(AUM)。

下面是 GV$UNDOSTAT 核心字段的详细解释,为了帮助你快速了解,我将它们分成了几个类别:

📊 核心字段详解

类别 字段名 说明
基本信息 INST_ID 实例编号。在RAC环境中,标识数据来源于哪个实例。
BEGIN_TIME 统计时间段的开始时间
END_TIME 统计时间段的结束时间 。默认每10分钟为一个统计间隔。
UNDOTSN 在此时间段内活动的UNDO表空间的时间戳编号
空间使用 UNDOBLKS 在此时间间隔内,事务消耗的UNDO块总数。这是衡量UNDO空间生成速率的核心指标。
ACTIVEBLKS 当前活动事务所占用的UNDO块数(这些事务尚未提交或回滚)。
EXPIREDBLKS 在此时间间隔内,已过期的UNDO块数 (事务已提交,且保留时间超过UNDO_RETENTION设置)。这些空间可被新事务重用。
UNEXPIREDBLKS 在此时间间隔内,未过期的UNDO块数 (事务已提交,但保留时间未超过UNDO_RETENTION)。这些空间应被保留用于一致性读。
事务与查询 TXNCOUNT 在时间间隔内执行的事务总数
MAXCONCURRENCY 在时间间隔内,同时执行的最大并发事务数
MAXQUERYLEN 在此时间间隔内,出现的最长查询的执行时间(秒)。这是诊断ORA-01555错误的关键字段。
空间压力指标 EXPSTEALCNT 为了满足新事务,系统窃取已过期(Expired)的UNDO扩展段的次数。这是正常且期望的行为。
UNXPSTEALCNT 为了满足新事务,系统窃取未过期(Unexpired)的UNDO扩展段的次数非零值是一个警告信号,表明UNDO空间可能不足,Oracle正在强制重用本应保留的空间。
SSOLDERRCNT 在此时间间隔内,发生的 ORA-01555: snapshot too old(快照过旧)错误的数量。任何非零值都意味着需要调整UNDO配置。
NOSPACEERRCNT 在此时间间隔内,因无法在UNDO表空间中分配空间而发生的错误数量非零值是一个严重警报,表明UNDO表空间严重不足,必须立即处理。
优化信息 TUNED_UNDORETENTION Oracle系统自动为您调整的UNDO保留时间(秒)。在AUM模式下,Oracle可能根据负载和最长查询自动调整实际保留时间。

💡 主要应用场景

了解这些字段后,你可以利用 GV$UNDOSTAT 视图完成以下几项重要工作:

  1. 诊断和预防 ORA-01555 错误

    这是 GV$UNDOSTAT 最经典的应用。你可以通过检查 SSOLDERRCNT 字段来判断是否发生过此错误,并通过比较 MAXQUERYLENTUNED_UNDORETENTION 来分析错误原因。

  2. 评估和规划 UNDO 表空间大小

    通过观察 UNDOBLKS 的历史峰值,并结合 UNDO_RETENTION 参数,可以估算UNDO表空间的合理大小,避免空间不足或浪费。

  3. 监控 UNDO 表空间压力

    关注 UNXPSTEALCNT(窃取未过期块次数)和 NOSPACEERRCNT(空间不足错误计数)等指标。如果这些值非零或持续增长,通常意味着UNDO表空间面临压力,需要及时干预。

一个简单的查询示例

如果你想查看过去一段时间内每个实例是否发生过 ORA-01555 错误,可以执行如下SQL:

sql 复制代码
SELECT
    inst_id,
    TO_CHAR(begin_time, 'YYYY-MM-DD HH24:MI') AS begin_time,
    TO_CHAR(end_time, 'YYYY-MM-DD HH24:MI') AS end_time,
    maxquerylen,
    tuned_undoretention,
    ssolderrcnt
FROM
    gv$undostat
WHERE
    ssolderrcnt > 0
ORDER BY
    inst_id, begin_time DESC;
相关推荐
姚远Oracle ACE2 小时前
Oracle AWR案例分析:精准定位SQL执行计划切换的时间点
数据库·sql·oracle
凉栀お_3 小时前
MySQL第四次作业(索引、视图)
数据库·mysql
睡前要喝豆奶粉3 小时前
.NET Core Web API中数据库相关配置
数据库·c#·.netcore
大G的笔记本3 小时前
高频 Redis 面试题答案解析
数据库·redis·缓存
万事大吉CC4 小时前
SQL语法基础教程
数据库·oracle
betazhou4 小时前
Oracle dgbroker常规命令管理简介
数据库·oracle·adg·dbbroker
山河亦问安4 小时前
Spring Boot异步接口性能优化:从单线程到高并发的优化历程
spring boot·后端·性能优化
海边夕阳20065 小时前
PostgreSQL性能调优:解决表膨胀、索引碎片和无效索引问题
数据库·经验分享·postgresql·性能优化
一 乐5 小时前
个人理财系统|基于java+小程序+APP的个人理财系统设计与实现(源码+数据库+文档)
java·前端·数据库·vue.js·后端·小程序