Showing posts with label MS Windows. Show all posts
Showing posts with label MS Windows. Show all posts

Sync PDB failed with ORA-40365 while performing 'alter user sys account lock password expire' - How to get rid of it.

As so often, a customer was asking for the solution of an error they have seen at the database. After creating a new Oracle 19c database with a fresh PDB in it, they found the error "Sync PDB failed with ORA-40365 while performing 'alter user sys account lock password expire'" in the view PDB_PLUG_IN_VIOLATIONS.

The Oracle Support Note "Sync PDB failed with ORA-40365 while performing 'alter user sys' (Doc ID 2777162.1)" told him that this error can happen when upgrading a database to a newer version.

Doc ID 2777162.1

You know how it is. Things that go differently than they are described demand analysis and don't give you a moment's peace. So I started to recreate the whole thing...

While the customer is working with version 19.8, I installed version 19.13 on my MS Windows laptop and created a new database there with the DBCA. I was (not) surprised when I saw the error on my end as well.

This means that something fundamentally different is going on here than what was described at Oracle Support. 

Log me, find me, SR me

Well - this error shouldn't happen if you create a new database, isn't it? So first I checked the version of the password file on my laptop for the new created CDB. This can be done with "orapwd" and the parameter describe.

Hm, the password file was created with version 12. But the support note told us, that a fresh created CDB should have password file format 12.2 - if not, we can upgrade the file manually to 12.2 using orapwd (more to come later in this blog post). 

So it looks like the DBCA is creating the wrong password file version in some way. But can this be? Maybe it depends on the password complexity? No, also another attempt with a very complex password ended with the same password file version: 12. 

Well, if the DBCA is doing it wrong, maybe it's recorded in the log file of the creation? And yes, it is.
 
 
As you can see at the highlighted line, the DBCA actually creates the password file fix with version 12 - instead of the version 12.2 we expected.
 
In my opinion, this is a bug - so I opened a service request with Oracle about it.
 
Long story short: This isn't a bug. At least not a bug at the DBCA. It is a bug at the documentation resp. the support note. Based on communication with Oracle Support, a new note has now been created:

Oracle Support Document 2663482.1 (19c DB Does Not Make Password File Default Format As 12.2)

can be found at: https://support.oracle.com/epmos/faces/DocumentDisplay?id=2663482.1
This new note now tells us, that we need to pass "-skipPasswordComplexityCheck false" to the DBCA (one has to ensure, that the password set is passing the password complexity function) to get a 12.2 password file. Also, an enhancement request was created to make the 12.2 password file version as the default one when creating a 19c database.
In the original support note (Doc ID 2777162.1), Oracle also has changed things now. First is, they have put in that his can also happen with a newly created database. Also they tell us, why they haven't changed the behavior. This is mainly because, in addition to password complexity, things like "Password Lifetime" for SYSDBA, SYSBACKUP,... users are turned on with password file version 12.2.
So it should be exciting to see if the behavior will then change fundamentally in a newer database version or if will remain as default 12.

How to get rid of it

Well, first step is to recreate your password file with version 12.2 - you use orapwd with a input file and the version you want the new file created as I did: 
 
Don't forget to rename the fresh created file that it has the same filename as the original one had (and check all topics that a change of the password file version does influence). Afterwards, you can fix the error in PDB_PLUG_IN_VIOLATIONS.
I tried to re-open the PDB as well as using "exec dbms_pdb.sync_pdb" - but the error never was set to resolved - it stayed in PENDING state and I weren't able to use "exec dbms_pdb.clear_plugin_violations".

To have the entry removed, I needed to do something I really DON'T like to do - to delete manually from the data dictionary with a "delete from pdb_plug_in_violations where error=40365;"  statement. Be aware that changing things at the Data Dictionary manually can cause a lot of trouble - you should only do it, if you have a sufficient backup and you are sure you do the right thing.






DOAG Conference 2020

What crazy times we have. Most conferences are online only, some are also on-premises, but without the necessary hygiene concept to avoid corona (or without enough control), as I have seen at twitter. 

The big DOAG conference this year is an online conference AND an on-premises one - but with a big hygiene concept. Roundabout half of the presentations are streamed online, all others can only be seen at Nuremberg. 

