Article written by Deiby Gómez.
Local Undo is a new kind of undo configuration for Multitenant Architecture and it is a new feature introduced in 12.2.0.1.0. A couple of weeks ago the documentation of 12.2.0.1.0 was released and also the binaries in Oracle Public Cloud, several DBAs around the world started to play with the new features. When we say "Local Undo" basically we are saying that every Pluggable Database will have its own Undo Tablespace, similar to the following image where the Pluggable Databases "NuvolaPDB1", "NuvolaPDB2", "NuvolaPDB3", and also PDB$SEED have its own Undo tablespace.
This was a big change compared with the multitenant undo configuration in 12.1. In 12.1 only CDB$ROOT has its own Undo tablespace and all the Pluggable Databases "shared" that undo tablespace, that's why the former multitenant undo configuration is called "Shared Undo". To summary, starting in 12.2.0.1.0 we have "Local Undo" or "Shared Undo". In this article I will show you step by step how to configure Local Undo in a Multitenant Database and also how to deconfigure it.
NOTE: This article was written using Oracle Database 12.2.0.1.0 Enterprise Edition Extreme Performance (Oracle Public Cloud).
The environment I am using is the following:
- a CDB Database called "NuvolaCG".
- 4 Pluggable Databases:
- NuvolaPDB1 (con_id=3)
- NuvolaPDB2 (con_id=4)
- NuvolaPDB3 (con_id=5)
- NuvolaPDB4 (con_id=6)
Currently the configuration my environment is using is "Shared Undo". In a Shared Undo configuration, all the pluggable databases use (Share) the same Undo Tablespace, the Undo Tablespace is owned by CDB$ROOT. For example, in the following query result you can see that all my PDBs are using the same undo tablespace called "UNDOTBS1" and you can see that the owner of that undo tablespace is the CDB$ROOT (con_id=1):
SQL> select s.con_id fromwhichpdb, s.username usersession, r.con_id undo_owner, r.tablespace_name current_undo, segment_name segmentused
from v$session s,
v$transaction t,
cdb_rollback_segs r
where s.taddr=t.addr
and t.xidusn=r.segment_id(+)
and t.con_id=r.con_id
and t.ses_addr=s.saddr
order by 1;
FROMWHICHPDB USERSESSION UNDO_OWNER CURRENT_UNDO SEGMENTUSED
------------ ------------ ---------- ------------ ------------------------------
3 USERA 1 UNDOTBS1 _SYSSMU3_1251228189$
4 USERB 1 UNDOTBS1 _SYSSMU9_3256821283$
5 USERC 1 UNDOTBS1 _SYSSMU1_307601955$
6 USERD 1 UNDOTBS1 _SYSSMU7_442620111$
How to configure Local Undo:
Shutdown the database:
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
Start the database up in upgrade mode:
SQL> startup upgrade;
ORACLE instance started.
Total System Global Area 5452595200 bytes
Fixed Size 8804328 bytes
Variable Size 1090521112 bytes
Database Buffers 4345298944 bytes
Redo Buffers 7970816 bytes
Database mounted.
Database opened.
Enable Local Undo:
SQL> alter database local undo on;
Database altered.
Shutdown the database:
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
Start the database up normally:
SQL> startup;
ORACLE instance started.
Total System Global Area 5452595200 bytes
Fixed Size 8804328 bytes
Variable Size 1090521112 bytes
Database Buffers 4345298944 bytes
Redo Buffers 7970816 bytes
Database mounted.
Database opened.
Confirm the new undo confiruation is "Local Undo":
SQL> SELECT PROPERTY_NAME, PROPERTY_VALUE FROM DATABASE_PROPERTIES WHERE PROPERTY_NAME = 'LOCAL_UNDO_ENABLED'
PROPERTY_NAME PROPERTY_VALUE
-------------------- --------------------
LOCAL_UNDO_ENABLED TRUE
Now let's open all the Pluggable Databases:
SQL> alter pluggable database all open;
Pluggable database altered.
NOTE:if you get the error "ORA-00060: deadlock resolved;" here, you can read my last articlewhere you can find the solution.
As you can see bellow, now all the Pluggable Databases have its own Undo Tablespace, by default the undo tablespace is called "UNDO_1".
SQL> select pdb.name PDB_NAME, tbs.name TABLESPACE_NAME from v$tablespace tbs, v$pdbs pdb where tbs.con_id=pdb.con_id and tbs.name like 'UNDO%' order by 1;
PDB_NAME TABLESPACE_NAME
----------- ------------------------------
NUVOLAPDB1 UNDO_1
NUVOLAPDB2 UNDO_1
NUVOLAPDB3 UNDO_1
NUVOLAPDB4 UNDO_1
PDB$SEED UNDO_1
NOTE: If you want to know how those Undo Tablespaces were created in every Pluggable Database you can read my article called "How Undo Tablespace is created in Local Undo Config".
I executed a couple of DMLs just to use undo segments in each Pluggable Database, and now you can see that every Pluggable Database is using its own Undo Tablespace. For example the session started in NuvolaPDB1 (con_id=3) is using the undo segment called "_SYSSMU8_3241223907$" which is part of the tablespace "UNDO_1" which is owned by NuvolaPDB1 (con_id=3).
SQL> select s.con_id fromwhichpdb, s.username usersession, r.con_id undo_owner, r.tablespace_name current_undo, segment_name segmentused
from v$session s,
v$transaction t,
cdb_rollback_segs r
where s.taddr=t.addr
and t.xidusn=r.segment_id(+)
and t.con_id=r.con_id
and t.ses_addr=s.saddr
order by 1; 2 3 4 5 6 7 8 9
FROMWHICHPDB USERSESSION UNDO_OWNER CURRENT_UNDO SEGMENTUSED
------------ ------------ ---------- ------------- ------------------------------
3 USERA 3 UNDO_1 _SYSSMU8_3241223907$
4 USERB 4 UNDO_1 _SYSSMU9_2687006412$
5 USERC 5 UNDO_1 _SYSSMU4_2039586447$
6 USERD 6 UNDO_1 _SYSSMU7_3889563214$
It is important to know that if you try to drop an undo tablespace when Local Undo is in use you wil get an error:
SQL> alter session set container=NuvolaPDB1;
Session altered.
SQL> drop tablespace UNDO_1 including contents and datafiles;
drop tablespace UNDO_1 including contents and datafiles
*
ERROR at line 1:
ORA-30013: undo tablespace 'UNDO_1' is currently in use
How to disable Local Undo:
shutdown the database:
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
Start the database up in upgrade mode:
SQL> startup upgrade;
ORACLE instance started.
Total System Global Area 5452595200 bytes
Fixed Size 8804328 bytes
Variable Size 1090521112 bytes
Database Buffers 4345298944 bytes
Redo Buffers 7970816 bytes
Database mounted.
Database opened.
Disable Local Undo:
SQL> alter database local undo off;
Database altered.
Shutdown the database:
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
Start the database up normally:
SQL> startup;
ORACLE instance started.
Total System Global Area 5452595200 bytes
Fixed Size 8804328 bytes
Variable Size 1090521112 bytes
Database Buffers 4345298944 bytes
Redo Buffers 7970816 bytes
Database mounted.
Database opened.
Confirm Shared Undo is used (Local Undo is false):
SQL> SELECT PROPERTY_NAME, PROPERTY_VALUE FROM DATABASE_PROPERTIES WHERE PROPERTY_NAME = 'LOCAL_UNDO_ENABLED';
PROPERTY_NAME PROPERTY_VALUE
-------------------- --------------------
LOCAL_UNDO_ENABLED FALSE
How to delete Undo Tablespaces after switch from Local Undo to Shared Undo:
There is an important thing here that you should know when you switch from Local Undo to Shared Undo. Since you used Local Undo you know that every Pluggable Database had its own Undo Tablespace, however when you enable "Shared Undo" all those undo tablepaces are not removed, which means that you will have them there and you have to take a desition either leave them there or remove them.
SQL> select pdb.name PDB_NAME, tbs.name TABLESPACE_NAME from v$tablespace tbs, v$pdbs pdb where tbs.con_id=pdb.con_id and tbs.name like 'UNDO%' order by 1;
PDB_NAME TABLESPACE_NAME
----------- ------------------------------
NUVOLAPDB1 UNDO_1
NUVOLAPDB2 UNDO_1
NUVOLAPDB3 UNDO_1
NUVOLAPDB4 UNDO_1
PDB$SEED UNDO_1
If you decide to remove them, you have two options, The first option is to use "catcon.pl" against all the Pluggable Database as I show you bellow:
[oracle@NuvolaDB ~]$ $ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -u sys/Nuvola1 -c 'NuvolaPDB1 NuvolaPDB2 NuvolaPDB3 NuvolaPDB4' -s -b DropUndoPDBs -- --x'drop tablespace UNDO_1 including contents and datafiles;'
catcon: ALL catcon-related output will be written to [/home/oracle/DropUndoPDBs_catcon_13739.lst]
catcon: See [/home/oracle/DropUndoPDBs*.log] files for output generated by scripts
catcon: See [/home/oracle/DropUndoPDBs_*.lst] files for spool files, if any
catcon.pl: completed successfully
[oracle@NuvolaDB ~]$
The second Option is to connect to every Pluggable Database manually and drop the undo tablespace, this could take more time than using catcon. I recommend catcon, it's easy and fast. The following sentences should be executed in every Pluggable Database you have:
SQL> alter session set container=NuvolaPDB1;
Session altered.
SQL> drop tablespace undo_1 including contents and datafiles;
Tablespace dropped.
In both options, Using catcon.pl and also drop the undo tablespace manually you have to do the following you have want to remove the Undo tablespace also from PDB$SEED:
SQL> alter session set "_oracle_script"=true;
Session altered.
SQL> alter pluggable database pdb$seed close;
Pluggable database altered.
SQL> alter pluggable database pdb$seed open read write;
Pluggable database altered.
SQL> alter session set container=pdb$seed;
Session altered.
SQL> drop tablespace UNDO_1 including contents and datafiles;
Tablespace dropped.
SQL> alter session set container=cdb$root;
Session altered.
SQL> alter pluggable database pdb$seed close;
Pluggable database altered.
SQL> alter pluggable database pdb$seed open read only;
Pluggable database altered.
SQL> alter session set "_oracle_script"=false;
Session altered.
After all these steps, you finally will leave your database as nothing happened. Of course you can see that disabling Local Undo and reverting back all the changes takes more time compared with enabling Local Undo.
SQL> select pdb.name PDB_NAME, tbs.name TABLESPACE_NAME from v$tablespace tbs, v$pdbs pdb where tbs.con_id=pdb.con_id and tbs.name like 'UNDO%' order by 1;
no rows selected
Conclusion:
- Enabling Local Undo creates all the undo tablespaces automatically in every PDB including PDB$SEED.
- Disabling Local Undo doesn't remove the undo tablespaces automatically.
- You need to bounce your database either for enabling Local Undo or Disabling it.
- Local Undo is strongly recommended. It gives more isolation to Pluggable Databases.
- The former Undo configuration (<12.2) is called "Shared Undo".
Follow me: