1. undo的概述和作用
在Oracle数据库中,undo是一种用于实现事务回滚和读一致性的机制。当一个事务对数据库进行修改时,Oracle会将修改前的数据保存到undo表空间中,以便在需要回滚事务或者读取一致性数据时使用。
undo的作用主要有以下几个方面:
实现事务回滚:当一个事务需要回滚时,Oracle会使用undo中保存的修改前的数据来还原数据库到事务开始之前的状态。
实现读一致性:当一个事务正在执行时,其他事务需要读取数据时,Oracle会使用undo中保存的修改前的数据来保证读取的数据是一致的。
支持闪回查询:闪回查询是一种可以在不恢复整个数据库的情况下,快速还原数据库到某个时间点的查询方式。Oracle会使用undo中保存的数据来实现闪回查询。
支持多版本并发控制:多版本并发控制是一种可以让多个事务同时访问数据库而不会相互干扰的机制。Oracle会使用undo中保存的数据来实现多版本并发控制。
总之,undo是Oracle数据库中非常重要的一个机制,它可以实现事务回滚、读一致性、闪回查询和多版本并发控制等功能。在实际应用中,需要根据实际情况来配置undo表空间的大小和性能,以保证数据库的稳定性和性能。
对数据执行修改操作时(DML修改buffer cache里的数据块),数据库会生成undo 信息(对当前的块的旧镜像信息做个保存,保存的块就是undo块),一旦执行的事务或语句由于某种原因失败,或者发出一条ROLLBACK 语句请求回滚,就可以利用undo信息将数据放回到修改前的样子.undo 信息存储在一组特殊的段中,这称为undo 段(undo segment).
[oracle@oracle-db-19c ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Mon Apr 3 08:05:51 2023
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
SQL> show user
USER is "SYS"
SQL> set pagesize 200 linesize 200
SQL>
SQL>
SQL> col tablespace_name format a20
SQL> col status format a20
SQL> select segment_name, tablespace_name, status, block_id, file_id from dba_rollback_segs;
SEGMENT_NAME TABLESPACE_NAME STATUS BLOCK_ID FILE_ID
-------------------- -------------------- -------------------- ---------- ----------
SYSTEM SYSTEM ONLINE 128 1
_SYSSMU1_1261223759$ UNDOTBS1 ONLINE 128 4
_SYSSMU2_27624015$ UNDOTBS1 ONLINE 144 4
_SYSSMU3_2421748942$ UNDOTBS1 ONLINE 160 4
_SYSSMU4_625702278$ UNDOTBS1 ONLINE 176 4
_SYSSMU5_2101348960$ UNDOTBS1 ONLINE 192 4
_SYSSMU6_813816332$ UNDOTBS1 ONLINE 208 4
_SYSSMU7_2329891355$ UNDOTBS1 ONLINE 224 4
_SYSSMU8_399776867$ UNDOTBS1 ONLINE 240 4
_SYSSMU9_1692468413$ UNDOTBS1 ONLINE 256 4
_SYSSMU10_930580995$ UNDOTBS1 ONLINE 272 4
11 rows selected.
SQL>
使用undo tablespace 存放从datafiles 读出的数据块的前镜像,提供以下四种情况所需要的信息.
1).回滚事务 :rollback2).读一致性 :正在做DML操作的数据块,事务结束前,其他用户读undo里面的数据前镜像
3).实例恢复 :instance recover(undo -------->rollback)
4).闪回技术 :flashback query、flashback table等
-- Manual :roll segment(淘汰)
-- Auto :undo tablespace (init parameter :undo_management=auto)
SQL>
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL>
-- UNDOTBS1的10个段,10个大表,系统默认10个
SQL>
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> select * from v$rollname;
USN NAME CON_ID
---------- ------------------------------------------------------------------------------------------ ----------
0 SYSTEM 1
1 _SYSSMU1_1261223759$ 1
2 _SYSSMU2_27624015$ 1
3 _SYSSMU3_2421748942$ 1
4 _SYSSMU4_625702278$ 1
5 _SYSSMU5_2101348960$ 1
6 _SYSSMU6_813816332$ 1
7 _SYSSMU7_2329891355$ 1
8 _SYSSMU8_399776867$ 1
9 _SYSSMU9_1692468413$ 1
10 _SYSSMU10_930580995$ 1
11 rows selected.
SQL>
1).可以建立多个undo tablespace(缺省一个),但一个时刻只有一个处于active
2).处于active状态的undo tablespace 不能offline 和 drop
SQL>
SQL> select tablespace_name, status, contents from dba_tablespaces;
TABLESPACE_NAME STATUS CONTENTS
-------------------- -------------------- ---------------------------------------------------------------
SYSTEM ONLINE PERMANENT
SYSAUX ONLINE PERMANENT
UNDOTBS1 ONLINE UNDO
TEMP ONLINE TEMPORARY
USERS ONLINE PERMANENT
TEMP02 ONLINE TEMPORARY
6 rows selected.
SQL> SELECT file_name FROM dba_data_files WHERE tablespace_name = 'UNDOTBS1';
FILE_NAME
----------------------------------------
/u02/oradata/CDB1/undotbs01.dbf
SQL>
SQL> CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE '/u02/oradata/CDB1/undotbs02.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED;
Tablespace created.
SQL> select tablespace_name, status, contents from dba_tablespaces;
TABLESPACE_NAME STATUS CONTENTS
-------------------- -------------------- ---------------------------------------------------------------
SYSTEM ONLINE PERMANENT
SYSAUX ONLINE PERMANENT
UNDOTBS1 ONLINE UNDO
TEMP ONLINE TEMPORARY
USERS ONLINE PERMANENT
UNDOTBS2 ONLINE UNDO
TEMP02 ONLINE TEMPORARY
7 rows selected.
SQL>
SQL>
SQL> -- memory动态修改
SQL> alter system set undo_tablespace=undotbs2;
System altered.
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2
SQL> select * from v$rollname;
USN NAME CON_ID
---------- ------------------------------------------------------------------------------------------ ----------
0 SYSTEM 1
11 _SYSSMU11_4263211716$ 1
12 _SYSSMU12_4060389560$ 1
13 _SYSSMU13_1614986827$ 1
14 _SYSSMU14_2442247673$ 1
15 _SYSSMU15_3040896203$ 1
16 _SYSSMU16_2151182073$ 1
17 _SYSSMU17_1110798109$ 1
18 _SYSSMU18_2692559868$ 1
19 _SYSSMU19_79700264$ 1
20 _SYSSMU20_1318461731$ 1
21 _SYSSMU21_2969415316$ 1
22 _SYSSMU22_3147182066$ 1
23 _SYSSMU23_208810255$ 1
14 rows selected.
SQL> alter system set undo_tablespace=undotbs1;
System altered.
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
SQL> select * from v$rollname;
USN NAME CON_ID
---------- ------------------------------------------------------------------------------------------ ----------
0 SYSTEM 1
1 _SYSSMU1_1261223759$ 1
2 _SYSSMU2_27624015$ 1
3 _SYSSMU3_2421748942$ 1
4 _SYSSMU4_625702278$ 1
5 _SYSSMU5_2101348960$ 1
6 _SYSSMU6_813816332$ 1
7 _SYSSMU7_2329891355$ 1
8 _SYSSMU8_399776867$ 1
9 _SYSSMU9_1692468413$ 1
10 _SYSSMU10_930580995$ 1
11 rows selected.
SQL>
SQL>
SQL> drop tablespace undotbs2 including contents and datafiles;
Tablespace dropped.
SQL> -- 动态视图查看
SQL> select * from v$tablespace;
TS# NAME INCLUDED_ BIGFILE FLASHBACK ENCRYPT_I CON_ID
---------- ------------------------------------------------------------------------------------------ --------- --------- --------- --------- ----------
1 SYSAUX YES NO YES 1
0 SYSTEM YES NO YES 1
2 UNDOTBS1 YES NO YES 1
4 USERS YES NO YES 1
3 TEMP NO NO YES 1
0 SYSTEM YES NO YES 2
1 SYSAUX YES NO YES 2
2 UNDOTBS1 YES NO YES 2
3 TEMP NO NO YES 2
0 SYSTEM YES NO YES 3
1 SYSAUX YES NO YES 3
2 UNDOTBS1 YES NO YES 3
3 TEMP NO NO YES 3
5 USERS YES NO YES 3
0 SYSTEM YES NO YES 4
1 SYSAUX YES NO YES 4
2 UNDOTBS1 YES NO YES 4
3 TEMP NO NO YES 4
5 USERS YES NO YES 4
14 TEST_TBS YES NO YES 3
15 PANDAS_TBS YES NO YES 3
6 TEMP02 NO NO YES 3
6 TEMP02 NO NO YES 1
7 DATA01 YES NO YES 3
8 TBS_MAXWELL YES NO YES 3
9 TEMP_MAXWELL NO NO YES 3
10 UNDOTBS2 YES NO YES 3
11 TBS_TOOLS YES NO YES 3
5 USERS YES NO YES 12
13 RMAN1 YES NO YES 3
0 SYSTEM YES NO YES 12
1 SYSAUX YES NO YES 12
2 UNDOTBS1 YES NO YES 12
3 TEMP NO NO YES 12
34 rows selected.
SQL>
在Oracle数据库中,undo数据块有以下4种状态:
Dirty状态:表示该undo数据块中的数据已经被修改,但是还没有被写入磁盘。当事务提交时,Oracle会将Dirty状态的undo数据块写入磁盘。
Unexpired状态:表示该undo数据块中的数据还没有过期,可以用于读取一致性数据或者回滚事务。当undo数据块中的所有事务都已经提交或者回滚时,该undo数据块就会变为Unexpired状态。
Expired状态:表示该undo数据块中的数据已经过期,不能再用于读取一致性数据或者回滚事务。当undo数据块中的某个事务占用的undo数据块已经达到了undo_retention参数设置的时间限制时,该undo数据块就会变为Expired状态。
Stale状态:表示该undo数据块中的数据已经被覆盖,不能再用于读取一致性数据或者回滚事务。当undo数据块中的数据被新的事务修改时,该undo数据块就会变为Stale状态。
需要注意的是,undo数据块的状态会随着事务的提交、回滚和过期而不断变化。在实际应用中,需要根据实际情况来配置undo表空间的大小和性能,以保证数据库的稳定性和性能。同时,还需要定期监控undo表空间的使用情况,以及进行undo表空间的维护和优化。
undo retention参数和undo autoextend on特性
*undo retention参数规定了unexpired commit数据的保留期,*它是保证一致性读和大多数闪回技术成功的关键,
将undo tbs设为autoextend on, 这是DBCA创建数据库时的缺省设置, *这一个特性将在 undo**空间不足时优先扩展新的空间,*其次才是覆盖unexpired commit.
NOTE: 如果要减少ORA_O1555错误(snapshot too old),考虑延长undo retention或使能 undo autoextend on.
Undo Retention Period是Oracle数据库中一个重要的参数,用于控制undo数据的保留时间。当一个事务对数据库进行修改时,Oracle会将修改前的数据保存到undo表空间中,以便在需要回滚事务或者读取一致性数据时使用。Undo Retention Period参数指定了undo数据在undo表空间中保留的时间,超过这个时间的undo数据将被自动删除。
Undo Retention Period参数的默认值是900秒(15分钟),可以通过以下SQL语句查询和修改:
查询Undo Retention Period参数的值:
SQL> col value format a20
SQL> SELECT value FROM v$parameter WHERE name = 'undo_retention';
VALUE
--------------------
900
SQL>
修改Undo Retention Period参数的值:
SQL> ALTER SYSTEM SET undo_retention = 1800;
System altered.
SQL> SELECT value FROM v$parameter WHERE name = 'undo_retention';
VALUE
--------------------
1800
SQL>
上述语句将Undo Retention Period参数的值修改为1800秒(30分钟)。
需要注意的是,修改Undo Retention Period参数的值可能会影响数据库的性能和稳定性。如果Undo Retention Period参数设置得太小,可能会导致undo数据被过早地删除,从而导致事务回滚失败或者读取不一致的数据。如果Undo Retention Period参数设置得太大,可能会导致undo表空间的空间不足,从而导致事务失败。因此,在修改Undo Retention Period参数的值时,需要根据实际情况进行调整,并进行充分的测试和验证。
Retention Guarantee是Oracle数据库中一个可选的参数,用于保证undo数据在undo表空间中的最小保留时间。当Retention Guarantee参数设置为TRUE时,Oracle会保证undo数据在undo表空间中的最小保留时间,即使undo表空间空间不足或者undo数据被过早地删除也不会影响保留时间。当Retention Guarantee参数设置为FALSE时,Oracle会尽可能地保留undo数据,但是不能保证最小保留时间。
Retention Guarantee参数的默认值是FALSE,可以通过以下SQL语句查询和修改:
查询Retention Guarantee参数的值:
SQL> SELECT value FROM v$parameter WHERE name = 'undo_retention';
VALUE
--------------------
900
SQL>
修改Retention Guarantee参数的值:
ALTER SYSTEM SET undo_retention = 1800 RETENTION GUARANTEE;
该语句将Retention Guarantee参数的值修改为1800秒(30分钟),并启用保证最小保留时间的功能。
需要注意的是,启用Retention Guarantee参数可能会导致undo表空间的空间不足,从而导致事务失败。因此,在启用Retention Guarantee参数时,需要确保undo表空间有足够的空间,并进行充分的测试和验证。同时,还需要定期监控undo表空间的使用情况,以及进行undo表空间的维护和优化。
通过dba_tablespaces视图, 缺省配置下undo retention是noguarantee.
SQL> select tablespace_name, status, contents, retention from dba_tablespaces;
TABLESPACE_NAME STATUS CONTENTS RETENTION
-------------------- -------------------- --------------------------------------------------------------- ---------------------------------
SYSTEM ONLINE PERMANENT NOT APPLY
SYSAUX ONLINE PERMANENT NOT APPLY
UNDOTBS1 ONLINE UNDO NOGUARANTEE
TEMP ONLINE TEMPORARY NOT APPLY
USERS ONLINE PERMANENT NOT APPLY
TEMP02 ONLINE TEMPORARY NOT APPLY
6 rows selected.
SQL>
在使用create database、create undo tablespace建立时开启,或使用alter tablespace修改retention guarantee选项;
SQL>
SQL> -- 保证在retention期间不允许被覆盖
SQL> show user;
USER is "SYS"
SQL> show con_name;
CON_NAME
------------------------------
CDB$ROOT
SQL> alter tablespace UNDOTBS1 retention guarantee;
Tablespace altered.
SQL> select tablespace_name,status ,contents,retention from dba_tablespaces;
TABLESPACE_NAME STATUS CONTENTS RETENTION
-------------------- -------------------- --------------------------------------------------------------- ---------------------------------
SYSTEM ONLINE PERMANENT NOT APPLY
SYSAUX ONLINE PERMANENT NOT APPLY
UNDOTBS1 ONLINE UNDO GUARANTEE
TEMP ONLINE TEMPORARY NOT APPLY
USERS ONLINE PERMANENT NOT APPLY
TEMP02 ONLINE TEMPORARY NOT APPLY
6 rows selected.
SQL>
SQL> alter tablespace undotbs1 retention noguarantee;
Tablespace altered.
SQL> select tablespace_name,status ,contents,retention from dba_tablespaces;
TABLESPACE_NAME STATUS CONTENTS RETENTION
-------------------- -------------------- --------------------------------------------------------------- ---------------------------------
SYSTEM ONLINE PERMANENT NOT APPLY
SYSAUX ONLINE PERMANENT NOT APPLY
UNDOTBS1 ONLINE UNDO NOGUARANTEE
TEMP ONLINE TEMPORARY NOT APPLY
USERS ONLINE PERMANENT NOT APPLY
TEMP02 ONLINE TEMPORARY NOT APPLY
6 rows selected.
SQL>
综合以上两点所述,针对undo_retention这个参数,个人的理解如下:
1).undo_retention只是一个预期结果,数据库会尽量达到的这个目标,但实际的结果可能优于预期(撤销空间足够充足),也可能低于预期(撤销空间不足);
2).当撤销 TBS充足时,所有的撤销数据都被保留在撤销空间内.已提交的撤销数据只会被标记为"过期" (并不删除).在空间不足时,它们才可以被新事务的撤销数据所覆盖,未提交的事务被标记为"未过期";
3).当撤销 TBS不足时,首先去覆盖标记为”过期”的撤销数据,如果此时还是空间不足,新的事务还是会覆盖未过期的撤销数据的,毕竟新事务不可能一直等待旧事务的提交或回滚完成后才发生;
4).如果在撤销 TBS上指定了retention guarantee,在撤销空间不足且旧的事务的撤销数据未过期时,将会由于无法分配撤销空间而导致新的事务的执行失败;
这个属性只对已commit的undo状态有效
1).v$session 查看用户建立的session
2).v$transaction 当前的事务
3).v$rollname undo段的名称
4).v$rollstat undo段的状态
5).dba_rollback_segs 数据字典里记录的undo段状态
一般来说,一个session只能对应一个事务,建立了session未必有事务,只有事务处于活动状态时,v$transaction才能看到这个事务.换句话说,如果看到了事务(在 v$transaction 里),那一定有个session和它对应,将两个视图里连在一起,信息看得更为清楚.
SQL> col username format a20
SQL> select username,sid,serial# from v$session where username is not null;
USERNAME SID SERIAL#
-------------------- ---------- ----------
SYS 2 26630
SYS 257 24339
SCOTT 260 15876
SQL> show user;
USER is "SYS"
SQL> show con_name;
CON_NAME
------------------------------
PDB1
SQL>
SQL> show user;
USER is "SCOTT"
SQL> create table emp1 as select * from emp;
Table created.
SQL> select * from emp1;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ------------------------------ --------------------------- ---------- --------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 24-JAN-87 3000 20
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 02-APR-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10
7839 KING PRESIDENT 8000 17-NOV-81 5000 0 10
14 rows selected.
SQL> update emp1 set comm=800 where empno=7788;
1 row updated.
SQL>
SQL> select a.sid,a.serial#,a.username,b.xidusn,xidslot,b.ubablk,b.status from v$session a,v$transaction b where a.saddr=b.ses_addr;
SID SERIAL# USERNAME XIDUSN XIDSLOT UBABLK STATUS
--- ------- -------- ------ ------- ------ -------
23 50042 SCOTT 20 20 274 ACTIVE
-- 两表联查
-- sid和serial#在v$session里
-- 在v$transaction里:
-- XIDUSN是undo segment的id,
-- XIDSLOT是事务槽的id,
-- UBABLK是undo块号
-- 对照上面看,下面语句显示出_SYSSMU20是一个活动段, 与XIDUSN=20吻合, 说明这个段被读进buffer了.
SQL> select a.usn,b.name,a.xacts from v$rollstat a, v$rollname b where a.usn=b.usn;
USN NAME CON_ID
--- --------------------- -------
0 SYSTEM 0
11 _SYSSMU11_4042378425$ 0
12 _SYSSMU12_2010754074$ 0
13 _SYSSMU13_3885018169$ 0
14 _SYSSMU14_2215206726$ 0
15 _SYSSMU15_2246797103$ 0
16 _SYSSMU16_1518052737$ 0
17 _SYSSMU17_1675921924$ 0
18 _SYSSMU18_2474130580$ 0
19 _SYSSMU19_193690114$ 0
20 _SYSSMU20_118432001$ 1
21 _SYSSMU21_1311937374$ 0
22 _SYSSMU22_1028642511$ 0
-- 说明上面的update操作用了13张表里的第20张表
默认system TBS会有一个单独的 undo segment(usn为 0).其他 TBS的事务不能使用它.
缺省下undo tablespace 会被分配10个undo segment,理论上一个段可以有多个事务,但Oracle的策略并不情愿如此,实验表明,对应并发的事务,通常每个事务会分配一个UNDO 段,也就是说如果这10个段不够,Oracle会自动再增加段.
当数据库启动时,如果碰到undo数据文件损坏或不同步,可以将其offline, 即只有一个系统 TBS(system)的undo也能进入系统,使数据字典得以维护,但不能对其他 TBS做DML操作.
数据库open下undo损坏和修复
如果数据库打开的情况下,当前undo坏掉的话,比如现在UNDOTBS2出现了介质损坏,那么数据库就不能继续DML操作了.如果这时UNDOTBS2 TBS上还有active状态的事务(未提交),Oracle会将其下的所有段(10个段)都标志为NEEDS RECOVERY,这时有备份可以恢复这个UNDOTBS2,但如果没有备份,你需要用新建的UNDO替代损坏的UNDO,那么损坏UNDO上的未提交事务也将丢弃.但Oracle没有提供自动解决NEEDS RECOVERY的机制,如果你想删除这个损坏的UNDO TBS,必须另做处理(需要系统择时重启),我们模拟一下这种情况:
[oracle@oracle-db-19c CDB1]$ pwd
/u02/oradata/CDB1
[oracle@oracle-db-19c CDB1]$ ll undo*
-rw-r-----. 1 oracle oinstall 382738432 Apr 3 09:18 undotbs01.dbf
[oracle@oracle-db-19c CDB1]$ mv undotbs01.dbf undotbs01.dbf.bkp
[oracle@oracle-db-19c CDB1]$ ll undo*
-rw-r-----. 1 oracle oinstall 382738432 Apr 3 09:19 undotbs01.dbf.bkp
[oracle@oracle-db-19c CDB1]$
SQL> alter system checkpoint;
-- cmd端再做update 语句时会报错
SQL> update emp1 set sal=1000 where empno=7902;
ORA-01116: 打开数据库文件 3 时出错
ORA-01110: 数据文件 8: '/u01/app/oracle/oradata/orcl/undotbs02.dbf'
ORA-27041: 无法打开文件
SQL> shutdown immediate
SQL> startup
ORACLE instance started.
Total System Global Area 2466250752 bytes
Fixed Size 2927384 bytes
Variable Size 654312680 bytes
Database Buffers 1795162112 bytes
Redo Buffers 13848576 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 8 - see DBWR trace file
ORA-01110: data file 8: '/u01/app/oracle/oradata/orcl/undotbs02.dbf'
数据库open之前要检查所记录SCN和datafile heaer记录的SCN是否一致;一致就正常打开库,不一致需要做media recover.
SQL> startup force mount
SQL> startup mount
SQL> select file#,checkpoint_change# from v$datafile;
FILE# CHECKPOINT_CHANGE#
------ ----------------------
1 8476730
2 8476730
3 8476730
5 8476730
6 8476730
7 8476730
8 8476730
SQL> select file#,checkpoint_change# from v$datafile_header;
FILE# CHECKPOINT_CHANGE#
------ ----------------------
1 8476730
2 8476730
3 8476730
5 8476730
6 8476730
7 8476730
8 0
SQL> alter database datafile 8 offline;
Database altered.
SQL> alter database open;
Database altered.
SQL> select * from v$rollname;
USN NAME CON_ID
--- ------- ---------
0 SYSTEM 0
-- 这个静态视图可以列出所有(online或offline)UNDO段信息
SQL> select segment_name,status from dba_rollback_segs;
SEGMENT_NAME STATUS
-------------------- -------------
SYSTEM ONLINE
_SYSSMU22_1028642511$ NEEDS RECOVERY
_SYSSMU21_1311937374$ NEEDS RECOVERY
_SYSSMU20_118432001$ NEEDS RECOVERY
_SYSSMU19_193690114$ NEEDS RECOVERY
_SYSSMU18_2474130580$ NEEDS RECOVERY
_SYSSMU17_1675921924$ NEEDS RECOVERY
_SYSSMU16_1518052737$ NEEDS RECOVERY
_SYSSMU15_2246797103$ NEEDS RECOVERY
_SYSSMU14_2215206726$ NEEDS RECOVERY
_SYSSMU13_3885018169$ NEEDS RECOVERY
_SYSSMU12_2010754074$ NEEDS RECOVERY
_SYSSMU11_4042378425$ NEEDS RECOVERY
-- DML依旧无法操作
SQL> create undo tablespace undotbs1 datafile '/u01/app/oracle/oradata/orcl/undotbs01.dbf' size 100m autoextend on;
Tablespace created.
SQL> select * from v$tablespace;
TS# NAME INC BIG FLA ENC CON_ID
--- ------- --- --- --- --- ------
1 SYSAUX YES NO YES 0
0 SYSTEM YES NO YES 0
2 UNDOTBS1YES NO YES 0 -- 需要激活
4 USERS YES NO YES 0
3 TEMP NO NO YES 0
6 EXAMPLE YES NO YES 0
5 UNDOTBS2YES NO YES 0 -- 文件已经被改名
SQL> select * from v$rollname;
USN NAME CON_ID
--- ------- ---------
0 SYSTEM 0
SQL> alter system set undo_tablespace=UNDOTBS1;
SQL> show parameter undo
NAME TYPE VALUE
------------------ ------- ---------
temp_undo_enabled boolean FALSE
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
注意: 此时原有活动事务的信息(未提交)可能仍然保存在UNDOTBS2, 已经没有恢复的必要了.
先删掉UNDOTBS2,否则无法使用UNDOTBS1
12.11.1 删除报错分析
SQL> drop tablespace undotbs2 including contents and datafiles;
drop tablespace undotbs2 including contents and datafiles
*
ERROR at line 1:
ORA-01548: active rollback segment '_SYSSMU11_4042378425$' found, terminate dropping tablespace
-- ORA-01548: 已找到活动回退段 '_SYSSMU11_4042378425$', 终止删除 TBS
-- 无法删除UNDOTBS2是因为undotbs2中有事务,Oracle把其下的所有段都标志成 NEEDS RECOVERY了,再查看一下相关的数据字典:
SQL> select segment_name,status from dba_rollback_segs;
SEGMENT_NAME STATUS
-------------------- ---------------
SYSTEM ONLINE
_SYSSMU24_1145560925$ ONLINE
_SYSSMU23_497753519$ ONLINE
_SYSSMU10_3531180387$ ONLINE
_SYSSMU9_2948221526$ ONLINE
_SYSSMU8_77629217$ ONLINE
_SYSSMU7_4210038832$ ONLINE
_SYSSMU6_2365516946$ ONLINE
_SYSSMU5_42966806$ ONLINE
_SYSSMU4_2369906140$ ONLINE
_SYSSMU3_3546637655$ ONLINE
_SYSSMU2_3335685343$ ONLINE
_SYSSMU1_1652837430$ ONLINE
_SYSSMU22_1028642511$ NEEDS RECOVERY
_SYSSMU21_1311937374$ NEEDS RECOVERY
_SYSSMU20_118432001$ NEEDS RECOVERY
_SYSSMU19_193690114$ NEEDS RECOVERY
_SYSSMU18_2474130580$ NEEDS RECOVERY
_SYSSMU17_1675921924$ NEEDS RECOVERY
_SYSSMU16_1518052737$ NEEDS RECOVERY
_SYSSMU15_2246797103$ NEEDS RECOVERY
_SYSSMU14_2215206726$ NEEDS RECOVERY
_SYSSMU13_3885018169$ NEEDS RECOVERY
_SYSSMU12_2010754074$ NEEDS RECOVERY
_SYSSMU11_4042378425$ NEEDS RECOVERY
25 rows selected.
解决有两个办法:
12.11.2 方法一、使用备份恢复
12.11.3 方法二、使用 oracle 提供的隐含参数_CORRUPTED_ROLLBACK_SEGMENTS
12.11.3.1 用spfile建立静态参数文件
SQL> create pfile from spfile;
[oracle@oracle-db-19c CDB1]$ cd $ORACLE_HOME/dbs
[oracle@oracle-db-19c dbs]$ pwd
/u01/app/oracle/product/19.3.0/dbhome_1/dbs
[oracle@oracle-db-19c dbs]$ ls -ltr
total 116964
-rw-r--r--. 1 oracle oinstall 3079 May 14 2015 init.ora.bkp
-rw-r--r--. 1 oracle oinstall 3079 May 14 2015 init.ora
-rw-r-----. 1 oracle oinstall 24 Nov 2 15:03 lkCDB1
-rw-r-----. 1 oracle oinstall 3584 Nov 27 16:55 spfilecdb1.ora.bkp
-rw-r-----. 1 oracle oinstall 3072 Feb 1 13:41 orapwcdb1
-rw-r--r--. 1 oracle oinstall 1188 Feb 2 19:19 initcdb1.ora.bkp
-rw-r--r--. 1 oracle oinstall 1188 Feb 2 19:19 initcdb1.ora
-rw-r-----. 1 oracle oinstall 14018048 Apr 2 15:48 arch1_400_1119711914.dbf
-rw-r-----. 1 oracle oinstall 34015232 Apr 2 16:00 arch1_401_1119711914.dbf
-rw-rw----. 1 oracle oinstall 1544 Apr 2 16:08 hc_cdb1.dat
-rw-r-----. 1 oracle oinstall 1843712 Apr 2 16:08 arch1_402_1119711914.dbf
-rw-r-----. 1 oracle oinstall 31752704 Apr 3 08:03 arch1_403_1119711914.dbf
-rw-r-----. 1 oracle oinstall 18989056 Apr 3 08:31 snapcf_cdb1.f
-rw-r-----. 1 oracle oinstall 19103744 Apr 3 08:31 c-1093429351-20230403-00
-rw-r-----. 1 oracle oinstall 3584 Apr 3 08:38 spfilecdb1.ora
[oracle@oracle-db-19c dbs]$
12.11.3.2 编辑静态参数文件
[oracle@oracle-db-19cdbs]$ vi initcdb1.ora
# 在静态参数文件里第一行插入以下10个needs recovery段的内容
_CORRUPTED_ROLLBACK_SEGMENTS=
(_SYSSMU22_1028642511$,
_SYSSMU21_1311937374$,
_SYSSMU20_118432001$,
_SYSSMU19_193690114$,
_SYSSMU18_2474130580$,
_SYSSMU17_1675921924$,
_SYSSMU16_1518052737$,
_SYSSMU15_2246797103$,
_SYSSMU14_2215206726$,
_SYSSMU13_3885018169$,
_SYSSMU12_2010754074$,
_SYSSMU11_4042378425$)
12.11.3.3 使静态参数文件启动数据库
SQL> shutdown immediate
SQL> startup pfile=$ORACLE_HOME/dbs/initorcl.ora
12.11.3.4 删除回退段
......
SQL>
drop rollback segment "_SYSSMU22_1028642511$";
drop rollback segment "_SYSSMU21_1311937374$";
drop rollback segment "_SYSSMU20_118432001$";
drop rollback segment "_SYSSMU19_193690114$";
drop rollback segment "_SYSSMU18_2474130580$";
drop rollback segment "_SYSSMU17_1675921924$";
drop rollback segment "_SYSSMU16_1518052737$";
drop rollback segment "_SYSSMU15_2246797103$";
drop rollback segment "_SYSSMU14_2215206726$";
drop rollback segment "_SYSSMU13_3885018169$";
drop rollback segment "_SYSSMU12_2010754074$";
drop rollback segment "_SYSSMU11_4042378425$";
12.11.3.5 查验
-- 至此可以正常DML等操作
SQL> select segment_name,status from dba_rollback_segs;
SEGMENT_NAME STATUS
--------------------- ------
SYSTEM ONLINE
_SYSSMU24_1145560925$ ONLINE
_SYSSMU23_497753519$ ONLINE
_SYSSMU10_3531180387$ ONLINE
_SYSSMU9_2948221526$ ONLINE
_SYSSMU8_77629217$ ONLINE
_SYSSMU7_4210038832$ ONLINE
_SYSSMU6_2365516946$ ONLINE
_SYSSMU5_42966806$ ONLINE
_SYSSMU4_2369906140$ ONLINE
_SYSSMU3_3546637655$ ONLINE
_SYSSMU2_3335685343$ ONLINE
_SYSSMU1_1652837430$ ONLINE
12.11.3.6 删除undotbs2
SQL> select * from v$tablespace;
TS# NAME INC BIG FLA ENC CON_ID
--- ------- --- --- --- --- --------
1 SYSAUX YES NO YES 0
0 SYSTEM YES NO YES 0
2 UNDOTBS1YES NO YES 0
4 USERS YES NO YES 0
3 TEMP NO NO YES 0
6 EXAMPLE YES NO YES 0
5 UNDOTBS2YES NO YES 0 -- 文件已经被改名
SQL> drop tablespace undotbs2 including contents and datafiles;
Tablespace dropped.
-- 如果还删除不了,则尝试修改字典
select * from v$tablespace;
-- 记下要删除的undo对应的ts#号,比如是=2,则执行下行语句:
update seg$ set type# = 3 where ts#=2;
-- 然后再删除该 TBS即可.
Temporary Undo表空间是Oracle数据库中的一种特殊类型的Undo表空间,用于存储临时Undo数据。它与普通Undo表空间的区别在于,它不会被用于长期存储Undo数据,而是只用于存储临时Undo数据,这些数据在事务提交后就会被立即删除。
Temporary Undo表空间的作用是提高数据库的性能和可用性。它可以减少Undo表空间的使用量,从而减少数据库的I/O负载和存储空间占用。同时,它还可以提高数据库的可用性,因为它可以避免长时间的事务占用Undo表空间,从而导致其他事务无法执行的情况。
在Oracle数据库中,Temporary Undo表空间是可选的,可以根据实际情况来配置。如果数据库中存在大量的长时间事务,或者Undo表空间的使用量较大,可以考虑配置Temporary Undo表空间来提高数据库的性能和可用性。同时,还需要定期监控Temporary Undo表空间的使用情况,以及进行Temporary Undo表空间的维护和优化。
启用 temp undo 好处:
1).减少 undo TBS
2).减少 redo 数据
3).允许在ADG中对临时表进行DML操作
-- session级别
SQL> ALTER SESSION SET TEMP_UNDO_ENABLED=TRUE;
SQL> ALTER SESSION SET TEMP_UNDO_ENABLED=FALSE;
-- system级别:
SQL> ALTER SYSTEM SET TEMP_UNDO_ENABLED=TRUE;
SQL> ALTER SYSTEM SET TEMP_UNDO_ENABLED=FALSE;