I was selected as a speaker again, which makes me still proud. This year, I will talk about migrating and upgrading a database using the autoupgrade tool over to nodes. I will show this with a Windows environment - because it's a little bit more to do manually, but I will also cover the things you need to do at Linux (as this means I will just say: you don't need to do that step on Linux πŸ˜‰). Unfortunately, the presentation will not be streamed online, this means, if you want to see that, you have to go to Nuremberg (and speak german, as my presentation will be in german). 

So, stay safe and see you there - hopefully!




Autoupgrade.jar on MS Windows: Database is open but "Error Cause: The database <--> is currently open with status of CLOSED."

People are using autoupgrade.jar to upgrade the Oracle databases more and more, this is the good news.

But the more people using autoupgrade.jar - the more things arise, while working with it. That's the bad news (or maybe it's also good news, because we do get a better feeling if things happen, WHY they happen).
At the blog of my employer, one was asking for a solution of the problem that autoupgrade in analyze mode is reporting a status of closed, but the database is open. He is connecting with an application and sqlplus, tnsping, etc. is working.

He was running autoupgrade on a 12c database on a MS Windows server in analyze mode, when he hits this error, also with the latest downloaded version of autoupgrade.jar (you should always download the latest autoupgrade.jar from Oracle Support).

The error was similar to this one:

Unsupported language [de], defaulting to English
AutoUpgrade tool launched with default options
------------ ERROR ------------
Error Cause: The Database orcljso2 appears to be down or open with the incorrect binaries for the mode ANALYZE. Ensure it is open with C:\app\oracle\product\12.2.0\dbhome_1

------------ ERROR ------------
Error Cause: The database orcljso2 is currently open with a status of CLOSED.  For ANALYZE mode, it needs to be open in one of the following: [OPEN, MOUNTED].

Unable to connect to database orcljso2 for entry upg1


To be honost, this is NOT an autoupgrade error, because there are some constraints for autoupgrade you have to fullfil, so it can do its work. One of the main things is, autoupgrade does connect to the database using "sqlplus / as sysdba". There isn't any tnsnames.ora or password involved. If this doesn't work in your environment, you need to fix that. It is also not related to MS Windows, but in Linux environments, typically connecting "/ as sysdba" is working (as you do everything using your "oracle" user and the default groups).

But how to know, what is the root problem, as autoupgrade does only tells you "the database is closed"?
Autoupgrade does write very, very detailed logs (or better traces). As you have specified a log directory for autoupgrade, you can find the logs there.
There are 2 possibilities where autoupgrade does put the logs into. If you don't specify a local entry, it puts it into the global directory, otherwise in the local one of your database specification in the config file.
  • global.autoupg_log_dir=C:\app\oracle\autoupgrade
  • upg1.log_dir=C:\app\oracle\autoupgrade\orcljso2
In my environment, I can then find the log files "autoupgrade.log" and "autoupgrade_err.log" in the directory C:\app\oracle\autoupgrade\cfgtoollogs\upgrade\auto

Some examples, of what can go wrong while (not) connecting with "/ as sysdba" and what "autoupgrade.log" does show as output.

1. A missing part in the database home of the source

I have specified
  • upg1.source_home=C:\app\oracle\product\12.2.0\
while the right entry would be
  • upg1.source_home=C:\app\oracle\product\12.2.0\dbhome_1
The entry at the log file then looks like
2020-07-09 14:52:45.844 ERROR Invalid value for source_home [C:\app\oracle\product\12.2.0\dbhome1] - Utilities.validateDirectory
2020-07-09 14:53:19.251 ERROR Unexpected IOException [null] [SELECT STATUS FROM SYS.V$INSTANCE;] - ExecuteSql$SQLClient.run
java.io.IOException: Cannot run program "C:\app\oracle\product\12.2.0\bin\sqlplus" (in directory "C:\Users\JOERG~1.SOB\AppData\Local\Temp"): CreateProcess error=2, The System cannot find the File specified
    at java.lang.ProcessBuilder.start(Unknown Source)
    at oracle.upgrade.commons.processes.ExecuteProcess.startSqlPlusProcess(ExecuteProcess.java:315)
    at oracle.upgrade.commons.sql.ExecuteSql$SQLClient.run(ExecuteSql.java:882)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: CreateProcess error=2, The System cannot find the File specified
    at java.lang.ProcessImpl.create(Native Method)
    at java.lang.ProcessImpl.<init>(Unknown Source)
    at java.lang.ProcessImpl.start(Unknown Source)
    ... 4 more

