ADOP edition cleanup

Oracle e-Business Suite administrators have access to pretty extensive documentation regarding Patching procedures. In Oracle EBS 12.2 Oracle introduced ADOP patching method along with Oracle Database EBR (edition-based redefinition) feature that allows minimizing downtimes for patching activities. As with everything in this world – it also comes with a few caveats. So let’s talk about the ADOP cleanup part a bit.
DualFS
In the application tier, it is rather simple – there are two filesystems to take care of. So every time the patch cycle is open, in patchFS actual patching is happening. Once the downtime comes cutover flips the filesystems and now the code is running a patched version. As a DBA I would suggest keeping PatchFS always up to sync. Finish patching cycles with FSClone and avoiding deploying the code directly in RunFS. There are a few options available with FSClone and prepare phases and even some custom synchronization options for very specific use cases. But at the end of the day that is pretty much it when it comes to taking care of the application filesystem.
Database Editions
Different story with the database. Every time a new patch cycle is started (adop phase=prepare) – the database creates a new edition. Thankfully, Oracle has tooling that handles all edition-related issues pretty well, like cross-edition triggers and AD_ZD package. In normal circumstances, APPS DBA should not be looking for any edition-related issues. However, if Oracle security patches are being applied and other maintenances are happening over time, the edition count in the database keeps growing. In some discussions with Oracle EBS folks, I recall the suggestion not to go over 20 editions, documentation states 25 or more. I would suggest not going over 10 or keep even lower.
EBR is quite complicated, but for sake of simplicity, let’s imagine that the edition is like a filesystem based on snapshots. The root filesystem (A) has all the objects (or files). In the new snapshot filesystem (B) if an object or file is created it exists only on that particular one (B), however, all the files that existed in the root filesystem (A) will have only references or links to the root filesystem. So in snapshot filesystem (B) if the object is accessed that existed in root filesystem (A) – basically it has only a link and actual data is in A. That is the whole point not to duplicate data in the database, create new versions online, and switch to it through cutover. Oracle EBS Vision database has over 400K objects, real-life EBS systems will have something like 600k and we have seen heavily customized ones with over 1M objects. So the approach as with the DualFS on application filesystem would not work in the database due to the time required to create those objects and significant space utilization. EBR solves these problems.
Cleanup
In regard to edition cleanup, I have heard several wrong assumptions. One of the common ones is that those editions are being cleaned in actualize phase. Documentation says:
$ adop phase=prepare $ adop phase=actualize_all $ adop phase=finalize finalize_mode=full $ adop phase=cutover $ adop phase=cleanup cleanup_mode=full
However, phase cleanup_mode=full is the one responsible for moving objects to the latest edition and dropping old editions.
The First edition in the database is usually called ORA$BASE. If there’s still this edition in the database – it’s pretty obvious that edition cleanup is not performed. Oracle EBS provides a few good SQL scripts like ADZDSHOWOBJS.sql showing edition states, ADZDSHOWED.sql will show editions or can obtain data directly from dba_editions. Here’s a typical example.
[apps ~]$ sqlplus @$AD_TOP/sql/ADZDSHOWOBJS.sql ========================================================================= = Editioned Objects Per Edition ========================================================================= EDITION_NAME A_VALID A_INVALID A_TOTAL S_VALID S_INVALID S_TOTAL TOTAL --------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ORA$BASE 600046 85 600131 0 0 0 600131 V_20210219_0121 12183 0 12183 564922 76 564998 577181 V_20210320_0836 15890 0 15890 577104 76 577180 593070 V_20210618_1013 3120 0 3120 592994 76 593070 596190 V_20220917_2123 1187 0 1187 596114 76 596190 597377 V_20221110_1255 90 0 90 597301 76 597377 597467 V_20221117_1541 2408 3 2411 597392 75 597467 599878 Note : (A_) - Actual Objects (S_) - Stub Objects
One of the main problems in my mind with a lot of editions is the fact that those editions are growing internal metadata tables. If you query dba_objects it’ll always return the number of objects in edition however sys.obj$ will multiply that by edition count. And once internal storage has been stretched it can be resized only by export/import. I have seen several performance issues against all_tab_cols or other all_ performance views due to the optimizer acting weird when there are a lot of editions.
Execution
Executing edition cleanup is pretty much like every other ADOP maintenance activity. It can be merged with the ADOP apply phase as well. Below, I’ll share a few recommendations to make things smoother and avoid a few issues learned.
Database connections
By default, ADOP cutover disconnects all APPS sessions and that pretty much guarantees that EBS after cutover will connect to the current or latest database edition. However, it’s not true for any custom schema or application connected to the edition-enabled user in the database.
SQL> select distinct SESSION_EDITION_ID, count(1) from gv$session group by SESSION_EDITION_ID; SESSION_EDITION_ID COUNT(1) ------------------ ---------- 0 423 59398809 12 61212763 620
One option is to restart the database before the ADOP cleanup_full phase. Another is to disconnect all sessions that are connected to previous editions. In the example above there are still 12 sessions connected to edition_id: 59398809 and cleanup will fail with an error, most likely with something like this:
ORA-00600: internal error code, arguments: [kghstack_underflow_internal_3],
Object creation in the process
Avoid creating any objects between actualize and cleanup phase (think about automated object creation, concurrent programs, and schedules) or it may end up in a situation as below. Edition cleanup completes successfully, however, there’s an edition with one or few objects.
EDITION_NAME A_VALID A_INVALID A_TOTAL S_VALID S_INVALID S_TOTAL TOTAL --------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- V_20211210_1255 1 0 1 0 0 0 1 V_20211217_1541 2408 3 2411 597392 75 597467 599878
To find the object of interest run something like:
select * from dba_objects where EDITION_NAME = 'V_20211217_1541';
Oracle’s existing process to clear this problem would be to start the edition cleanup procedure over again from the prepare, actualize, and cutover phase. However, in some simpler cases, it could be as easy as connecting to the current edition, and recreating those objects with something like CREATE OR REPLACE FORCE EDITIONABLE VIEW [PACKAGE]. Once there are no objects in the OLD edition – rerun (adop phase=cleanup cleanup_mode=full) that will take care of the dangling edition.
Database links or TYPE objects
A lot of headaches may deliver obsolete or nonworking database links. If there’s an object (like a package) in an old edition that references a database link that either is not working or is not present in the current edition – most probably the edition cleanup procedure will fail.
The solution to this is to create dummy DB links (probably even users and dummy objects) to themselves, so those references work, perform edition cleanup and clear those objects out once edition cleanup has been completed. This is especially relevant for environments that have been upgraded from previous versions or migrated and referenced objects are not always database links. Similar issues have been observed with object_type TYPE.
Safety
Always a smart idea before such maintenance is to create a guaranteed restore point. In case of any issues with the data dictionary or edition cleanup. It’s super easy to get back before the process has started and fix the issues in advance before they actually happen. However, to avoid unnecessary issues, make sure there’s enough space in db_recovery_file_dest_size.
To conclude
Oracle database edition cleanup is an important life cycle management task in EBS release 12.2. This operation is not executed so often sometimes we see organizations even forget about that at all. This is not a complicated task as currently, the tooling has grown. It may be a bit challenging task executing cleanup for the first time or executing it against an upgraded environment as we have seen issues in the past. However, if managed to get through the first cycle and issues with the data dictionary are resolved – this should be a walk in the park.