Ok, I promised to write more about patching speed. And this blog post will be just the root post targeting datapatch speed. I will link also to blog posts I’ve written before but also share knowledge which may not be obvious at first stage. The overall topic will be How to speed up datapatch – and much more information.
What is datapatch
Let me start at the ground level and explain what datapatch is and why it exists.
When you are still on Oracle Database 11g, you may wonder what datapatch is all about. Certainly, I hope that you are not on 11g anymore. Hence, most readers will have used datapatch before already. It basically came in to satisfy software/database patching in a Multitenant environment where you need to adjust not only a single database. Even in a single tenant environment with only one PDB you need to apply SQL and PL/SQL changes to CDB$ROOT but also to the PDB and the – read-only – PDB$SEED.
datapatch is the patching vehicle which applies SQL and PL/SQL changes to all your databases and/or containers and updates the data dictionary.
You can find datapatch in your $ORACLE_HOME/OPatch directory. And with each new version of opatch you may also get a new version of datapatch.
But have you ever opened datapatch in an editor? It is fairly short and only basically does this:
Now when you open sqlpatch, it may not wonder you anymore that it will just call another “buddy” to do actual work:
$ORACLE_HOME/perl/bin/perl -I$ORACLE_HOME/sqlpatch -I$ORACLE_HOME/rdbms/admin -I$ORACLE_HOME/sqlpatch/lib $ORACLE_HOME/sqlpatch/sqlpatch.pl $@
So now we come closer. It is actually a perl script. And with all these steps, the right environment and patching parameters will be set, it will do the logging and clean up afterwards.
But at the bottom line it utilizes SQL*Plus to execute scripts and statements.
One of the central components of datapatch is that it tracks patching within the database. On this blog you can find several scripts to monitor the datapatch actions and patching history within your database.
This is how it looks in one of my environments:
CON_ID ACTION_TIME PATCH_ID PATCH_TYPE ACTION DESCRIPTION SOURCE_VERSION TARGET_VERSION _________ ______________ ___________ _____________ ___________ ________________________________________________________ _________________ _________________ 1 2019-04-28 29517242 RU APPLY Database Release Update : 220.127.116.11.190416 (29517242) 18.104.22.168.0 22.214.171.124.0 1 2019-10-16 30125133 RU APPLY Database Release Update : 126.96.36.199.191015 (30125133) 188.8.131.52.0 184.108.40.206.0 1 2020-01-21 30557433 RU APPLY Database Release Update : 220.127.116.11.200114 (30557433) 18.104.22.168.0 22.214.171.124.0 1 2020-04-15 30869156 RU APPLY Database Release Update : 126.96.36.199.200414 (30869156) 188.8.131.52.0 184.108.40.206.0 1 2020-07-15 31281355 RU APPLY Database Release Update : 220.127.116.11.200714 (31281355) 18.104.22.168.0 22.214.171.124.0 1 2020-10-21 31771877 RU APPLY Database Release Update : 126.96.36.199.201020 (31771877) 188.8.131.52.0 184.108.40.206.0 1 2021-01-20 32218454 RU APPLY Database Release Update : 220.127.116.11.210119 (32218454) 18.104.22.168.0 22.214.171.124.0 1 2021-04-21 32545013 RU APPLY Database Release Update : 126.96.36.199.210420 (32545013) 188.8.131.52.0 184.108.40.206.0 1 2021-08-09 32904851 RU APPLY Database Release Update : 220.127.116.11.210720 (32904851) 18.104.22.168.0 22.214.171.124.0 1 2021-12-15 33192793 RU APPLY Database Release Update : 126.96.36.199.211019 (33192793) 188.8.131.52.0 184.108.40.206.0 1 2021-12-16 33192694 INTERIM APPLY OJVM RELEASE UPDATE: 220.127.116.11.211019 (33192694) 18.104.22.168.0 22.214.171.124.0 1 2022-01-19 33192694 INTERIM ROLLBACK OJVM RELEASE UPDATE: 126.96.36.199.211019 (33192694) 188.8.131.52.0 184.108.40.206.0 1 2022-01-19 33515361 RU APPLY Database Release Update : 220.127.116.11.220118 (33515361) 18.104.22.168.0 22.214.171.124.0 1 2022-01-19 33561310 INTERIM APPLY OJVM RELEASE UPDATE: 126.96.36.199.220118 (33561310) 188.8.131.52.0 184.108.40.206.0 2 2019-04-28 29517242 RU APPLY Database Release Update : 220.127.116.11.190416 (29517242) 18.104.22.168.0 22.214.171.124.0 2 2019-10-16 30125133 RU APPLY Database Release Update : 126.96.36.199.191015 (30125133) 188.8.131.52.0 184.108.40.206.0 2 2020-01-21 30557433 RU APPLY Database Release Update : 220.127.116.11.200114 (30557433) 18.104.22.168.0 22.214.171.124.0 2 2020-04-15 30869156 RU APPLY Database Release Update : 126.96.36.199.200414 (30869156) 188.8.131.52.0 184.108.40.206.0 2 2020-07-15 31281355 RU APPLY Database Release Update : 220.127.116.11.200714 (31281355) 18.104.22.168.0 22.214.171.124.0 2 2020-10-21 31771877 RU APPLY Database Release Update : 126.96.36.199.201020 (31771877) 188.8.131.52.0 184.108.40.206.0 2 2021-01-20 32218454 RU APPLY Database Release Update : 220.127.116.11.210119 (32218454) 18.104.22.168.0 22.214.171.124.0 2 2021-04-21 32545013 RU APPLY Database Release Update : 126.96.36.199.210420 (32545013) 188.8.131.52.0 184.108.40.206.0 2 2021-08-09 32904851 RU APPLY Database Release Update : 220.127.116.11.210720 (32904851) 18.104.22.168.0 22.214.171.124.0 2 2021-12-15 33192793 RU APPLY Database Release Update : 126.96.36.199.211019 (33192793) 188.8.131.52.0 184.108.40.206.0 2 2021-12-16 33192694 INTERIM APPLY OJVM RELEASE UPDATE: 220.127.116.11.211019 (33192694) 18.104.22.168.0 22.214.171.124.0 2 2022-01-19 33192694 INTERIM ROLLBACK OJVM RELEASE UPDATE: 126.96.36.199.211019 (33192694) 188.8.131.52.0 184.108.40.206.0 2 2022-01-19 33515361 RU APPLY Database Release Update : 220.127.116.11.220118 (33515361) 18.104.22.168.0 22.214.171.124.0 2 2022-01-19 33561310 INTERIM APPLY OJVM RELEASE UPDATE: 126.96.36.199.220118 (33561310) 188.8.131.52.0 184.108.40.206.0
I don’t want to go into the details of the output but you easily recognize that the view CDB_REGISTRY_SQLPATCH tracks all changes, not only RUs but also interim (one-off) patches.
Please do always two things:
- Don’t access DBA_REGISTRY_SQLPATCH but instead CDB_REGISTRY_SQLPATCH instead since your scripts will then display the correct information in an CDB environment, too
- Always set alter session set “_exclude_seed_cdb_view”=FALSE; since otherwise you will miss PDB$SEED – and this could end in a true nightmare. It does not harm to use this underscore even in non-CDB environments. And if you wonder why it is set to FALSE by default, please open an SR and refer any of the open bugs with this default parameter setting.
You may also potentially add a delimiter on ACTION_TIME to the above script to see only the patch actions maybe from the past 6 months, especially since 19c will have a longer life most likely. And be aware that the list is sorted by CON_ID at first. You may also prefer a sorting on the ACTION_TIME instead.
In summary, your database knows when it has been massaged by datapatch.
What if you forgot to run datapatch?
This is a common question we hear from time to time – and actually we see sometimes out there. You patched nicely with opatch, but somebody forgot to run datapatch.
At first, the fact that somebody forgot to run datapatch is bad. It means that your database operates with binary patches but misses the SQL and PL/SQL parts of a patch. Certainly, there are patches which have no SQL or PL/SQL representation. Usually optimizer fixes are such an examples. The fix for an issue is in the binary, and there is no adjustment in the dictionary necessary. The opposite is Data Pump. There usually you have a counter part in the SQL and PL/SQL APIs.
So please make sure to run:
as a standard action when you applied the binary patches to your systems.
But see what happens if you did run it accidentally another time for no reason. No worries at all, it recognizes that it has nothing to do.
Current state of interim SQL patches: Interim patch 33192694 (OJVM RELEASE UPDATE: 220.127.116.11.211019 (33192694)): Binary registry: Not installed PDB CDB$ROOT: Rolled back successfully on 19-JAN-22 10.14.44.327180 PM PDB PDB$SEED: Rolled back successfully on 19-JAN-22 10.14.44.347566 PM Interim patch 33561310 (OJVM RELEASE UPDATE: 18.104.22.168.220118 (33561310)): Binary registry: Installed PDB CDB$ROOT: Applied successfully on 19-JAN-22 10.14.44.331372 PM PDB PDB$SEED: Applied successfully on 19-JAN-22 10.14.44.350816 PM Current state of release update SQL patches: Binary registry: 22.214.171.124.0 Release_Update 211225122123: Installed PDB CDB$ROOT: Applied 126.96.36.199.0 Release_Update 211225122123 successfully on 19-JAN-22 09.48.19.540225 PM PDB PDB$SEED: Applied 188.8.131.52.0 Release_Update 211225122123 successfully on 19-JAN-22 09.48.19.756424 PM Adding patches to installation queue and performing prereq checks...done Installation queue: For the following PDBs: CDB$ROOT PDB$SEED No interim patches need to be rolled back No release update patches need to be installed No interim patches need to be applied SQL Patching tool complete on Mon May 30 11:35:36 2022
And then it stops successfully with no treatment done to your database(s) and container(s).
Rolling or non-rolling, that’s the question
I need to mention one very important additional piece of information.
You may have wondered why some patches, for instance Data Pump patches, often are not included in Release Update (RU) patch bundles. And the simple explanation is that a patch in an RU is supposed to be “RAC rolling and standby-first“. But as soon as a patch has a SQL and/or PL/SQL part and adjust an API, as long as there is no way to block access to the API for all instances, there is a risk involved. Hence, such patches are excluded from patch bundles.
Hence, it also does not matter on which node of your cluster you invoke datapatch. But you need to invoke it only on one node, not on every node, since you patch the dictionary of your database.
This is one of the oldest myths.
Your database or PDB does not have to be in STARTUP UPGRADE mode. Instead, a normal STARTUP is fine and sufficient. But it is very important that your PDBs are open. A closed PDB can’t be adjusted.
This is why we always recommend to use the SAVE STATE command to ensure that your PDBs are opened automatically after you took down the CDB. Of course, in RAC environments you may realize this with the resource setting.
Gathering database info...done Note: Datapatch will only apply or rollback SQL fixes for PDBs that are in an open state, no patches will be applied to closed PDBs. Please refer to Note: Datapatch: Database 12c Post Patch SQL Automation (Doc ID 1585822.1)
A while ago I wrote a blog post about whether a STARTUP UPGRADE is needed or not.
And repeating myself, it is not needed. We worked together with the patching team to correct also the OJVM READMEs.
Now when you dig deeper you may recognize that datapatch logs quite a bit. And even though the logging is not perfect yet and lacks some things due to the nature of the underlying PERL libraries, there is a lot of good information in:
So the first important part is that the logs aren’t in your actual $ORACLE_HOME.
What will you find in this directory? At first, you may wonder about the kind of naming schema of the logs. It has the process ID in the name rather then the container name or ID. Hence, it is a bit hard to navigate around.
But what types of logs are there? I’m stealing this from MOS Note: 2680521.1 – Datapatch User Guide since it lists the various logs:
|sqlpatch_invocation.log||A detailed log of the processing done by datapatch|
|sqlpatch_debug.log||With –debug , contains additional information useful for troubleshooting|
|Bootstrap*.sql||Script created by datapatch to run the bootstrap processing in the database.|
|bootstrap*.log||The log files from running the bootstrap*.sql script in the database (per container).|
|Install*.sql||Script created by datapatch to run the apply and/or rollback scripts for the patches. For CDBs, this script is passed to catcon.pl to run in each container.|
|sqlpatch_catcon_*.log||The log files created by catcon as it processes the install<n> script for each container. (The individual apply/rollback logs are captured for each patch ID in the $ORACLE_BASE/cfgtoollogs/sqlpatch/patch_id directories).|
|sqlpatch_catcon__catcon_<action>.sql||Scripts generated by catcon to perform specific actions in each container of a CDB.|
|sqlpatch_catcon__catcon_<PID>.lst||catcon startup log file; identifies catcon log file locations|
So the “invocation” log is the place where usually I start at when I want to analyze a patching run.
What we miss right now but have an enhancement open for is a patch_summary.log as we have it for the upgrade which shows you an overview at first glance.
If you want to see what can be done with such logs, what can be read and what can’t, you may read this blog post:
How does this look now in my environment? There is at first a log part which is aligned with the patch number, for instance:
├── 33515361 │ └── 24589353 │ ├── 33515361_apply_CDB2_CDBROOT_2022Jan19_21_47_29.log │ ├── 33515361_apply_CDB2_PDBSEED_2022Jan19_21_47_54.log │ ├── 33515361_apply_UP19_2022Jan19_23_17_14.log │ ├── 33515361_ru_apply_CDB2_CDBROOT_2022Jan19_21_47_28.log │ ├── 33515361_ru_apply_CDB2_PDBSEED_2022Jan19_21_47_53.log │ └── 33515361_ru_apply_UP19_2022Jan19_23_17_13.log
This is the information for a specific patch. You see that it got applied not only to my CDB2 but also to another database, UP19.
And there is another tree with the sqlpatch information including the sqlpatch_invocation.log:
├── sqlpatch_29286_2022_01_19_21_46_51 │ ├── bootstrap1_CDB2_CDBROOT.log │ ├── bootstrap1_CDB2_PDBSEED.log │ ├── bootstrap1.sql │ ├── install1.sql │ ├── sqlpatch_autorecomp_CDBROOT.log │ ├── sqlpatch_autorecomp_PDBSEED.log │ ├── sqlpatch_catcon_0.log │ ├── sqlpatch_catcon__catcon_29286.lst │ ├── sqlpatch_debug.log │ ├── sqlpatch_invocation.log │ ├── sqlpatch_progress.json │ └── sqlpatch_summary.json
Now be very aware that the root directory is badly ordered due the naming – and even more important, you will find ALL patch runs for ALL your homes using this $ORACLE_BASE within this directory.
This makes it sometimes a lovely exercise when I download a 3GB zip file from MOS looking for an issue for a specific database. Especially with many containers/PDBs it is great fun.
How to speed up datapatch – Rule no.1?
Now I wrote a lot of stuff about datapatch – but you may miss the information how to speed it up.
Of course there is a lot of things to write and discuss – and I don’t want this blog post to become too lengthy, especially since it will be hard to find the correct topic.
Still, one general rule needs to be told, especially for Multitenant environments.
If you want to speed up patching with datapatch, recompile beforehand.
You will especially feel and see the difference in larger Multitenant environments. Make sure your PDBs are all open, and then invoke the recompilation:
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -n 1 -e -b utlrp -d $ORACLE_HOME/rdbms/admin utlrp.sql
How do we continue?
I hope you aren’t too disappointed at this point. Just a tiny little recommendation but many of you will certainly now state that this doesn’t fix your current problem. But I wanted to give a broad overview at first, and then dig deeper and go step-by-step. The following blog post will be much shorter but also cover an area we seem more and more happening.
So stay tuned 🙂
Further Links and Information
- Patch monitor script for Oracle 19c
- Do you need STARTUP UPGRADE when you patch?
- MOS Note: 2680521.1 – Datapatch User Guide
- What does datapatch do when you have different components in your containers?
- Binary patching is slow because of the inventory