2020-07-09 14:53:19.259 ERROR The database orcljso2 appears to be down or open with the incorrect binaries for the mode ANALYZE,
ensure it is open with C:\app\oracle\product\12.2.0 - UpgradeConfigDBValidator.initializeIsDBUp
2020-07-09 14:53:19.262 ERROR The database orcljso2 is currently open with a status of CLOSED. 
For ANALYZE mode, it needs to be open in one of the following: [OPEN, MOUNTED]. - UpgradeConfigDBValidator.initializeIsDBUp

Solution: Correct the Source home path in your configuration. I think the same error can happen, if the Source Home is not the same as the home the service was started from.
Note: If you specify e.g. the home and miss the "_", you do get another error message:
Invalid value for source_home [C:\app\oracle\product\12.2.0\dbhome1]
It was not possible to validate the directory for source_home of entry upg1)

2. Wrong SID in the configuration file

If you have specified a wrong SID in the configuration file, the error is a little bit hidden.

2020-07-16 14:33:53.786 ERROR The database orcljso appears to be down or open with the incorrect binaries for the mode ANALYZE,
ensure it is open with C:\app\oracle\product\12.2.0\dbhome_1 - UpgradeConfigDBValidator.initializeIsDBUp
2020-07-16 14:33:53.798 ERROR The database orcljso is currently open with a status of CLOSED.  For ANALYZE mode, it needs to be open in one of the following: [OPEN, MOUNTED]. - UpgradeConfigDBValidator.initializeIsDBUp
2020-07-16 14:33:53.803 INFO Content of the file C:\app\oracle\product\12.2.0\dbhome_1\sqlplus\admin\glogin.sql is:
--
-- Copyright (c) 1988, 2005, Oracle.  All Rights Reserved.
--
-- NAME
--   glogin.sql
--
-- DESCRIPTION
--   SQL*Plus global login "site profile" file
--
--   Add any SQL*Plus commands here that are to be executed when a
--   user starts SQL*Plus, or uses the SQL*Plus CONNECT command.
--
-- USAGE
--   This script is automatically run
-- - GLoginLogger.logGlogin


So it halts at this state in the log. The only thing where you can see that you have specified a wrong SID is at the error itself (my database is ORCLJSO2 and not ORCLJSO).

Solution: Correct the SID in your configuration file.
Note: If the SID is correct but the dbname is wrong, the autoupgrade tool connects to the database and starts working.

Wrong configuration is:
    upg1.dbname=orcljso
    upg1.sid=orcljso2

Output of the autoupgrade.log at job level is:
   DataBase Name:orcljso2
   Sid Name     :orcljso2

3. Wrong SQLNET configuration or ORA_DBA group missing

Another reason, why the autoupgrade tool cannot connect to the database is that you have some values at your sqlnet configuration, which don't allow this or your (windows shell) user is not part of the ORA_DBA group.

As example, you have specified:
SQLNET.AUTHENTICATION_SERVICES = (NONE)

The output at the logfile is pretty same as for a wrong SID:

2020-07-16 15:06:19.805 ERROR The database orcljso2 appears to be down or open with the incorrect binaries for the mode ANALYZE,
ensure it is open with C:\app\oracle\product\12.2.0\dbhome_1 - UpgradeConfigDBValidator.initializeIsDBUp
2020-07-16 15:06:19.821 ERROR The database orcljso2 is currently open with a status of CLOSED.  For ANALYZE mode, it needs to be open in one of the following: [OPEN, MOUNTED]. - UpgradeConfigDBValidator.initializeIsDBUp
2020-07-16 15:06:19.825 INFO Content of the file C:\app\oracle\product\12.2.0\dbhome_1\sqlplus\admin\glogin.sql is:
--
-- Copyright (c) 1988, 2005, Oracle.  All Rights Reserved.
--
-- NAME
--   glogin.sql
--
-- DESCRIPTION
--   SQL*Plus global login "site profile" file
--
--   Add any SQL*Plus commands here that are to be executed when a
--   user starts SQL*Plus, or uses the SQL*Plus CONNECT command.
--
-- USAGE
--   This script is automatically run
-- - GLoginLogger.logGlogin



Solution: Check your SQLNET configuration, e.g. set SQLNET.AUTHENTICATION_SERVICES = (NTS), start "lusrmgr" to check the the user account is part of the ORA_DBA group. Be aware, that there can be also some kind of "ORA_<ORACLE_HOME>_DBA" in the "lusrmgr"!

As it is a little bit more special using MS Windows, the documentation for authentication can be found here.
If you use a domain account, have a special look at the documentation part "Overview of Operating System Authentication Enabled at Installation". You need to put this domain account into ORA_DBA AND grant local administrative rights.

Hope that helps you running autoupgrade.jar (even on MS Windows) successful.



ora-07217 / rman-03009 on MS Windows with UNC path that contains dollar sign

A customer of mine had a strange behaviour after upgrade of a database to 19c on MS Windows. He was running in an error while trying to "delete obsolete" in rman.

The error he got was
rman-03009: failure of delete command on ORA_DISK_1 channel
ORA-07217: sltln: environment variable cannot be evaluated.

ORA-07217: sltln: environment variable cannot be evaluated

The reason behind that?
Well, he used a special kind of backup location with a UNC path.


As you can see, the UNC path is located at another server using the "E$" share for the e:\ drive on that server. With 12.1 the usage of the dollar sign wasn't a problem - with 19c, after the upgrade, the database started to throw the "environment variable" error.

There wasn't a chance to get rid of these backups/backup entries in the controlfile and the rman catalog using any crosscheck - delete expired (even with force) - delete obsolete combination.

The only chance we had was to unregister the database from the rman catalog, deleted all the stuff regarding backup from the controlfile repository and register the database again with the rman catalog. After this, we moved all "old" backup files to a new folder and cataloged them again.

And here is how to get rid of the "problematic" entries from the controlfile:

First you have to connect to the database as SYSDBA. then you can run the following select:

 select rownum-1, type from v$controlfile_record_section;  

You need to find the section with the type of the backup things you want to delete. Be aware that you can corrupt your controlfile and your database if you remove the wrong things!

To clear the section in the controlfile you must run the following for every section you want to delete:

 execute sys.dbms_backup_restore.ResetCfileSection(<your_section_id>);

You should be able to delete all backup related information with that. If you run into an error while you reset other things of the controlfile section, then this part is protected.


MS Windows, Virtual Service Accounts and Non-CDB to CDB/PDB conversion

Sometimes, when you test something, you do struggle about something else. This happened to me πŸ™‹while testing the autoupgrade.jar (I will also write a blog update in the next days about the latest version) with a pre-release lab version (thanks to Mike Dietrich for sharing it). 
Part of this pre-release version is the conversion of a non-cdb database into a PDB and plug that automatically into an already existing CDB.
(explanation for the screenshots: ECKES is a 12.2 NON-CDB database, ECKES1 is an empty 19c CDB).

πŸ‘‰ By the way - 19c is the last version where NON-CDB architecture is supported AND you do have 3 (THREE!) pdbs free per CDB with 19c and later. Even with Standard Edition 2 licenses! That's great, so use it!

But back to my tests, what happened?
The old oracle database (ECKES) created a XML metadata file after it was upgraded to 19c. You need this file to plug-in the database later on into an already existing CDB, but the CDB (ECKES1) wasn't able to read this XML metadata file. This can happen in every environment, not only with the autoupgrade-tool!

I've got the following error on every run, even if I did the NON-CDB to PDB migration by myself:
ORA-65026 XML metadata file error : LPX-00202: could not open

(By the way, some people are getting ORA-27041: unable to open file for this error.)

While testing manually, I have found out later on, that the CDB database was able to read the xml only, when it was placed into a subdirectory of this Oracle database version, e.g. %ORACLE_HOME%\database, but not, if it was automatically written by the autoupgrade tool to it's own directories or, e.g., to my c:\temp.

You can see it at the following screenshot, where DBMS_PDB.CHECK_PLUG_COMPATIBILITY succeeded at the first call (c:\oracle\product\19.3.0.0\database\Eckes.xml), but not at the second, the home of the autoupgrade tool (c:\oracle\product\upg_logs\ECKES\...).


It took me some weekend hours to find out why this happens. 
With Oracle 19c, I have installed the database software using a "virtual account", I think, most people will do it that way to avoid to create some special users in Windows. After that, I used the dbca to create an empty CDB for my tests.

The "old" database software is running as "local system" and also the autoupgrade-service from the new home was doing so, while the fresh created 19c CDB was running with the "virtual account" - as "NT Service\OracleService<MySID>". 


When a XML metadata file is created, it is created as "Local System", not as "NT Service\OracleService<MySID>" and therefore, the fresh created file lacks the read/write permission of the ServiceAccounts (ORA_OraDB19Home1_SVCACCTS). 
You can see here, the XML metadata file created at the %ORACLE_HOME% subdirectory does have the rights,


while the XML metadata file created at the autoupgrade.jar home don't have the rights of the ServiceAccount.


My first thoughts were, why is it not enough to have "ORA_DBA" as group for both files, but that's something which is built-in into Windows unfortunately. 

How can you fix that?
If you are doing a NON-CDB to PDB conversion manually, it's easy to choose the right directory - e.g. place the file in the database subdirectory of your new %ORACLE_HOME%. If you want to do it more automated or you want to store the xml metadata file somewhere else, you have to change the Service of the CDB, where you want the database be plugged into. You need to set it to "Local System" for the time of the migration. 



After the migration is done, you can set the service back to the virtual user service account. 

⚡A comment on that: Be aware that you need to restart the service (which restarts your database instance) after you have changed the "logon as" in the MS Windows Service properties!

Another way to fix issues with Oracle databases on MS Windows is to switch to Linux environments, e.g. Oracles database appliances. You can avoid a lot things where you struggle on Windows. πŸ˜‰

Hope that will someone help to avoid hours of investigation.
 

Backup Oracle Database from MS Windows using UNC to Oracle Database Appliance (Samba / CIFS) and Oracle CloudFS

Every customer will help us to build up additional knowledge (in other words, they request something you haven't done or needed somewhere else before).

My actual customer has bought two Oracle Database Appliances, ODA X7-2 HA, and they are migrating all Oracle databases with different versions from the old, VMWare based, Windows environment to the ODA (Virtualized Platform).

After the successful deployment of the ODAs in the customers vlan (maybe worth another post) the question was, how to put the things from the old environments to the ODAs.

Secure copy (scp/Puttys pscp) is ok, but either you need to install putty everywhere or you need to map all server drives at your client and (p)scp all to the ODAs,... not really a fun task.
Also you have an additional step if you create e.g. the RMAN backup locally at the Windows server and then (p)scp it to the ODA. You know it's an additional step which means (down) time and money, so we wanted to avoid this for the time of the migration.
As nfs was not a solution (due to some internal configuration issues) we thought about creating a direct connection between the ODAs and the Windows servers.

CloudFS is a nice feature of ACFS (not only) on the ODAs, but it can't be used without some additional configuration to map a drive at the Windows Server or to use UNC from  RMAN or as directory for Datapump Exports to the ODA.

The customer wants to allow the Windows Server for the time of the migration of all databases to write from any machine directly (without to set any user/password) to the CloudFS on the ODA X7-2 HA, so we had to configure Samba (smb) at the ODA.

If you may need it, here are the steps you can walk through if you want to use CloudFS within UNC paths or if you need to map the CloudFS directory from the ODA to your Windows Server without user/password.
  1. Ensure, that CloudFS is configured and sized right to have enough space for your files. Typically, CloudFS is created when the ODA_BASE is deployed, but you can skip this step. If you have skipped it, you can create CloudFS using the asmca (ASM Configuration Assistent) or you can do it manually. I didn't need it, but I think Matthew described in his cloudfs post very well, how to do it if you don't want to use asmca. Even resize can be done very easy by following this oracle support note.

    To check the existence and the size of your CloudFs, run
    df -h /cloudfs

    CloudFS is mapped on both ODA nodes to /cloudfs. Owner:group should be oracle:oinstall.

  2. Configure Samba at the ODA_BASE (as root), part GLOBAL
    You need to edit the smb.conf file which is located at /etc/samba:
    vi /etc/samba/smb.conf

    Skip to - roundabout - line 100 (Standalone Server Options). There you can see this configuration:
        security = user
        passdb backend = tdbsam

    Change this (even if it's marked deprecated to use security = share) to:
       security = share
       passdb backend = tdbsam
       guest account = oracle


  3. Configure Samba on both nodes with the name and the rights of your share.
    Now it's time to bring your share configuration into the smb.conf file. At approx. line 255 the "Share Defnitions" part starts. There you do need to put in the configuration for your share. The part in [ ] is the name you later see if you use your Windows explorer - so it's the public name of the share: We named it ODAPROD_CLOUDFS, but typically only CLOUDFS is enough.

    [ODAPROD_CLOUDFS]
    comment=cloudfs files
    path=/cloudfs
    browsable=yes
    public = yes
    writable = yes
    printable = no


    After you have inserted this write the smb.conf and quit from vi.

  4. Copy the smb.conf to second node
    To be able to use the share "high available" later on, copy the changed smb.conf from your local nodes /etc/samba/smb.conf to the second node using scp.

  5. Start / Stop the Samba Service on both nodes.
    You need to start the service at both nodes manually.
    To do this, connect as root to ODA_BASE on both nodes and run
    service smb start

    If you want to stop the Samba share, you can run
    service smb stop

  6. Test UNC path from Windows
    You can now test the connection. Open a File Explorer Window at MS Windows. Then you should be able to use the share. Don't use the node names to connect to the share, use the SCAN name of the system, so you are able to use the share even if one of the nodes is not available, e.g. while reboot.

    In my case, we can now use the UNC path from Windows without to specify a user/password to write into /cloudfs at the ODA using in Windows explorer:
    \\ODA-SCAN\ODAPROD_CLOUDFS

    You could also map the share as drive in Windows using the net use command.

    Now we can make backups from the Windows server direct to the ODA, using e.g.
    backup database format '\\ODA-SCAN\ODAPROD_CLOUDFS\%U';

    In addition, we don't need to install putty on all windows servers to pscp e.g. the VM templates for the application VMs we want to use at the virtualized platform.

Some remarks:
  • As this configuration don't need a username and password, you should start and stop the smb service explicitly - don't let it run all the time, start it when needed and stop it if you have put everything onto the ODA.
    It's a question of security and you sure don't want that someone uses the storage of the ODA to put some photos or videos on and share it. 
  • If you need the cloudfs share as a long term solution, use the standard configuration with security, add your share to the smb.conf and map the drive on the MS Windows systems you need it.
  • I don't have registered the smb service to the cluster infrastructure (as it is - in our case - only started when needed). If you want to keep the smb share(s) (so SMB is automatically started after ACFS/databases/...) you can configure that - the solution would be: crsctl add resource
    An example can be found (for Samba) at the documentation of Oracle (this link is for version 12.1)

Slow Autocad / Autodesk - the newer the Oracle database version is, the worser the performance?

The initial situation

One day, not so far before I went to my summer holidays, we got an ask to help one of our customers running Autocad (Autodesk) for a geo information system. The database, autocad is running on, is an 11g Enterprise Edition with spatial and tuning and diagnostics pack.

The runtime for some queries, the customer told me, was over ten minutes - and they would be happy to get results within the application in less than a minute.

As I didn't had any points of contact with Autocad on Oracle database before, I made the decision to visit our customer and to get an impression of the database performance. There I saw 2 different kind of schemas. One user/schema type is normal, but the other one is using virtual private database (VPD). The application running on the vpd user schema was horrible in performance, the same application running on the non vpd user schema was still incredible slow with some statements, but still better. All normal performance and memory parameters have been set to reasonable values. All performance critical things like read-writes, cache hit rates, etc. showed me a very good performing database - all in all, this database seemed to be in a very good condition - which I normaly don't see if we where ask for performance reviews.
I searched on the internet for a possible answer and I found an autocad knowledge base entry named:

AutoCAD Map 3D and Oracle Versioning causes performance degradation

And what I have found there?

Causes:
There will always be a performance degradation once the database is versioned.  The same behavior happens with the Industry Model when the database is job-enabled.  Both implementations use Virtual Private Databases.  There is no conflict in Oracle versioning.

Solution:
Oracle tuning is necessary and requires participation with an Oracle DBA.

Well, not that helpful, also the other entries in the knowledge system of autodesk were not helpful, too (if autocad is slow, you should index - isn't that a job also for an ISV to sell a FAST and STABLE application?)

I first recognized, that most of the slow queries I have seen, were bound to selects from views - views with up to 20 different tables and a lot of joins. The customer then told me, that he have heard from other Autocad users that they stepped back to an old Oracle database version (9i!), as the selects where running faster. The newer the database, the worser the performance? Rule based optimizer beats Cost based optimizer? Sounds like an unsolved riddle, maybe it's also an unsolvable riddle? I didn't hoped so...

So I've asked the customer to get a dump of both schemas and I made a trace file with a small number of the worst performing selects. With this and with my curiosity I hoped to shed some light in the dark at home in my lab...

Tracing and Testing


On my MS Windows 10 (customer is running oracle on MS Windows server) laptop I imported both schemas in my 12.1.0.2 database. After that, I've started with my tests. First I made some tests of the sqls and traced them with a normal sql trace to get also the execution plans. The behavior of my 12.1 database seemed to be totally the same as the 11.2 of our customer, not in total seconds, but in factors of the runtime between non-VPD and VPD schema selects.

Again, I've found a nearly good execution plan for one of the worst statements - even the roundabout 20 joins seemed to be a good choice. But the total runtime was still bad.

Parts of the trace file showed again, that the database executed and fetched the values incredible fast. Again, all parameters and cache hit rates, etc. looked very promising. But there was a very high elapsed and cpu time for parsing the statements:


select count(*) from el_v_wp_sleeve
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1    171.39     173.50          4        276          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.07       0.25        924      13744          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3    171.46     173.75        928      14020          0           1

--------------------------------------------------------------------------------
Together with the customer statement, that autocad is running faster on older oracle versions, I realized that my first thought I had before is right:
It seems to be likely to have some problems within the cost based optimizer as the older versions of oracle used other internal functions in CBO or the RBO. I decided to turn on the cost based optimizer tracing:

alter session set events '10053 trace name context forever, level 1';

Some test executions and 2 GB of trace files later, I started my investigation. What was happening in the parse phase that was so exhausting for the optimizer to blow up the runtime to nearly 3 minutes, when executing and fetch only do need a quarter of a second? It didn't took me that long to find out, that the optimizer was trying a lot of different execution and join plans to find the best one. And - at the end - the plan found and used is really good - this was crystal clear by looking at the execution and fetch times.

The system statistics, the optimizer uses, are fine:

-----------------------------
SYSTEM STATISTICS INFORMATION
-----------------------------
Using dictionary system stats.
  Using NOWORKLOAD Stats
  CPUSPEEDNW: 3305 millions instructions/sec (default is 100)
  IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
  IOSEEKTIM:  10 milliseconds (default is 10)
  MBRC:       NO VALUE blocks (default is 8)

And the Table and Index Stats in the Base Statistical Information didn't show any strange values. But in the optimizer optimation part of the trace file, I've found a couple of different trys: Considering view merge, considering outer-join elimination, considering predicate, find best directive, ... and again considering, find directive ... and again considering, ...Obvious to say - most of them are
--- snip ---
rejected
OJE:   outer-join not eliminated
OJE: End: finding best directive for query block SEL$2 (#0)
CVM:   Checking validity of merging in query block SEL$3 (#0)
CVM: Considering view merge in query block SEL$3 (#0)
OJE: Begin: find best directive for query block SEL$3 (#0)
OJE: End: finding best directive for query block SEL$3 (#0)
SVM:     SVM bypassed: Query NO MERGE hint.
CVM: Considering view merge in query block SEL$4 (#0)
OJE: Begin: find best directive for query block SEL$4 (#0)
OJE: Considering outer-join elimination on query block SEL$4 (#0)
OJE: considering predicate"SP"."FID_ATTR"="IP"."FID"
--- snip end ---

Considering so many different possible execution plans made it at the end to a fast execution plan, but, the next time this statement executes, it starts parsing from the beginning, considering again a lot of possibilities. I never have seen that behavior before, but as I have found the problem, I knew, there will be some kind of workaround.

Speeding up performance from minutes to parts of seconds


Finding the problem is normally 80 percent of the solution - so I was happy to find some kind of root cause, even if I didn't know if this could be normal behavior or if this is a bug in the optimizer.

And the optimizer said: Help me - Hint me
The first thing I have tested was to tune the queries in the non-VPD schema. This is the most relevant case for our customer. After searching in google and in Oracle support a lot, trying to change session (or system parameters) to other values, I decided to create some more indexes (more than 10 new ones) on the tables that are used in the view. This speeded up the parse phase - for a couple of seconds, but it was still a parse phase nearly 3 minutes in time. So I knew, the new indexes are used in the new execution plan and the new execution plan executed and fetched faster as the old one. Speeding up the execution and fetch phase from 0.25 seconds to 0.17 - great work!
But as the customer problem was not the execution and fetch phase, it still was not a solution. As I knew the query and the final execution plan, I started to put some hints in the view - I wanted to tell the optimizer more to let him less decisions to consider. Trying different Index and Use_-/NO_USE hints also speeded up the parse time for seconds, but it was still some boring 2 minutes in time. One of the last shots I wanted to try fitted: Creating the view with a NO_QUERY_TRANSFORMATION hint. Great!

SELECT /*+ NO_QUERY_TRANSFORMATION */ G.FID, G.SLEEVE_SPECIFIC_TYPE,
  G.FID_ATTR, G.ORIENTATION, G.DISPLAY_COLOR, G.ID_SLEEVE_TYPE, G.SLEEVE_TYPE,
   G.ID_VOLTAGE, G.VOLTAGE, G.ID_DISPOSITION_STATE, G.DISPOSITION_STATE,
  G.ID_ACCURACY, G.ACCURACY, G.DATE_INSTALLATION, G.ID_SLEEVE_CONSTRUCTION,
  G.SLEEVE_CONSTRUCTION, G.ID_SLEEVE_SPECIFIC_TYPE, G.GEOM.SDO_POINT.X,
  G.GEOM.SDO_POINT.Y, G.GEOM.SDO_POINT.Z
FROM
 EL_V_WP_SLEEVE G

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      1.01       1.02          0        210          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        6      0.01       0.02          0       2951          0         569
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        8      1.03       1.05          0       3161          0         569

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 104     (recursive depth: 1)

I have reduced the parse time from 3 minutes to 1 second. Good enough for our customer, so I stopped with more investigations on the non-VPD schema.

The next step: Will my new hint also fit to the VPD schema? What's your guess? Oh yes, you are totally right. 
NO!!
Using the hint reduced the parsing time for selects on the view in the VPD schema by some seconds, but the parsing time was still some minutes also here. Creating and testing the VPD policy is part of the parsing phase. That means, it is a must have to check the PL/SQL function which is executed for the VPD policy - in this case it was running roundabout 2 or 3 seconds with a high number of queries and some PL/SQL stuff. Not a huge time killer...

And the optimizer said: Help me - with database/session parameters

Back to start - Tracing 10053 with VPD. And yes, it was the same problem, the optimizer still is considering hundreds of paths/changes/joins/predictions and nearly never comes to an end. But the execution and fetch phase - still incredible fast. I knew why - the VPD workflow is killing my hint somewhere.

It was more or less just a little try to change some of the system parameters. But one parameter (and ONLY this one) worked:

alter session set "_optimizer_cost_based_transformation"=off;

Later on, I have found another blog with some cost based optimizer related problems. There the guy  was setting _btree_bitmap_plans and optimizer_index_cost_adj in addition, but changing both parameters did not made any difference on the total statement execution time. I've gotten, for the VPD schema, a really good two to five second runtime (spending nearly 5 minutes before).

Ok, I have two different approaches to push the Autocad performance: For VPD schemas I can set the system or session parameter _optimizer_cost_based_transformation. For non vpd schemas creating the views (or using SQL Patch) with a NO_QUERY_TRANSFORMATION hint also speeds up. But vice versa? No, I have to use both approaches in parallel.

And the optimizer said: Help me - give me a goal
As we do let the customer decide, which solution they would implement, I checked for another possibility that is used not often (enough) in my opinion: DBMS_SPM allows to create sql plan baselines. This feature is part of the Enterprise Edition without licensing Diagnostics and Tuning Pack (https://blogs.oracle.com/optimizer/does-the-use-of-sql-plan-management-and-the-dbmsspm-database-package-require-a-tuning-or-diagnostic-pack-license).

Why is using an SQL Plan Baseline a good choice here? Because we know, that after parsing, the execution plans are running fast as hell (More information of managing baselines can be found here: https://docs.oracle.com/database/121/TGSQL/tgsql_spm.htm#TGSQL94621). I run the statement (after flushing the sga) again without any hint and without the _optimizer_cost_based_transformation=off session/system parameter to get my plan.
This time, the execution was as slow as I knew from the beginning. Then I captured the plan from the cursor cache and created a SQL Baseline:

SQL> variable cnt number;
SQL> execute :cnt := dbms_spm.load_plans_from_cursor_cache(sql_id=>'1pmbtxzgktxfj')

That's it, folks! After that, I have checked by querying dba_sql_plan_baselines that the baseline was accepted and enabled.
Then I have re-run the statement again. As the cost based optimizer now skips any optimization after hard parse (creating sql-id, checking statement syntax and rights and permissions), the statement just "executes" and "fetches". So all the statements running minutes before are now running in parts of seconds.

Conclusion

 

As you can see - as often in Oracle databases there isn't a single truth. If you can find a root case (and typically you will), you can (if it is not a bug) find a workaround. For this Autocad problem, the customer has chosen to implement the system parameter and to change the views. This is fast enough for them and it is easier to handle as DBMS_SPM (where they do need all SQL-IDs from the slow running queries).