Friday, 10 July 2015

OPEN_CURSORS in Oracle


Open_Cursor Parameter , in this article we will discuss what this parameter do  , I used Oracle Documentation to describe this parameter but in simpler way .

In Oracle Documentation

Open_cursor : specifies the maximum number of open cursors (handles to private SQL areas) a session can have at once. You can use this parameter to prevent a session from opening an excessive number of cursors.

to check in database

    SQL> show parameter Open_cursor

    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    open_cursors                         integer     300
    

As we see in the last Line , "its prevent Session from opening excessive number of cursor"  how is that !!!

Open_cursor located in shared_pool which is part of SGA ( library Cache) , The benefit of this parameter is to prevent Session clogging CPU with requests .

But what i mean when I set this Parameter to integer , let take the above example :

-Parameter is set to 300
-That mean each session can have  300 cursors

If this session fill the 300 What will happened !!!

     "ora-1000 maximum open cursors exceeded"

On Documentation Oracle Recommended to set this Parameter for high value  for Application usage , if the above error raised and you already set to high Value then make sure your developer is closing their cursor and this is common issue.

    SQL> Show parameter cursor

    NAME                                      TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    cursor_sharing                             string      EXACT
    cursor_space_for_time                boolean     FALSE
    open_cursors                               integer     300
    session_cached_cursors               integer     20


But what others Parameter mean,  what each parameter mean lets ask this question what if User or session run query include the same cursor , is it take another space in memory !!!

it dose not make sense , so in this case we use SESSION_CACHED_CURSOR.

regarding to oracle documentation

SESSION_CACHED_CURSOR : its Number of session cursors to cache. Repeated parse calls of the same SQL statement cause the session cursor for that statement to be moved into the session cursor cache. 

you have to know some truth about this parameter :
1) its cache only close cursor which mean if you cursor still opened how could it be cached !!!

2) you can set this parameter > OPEN_CURSOR , < OPEN_CURSOR Or equal OPEN_CUROSR , that indicate us between relation between this parameter ----> NOTHING.

3) if you are not setting this parameter ( Value 0 ) then no cursor will be cached for session . But Wait we said oracle used shared pool in cursor Yes , your cursor will be in SHARED_POOL but session have to find this cursor , so if you set to non zero first thing oracle will do is check SHARED_POOL ( Library cache ) and back to you with result .


After discuss point number 3 we see the main advantage for cache cursor which is better performance , enhance query execution time.

But the shared_pool has limited size so i can't cache all my cursor , now next parameter will avoid this

CURSOR_SPACE_FOR_TIME

Boolean value (TURE|FALSE) each one of them mean something

FALSE : Shared SQL areas can be deallocated from the library cache to make room for new SQL statements.

TRUE : Shared SQL areas are kept pinned in the shared pool , if you are using application contain lot of cursor it will be good to set it to enhance execution time ( to do that shared pool must be large enough to hold all open cursors simultaneously) .


If we have 3 query each one want to use same cursor how oracle handle this , Parameter number 4 will control that.

CURSOR_SHARING

CURSOR_SHARING determines what kind of SQL statements can share the same cursors.

this parameter take three value ( FORCE | SIMILAR | EXACT ) i will describe each one of them , Oracle Documentation definition : 

-Forces statements that may differ in some literals, but are otherwise identical, to share a cursor, unless the literals affect the meaning of the statement.

-Similar Causes statements that may differ in some literals, but are otherwise identical, to share a cursor, unless the literals affect either the meaning of the statement or the degree to which the plan is optimized.

-Exact Only allows statements with identical text to share the same cursor.

you can't imagine how many document you will find if you search on google for this parameter , examples , article and tuning for it.

to set this parameter you have to make sure what you need , understand it.the best way to do that with trying to test it.

Thanks
NJ
 Reclaim Space in Tablespace using Shrink Command

    SQL> ALTER TABLE TABLE_NAME enable ROW movement;

    SQL> ALTER TABLE TABLE_NAME shrink SPACE;

    SQL> ALTER TABLE TABLE_NAME disable ROW movement;


Benefits regarding to Oracle Documentation :

    Full table scans will take less time (a table scan will always scan up to the HWM even if space is not used)
    Better index access takes place because of a smaller B-Tree
    Space is freed up for other database objects
    Space below the HWM is released and the HWM is moved down
Spool File With Date/Time Name


Amazing way to spool  automatically :

    SET TERMOUT OFF
    COLUMN today_ddmmyyyy_col NEW_VALUE today_ddmmyyyy
    SELECT TO_CHAR ( SYSDATE, 'DDMMYYYY') AS today_ddmmyyyy_col
    FROM    dual;
    SET TERMOUT ON
    SPOOL log_&today_ddmmyyyy..log

Thanks.
ORA-01438 Which Column

ORA-01438: value larger than specified precision allowed for this column


You will receive this error while trying to insert big Value In Column with Specific Range , But How Could You know Which Column is it i will some hint that could help you to do that :

Hint #1 :

1-ORA-01438  : For Numeric Value
2-ORA-12899  : For Varchar2 Value

Hint #2 :

Enable Audit On know which One of these Column caused the error

    SQL > Create table test as select * from scott.dept

    SQL> desc dept
     Name                                Null?    Type
     ----------------------------------- -------- ------------------------
     DEPTNO                              NOT NULL NUMBER(2)
     DNAME                                        VARCHAR2(14)
     LOC                                          VARCHAR2(13)
    
    SQL> audit insert on test.test whenever not successful;
    
    Audit succeeded.
    
    SQL> insert into test.test values(2000,'test','test');
    insert into scott.dept values(2000,'test','test')
                                  *
    ERROR at line 1:
    ORA-01438: value larger than specified precision allowed for this
    column
    
    
    SQL> select sql_text,returncode from dba_audit_trail
      2  where owner='test' and obj_name='TEST';
    
    SQL_TEXT
    ----------------------------------------------------------------------
    RETURNCODE
    ----------
    insert into scott.dept values(2000,'test','test')
          1438

 Hint #3 :

Enable Tracing Level 1438


SQL > conn test/test ;
SQL> create table test as select * from scott.dept ;

SQL> select * from test ;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON


SQL> alter system set events='1438 trace name Errorstack forever,level 10';


SQL> insert into test values (100000000000000000,'test','JOR');                        
insert into test values (100000000000000000,'test','JOR')
                         *
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column

In Trace File :

ORA-01438: value larger than specified precision allowed for this column
Current SQL statement for this session:
insert into test values (100000000000000000,'test','JOR')

Thanks.
NJ
Encrypt Your PL/SQL Code Using Wrap Command


Today I will make demonstration how to hide your code , Function , Procedure and anything Related to PL/SQL Code , to do this you have to know wrap utility in oracle .

Step #1:

You Have to Write Sample Code to Make test on it .

Sample Code :

    SQL> CREATE OR REPLACE PROCEDURE testproc
    IS
    BEGIN
       DBMS_OUTPUT.PUT_LINE('Wrap Me!');
     END;
    /
    Procedure created.


Ensure Procedure Run Successfully :

    SQL> exec testproc

    PL/SQL procedure successfully completed.


The above Steps Just to make sure our Procedure will run suceesfully without any error , now i will delete it again and start using wrap to encrypt.

    SQL> conn test/test;
    Connected.
    SQL>
    SQL> drop procedure testproc ;

    Procedure dropped.

Step #2:

Using Wrap to Create plb File .

-Save Above Procedure in File Called TestProc.sql under home>>oracle .

    C:\Documents and Settings\Ramtech> wrap iname=Testproc.sql

    PL/SQL Wrapper: Release 10.2.0.5.0- Production on Mon Dec 03 22:42:14 2012

    Copyright (c) 1993, 2004, Oracle.  All rights reserved.

    Processing Testproc.sql to Testproc.plb

 OR

If i want to get my procedure script wrapped and no one can read my file :


    C:\Documents and Settings\Ramtech> wrap iname=Testproc.sql oname=wrapped.sql

    PL/SQL Wrapper: Release 10.2.0.5.0- Production on Mon Dec 03 22:46:12 2012

    Copyright (c) 1993, 2004, Oracle.  All rights reserved.

    Processing Testproc.sql to wrapped.sql


Open Wrapped.sql

    C:\Documents and Settings\Ramtech> more wrapped.sql
    CREATE OR REPLACE PROCEDURE testproc wrapped
    a000000
    1
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    7
    49 85
    SOwY8JEJe1MROnuBTksxRTO9iJ4wg5nnm7+fMr2ywFwWoWLRPhaXroubdIvAwDL+0oYJjwlp
    uFKbskr+KLK957KzHQYwLK4k6rKBpVHb4USaw+kyLvYOxeokH/Y5pkT0tnU=

    /
    

Step #3:

Now I want to create procedure in my database :

    C:\Documents and Settings\Ramtech> sqlplus test/test

    SQL*Plus: Release 10.2.0.5.0 - Production on Mon Dec 3 22:48:03 2012

    Copyright (c) 1982, 2010, Oracle.  All Rights Reserved.


    Connected to:
    Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options

    SQL> @Testproc.plb

    Procedure created.

    SQL>
    SQL>
    SQL> exec Testproc

    PL/SQL procedure successfully completed.


Thanks.
NJ
ORA-00265: instance recovery required, cannot set ARCHIVELOG mode


SQL> shutdown immediate ;
ORA-01109: database not open


Database dismounted.
ORACLE instance shut down.
SQL> startup mount ;
ORACLE instance started.

Total System Global Area  285212672 bytes
Fixed Size                  2095704 bytes
Variable Size             155190696 bytes
Database Buffers          121634816 bytes
Redo Buffers                6291456 bytes
Database mounted.
SQL> alter database archivelog ;
alter database archivelog
*
ERROR at line 1:
ORA-00265: instance recovery required, cannot set ARCHIVELOG mode


SQL> shutdown immediate ;
ORA-01109: database not open


Database dismounted.
ORACLE instance shut down.
SQL> startup ;
ORACLE instance started.

Total System Global Area  285212672 bytes
Fixed Size                  2095704 bytes
Variable Size             155190696 bytes
Database Buffers          121634816 bytes
Redo Buffers                6291456 bytes
Database mounted.
Database opened.
SQL>

SQL> SQL> shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount ;
ORACLE instance started.

Total System Global Area  285212672 bytes
Fixed Size                  2095704 bytes
Variable Size             155190696 bytes
Database Buffers          121634816 bytes
Redo Buffers                6291456 bytes
Database mounted.
SQL> alter database archivelog;

Database altered.

Thanks.

NJ
ORA-16024: parameter LOG_ARCHIVE_DEST_1 cannot be parsed
ORA-16024: parameter LOG_ARCHIVE_DEST_1 cannot be parsed


Cause:
Missing Space Issue

Solution
log_archive_dest_1 = 'LOCATION=D:\app\Ramtech\oradata\orcl\ VALID_FOR=(ALL_LOGFILES,ALL_ROLES)DB_UNIQUE_NAME=orcl'

Should be

log_archive_dest_1 = 'LOCATION=D:\app\Ramtech\oradata\orcl\ VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=orcl'
Bounce Standby Database


Shutdown Standby Database :


    sqlplus /as sysdba
    alter database recover managed standby database cancel;
    shutdown;



Startup Standby Database :


     sqlplus /as sysdba
     startup nomount
     alter database mount standby database
     alter database recover managed standby database disconnect from session;

Thanks.



Some Commands To Deal With Standby Database


Open Standby In Read Only :

    SQL> RECOVER MANAGED STANDBY DATABASE CANCEL;
    SQL> ALTER DATABASE OPEN READ ONLY;

Back to Mount Point ( Same as Before Open in Read Only ) :

    SQL > shutdown;
    SQL > startup nomount
    SQL > alter database mount standby database
    SQL > alter database recover managed standby database disconnect from session;

Switch Over Primary As Standby , And Standby As Primary

Primary Database : Prim
Standby Database : Stdby

On Prim :

    SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY;
    SQL> SHUTDOWN NORMAL;
    SQL> STARTUP NOMOUNT;
    SQL> ALTER DATABASE MOUNT STANDBY DATABASE;



On standby:

    SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
    SQL> SHUTDOWN;
    SQL> STARTUP;


On Prim :

    SQL> ALTER DATABASE RECOVDR MANAGED STANDBY DATABASE;



On standby:

    SQL> ALTER SYSTEM ARCHIVE LOG START;
    SQL> ALTER SYSTEM SWITCH LOGFILE;


Thanks.





Bulid Logical Database


We Post Earlier What is the Different Between Logical Database and Standby Database , Both Are Type For Data Guard .


Today we will take about how to configure Logical Database , to do this you must first create Physical Standby Which i mention it before , And you can Follow the link .

for 10g,11g you can use the same steps , Now After create physical Standby Database , And Make sure its working Without any problem , You Have to follow the below steps to Create Oracle Logical Standby.


Steps to convert Standby Database to Logical Standby Database :

Step #1 :

in this step logminer Dictionary Must be Built into redo data. ( Build LogMiner Tables for Dictionary)

On Primary

    SQL> begin
      2  dbms_logstdby.build;
      3  end ;
      4  /



OR

     SQL> execute dbms_logstdby.build;


Step #2:

Now we have stop Managed recovery between primary and standby :

On Standby :


    SQL> alter database recover managed standby database cancel ;

    Database altered.


Step #3 :

Convert Physical Standby to Logical Standby .

On Standby :


    SQL> alter database recover to logical standby stdby ;

    Database altered.


Notices : If this command hang and take to much Time then Back to step #1 and did it again .

Step #4:

On Standby ( New Logical)  we open it in Resetlog mode .


On New Logical ( Standby) :

    SQL> shutdown immediate ;
    ORA-01507: database not mounted


    ORACLE instance shut down.

    SQL> startup mount ;
    ORACLE instance started.

    Total System Global Area  839282688 bytes
    Fixed Size                  2217992 bytes
    Variable Size             532678648 bytes
    Database Buffers          301989888 bytes
    Redo Buffers                2396160 bytes
    Database mounted.

    SQL>
    SQL>
    SQL> alter database open resetlogs ;

    Database altered.


Step #5:

Start Apply Service On logical


    SQL> alter database start logical standby apply ;

    Database altered.


OR


    SQL> alter database start logical standby apply immediate ;
    Database altered.


Just As Check if everything Goes Fine :

    SQL> select database_role , Name from v$database ;

    DATABASE_ROLE    NAME
    ---------------- ---------
    LOGICAL STANDBY  STDBY


Thanks.


Startup/Shutdown Logical Standby Database


Simple Steps to do that


Shutdown Steps :

On Primary do the following :

    SQL > alter system switch logfile ;
    SQL > alter system archive log current ;


Go to Standby :

    SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
    SQL> shutdown immediate;

Primary Database :

    SQL> shutdown immediate;


Startup Steps :

Primary Database


    SQL>startup;

 Standby Database:

    SQL > startup
    SQL > alter database start logical standby apply immediate ;


Thanks.



RMAN Snapshot Controlfile for RAC database in 11gR2


Just thought of quickly updating the change made in RMAN Snapshot Controlfile behavior for RAC database with Oracle 11gR2 and later. Well, if you are wondering why post 11gR2 upgrade the RMAN Snapshot Controlfile backup for your RAC database is failing with 'ORA-00245: control file backup operation failed', here is the reason plus  a workaround to tackle the issue.


According to MOS [ID 1263621.1], it is an expected behavior with 11gR2 or later in contrast to earlier Oracle versions.  Since all instances of the RAC database shares the same snapshot controlfile, you must ensure that the SCF for a RAC database is configured on a shared device plus all instances of the RAC database must have access to the file.


The error in the context is likely to appear if all instances of  RAC database can't access the snapshot controlfile. Therefore, the following RMAN configuration across all instances (on each node) should avoid the situation:


Syntax:


RMAN>  CONFIGURE SNAPSHOT CONTROLFILE NAME TO ;




References:
RMAN Snapshot Controlfile Must Reside on Shared Device for RAC database in 11g [ID 1263621.1]


Wednesday, 8 July 2015

Diagnosing and Repairing Failures with 11g Data Recovery Advisor

The 11g Data Recovery Advisor is part of the 11g database health checking framework and diagnoses persistent data failures and not only presents options to repair and fix the problem but also can execute the repair and recovery process at our request.

The Repair Advisor can take away lot of the stress associated with peforming backup and recovery by diagnosing what is wrong as well as presenting us with the syntax as well to execute the commands to restore and recover as the case may be. Under pressure, everyone can make mistakes and it is comforting to know that there is a tool which can really he;p the DBA.

The Data Recovery Advisor can be used via OEM Database or Grid Control or via the RMAN command line interface.

Let us look at an example of using the RMAN Data Recovery Advisor to recover from a loss of control files situation with and without the CONTROL AUTOBACKUP option being enabled.

Note, that when there is no control file autobackup, the RMAN Repair Advisor is not able to do the full automated recovery for us and we use a combination of automatic and manual repair to fix the problem.


Scenario is loss of control files – AUTOBACKUP is enabled


RMAN> list failure;

using target database control file instead of recovery catalog
List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5652 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl is missing
5649 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/oradata/sqlfun/control01.ctl is missing

RMAN> advise failure;

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5304 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl is missing

analyzing automatic repair options; this may take some time
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=133 device type=DISK
analyzing automatic repair options complete

Mandatory Manual Actions
========================
no manual actions available

Optional Manual Actions
=======================
no manual actions available

Automated Repair Options
========================
Option Repair Description
—— ——————
1 Use a multiplexed copy to restore control file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_632546057.hm

RMAN> repair failure preview;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_632546057.hm

contents of repair script:
# restore control file using multiplexed copy
restore controlfile from ‘/u01/app/oracle/oradata/sqlfun/control01.ctl';
sql ‘alter database mount';

RMAN> repair failure;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_632546057.hm

contents of repair script:
# restore control file using multiplexed copy
restore controlfile from ‘/u01/app/oracle/oradata/sqlfun/control01.ctl';
sql ‘alter database mount';

Do you really want to execute the above repair (enter YES or NO)? YES
executing repair script

Starting restore at 18-JUN-12
using channel ORA_DISK_1

channel ORA_DISK_1: copied control file copy
output file name=/u01/app/oracle/oradata/sqlfun/control01.ctl
output file name=/u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl
Finished restore at 18-JUN-12

sql statement: alter database mount
released channel: ORA_DISK_1
repair failure complete

Do you want to open the database (enter YES or NO)? YES
database opened

RMAN>

RMAN> list failure;

no failures found that match specification


Scenario is loss of control files – No AUTOBACKUP


RMAN> list failure;

using target database control file instead of recovery catalog
List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5652 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl is missing
5649 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/oradata/sqlfun/control01.ctl is missing

RMAN> advise failure;

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5652 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl is missing
5649 CRITICAL OPEN 18-JUN-12 Control file /u01/app/oracle/oradata/sqlfun/control01.ctl is missing

analyzing automatic repair options; this may take some time
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=135 device type=DISK
analyzing automatic repair options complete

Mandatory Manual Actions
========================
1. If file /u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl was unintentionally renamed or moved, restore it
2. If file /u01/app/oracle/oradata/sqlfun/control01.ctl was unintentionally renamed or moved, restore it
3. If you have a CREATE CONTROLFILE script, use it to create a new control file
4. Contact Oracle Support Services if the preceding recommendations cannot be used, or if they do not fix the failures selected for repair

Optional Manual Actions
=======================
1. If a standby database is available, then perform a Data Guard failover initiated from the standby

Automated Repair Options
========================
no automatic repair options available

RMAN> repair failure preview;

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of repair command at 06/18/2012 11:00:06
RMAN-06953: no automatic repairs were listed by ADVISE FAILURE

Find the last database backup of control file in FRA

RMAN> restore controlfile from ‘/u01/app/oracle/flash_recovery_area/SQLFUN/autobackup/2012_06_18/o1_mf_s_786251074_7xwbl3l4_.bkp';

Starting restore at 18-JUN-12
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=125 device type=DISK

channel ORA_DISK_1: restoring control file
channel ORA_DISK_1: restore complete, elapsed time: 00:00:02
output file name=/u01/app/oracle/oradata/sqlfun/control01.ctl
output file name=/u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl
Finished restore at 18-JUN-12

RMAN> list failure;

no failures found that match specification

RMAN> alter database mount;

database mounted
released channel: ORA_DISK_1

RMAN> alter database open resetlogs;

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of alter db command at 06/18/2012 11:36:01
ORA-01194: file 1 needs more recovery to be consistent
ORA-01110: data file 1: ‘/u01/app/oracle/oradata/sqlfun/system01.dbf’

RMAN> list failure;

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5898 CRITICAL OPEN 18-JUN-12 System datafile 1: ‘/u01/app/oracle/oradata/sqlfun/system01.dbf’ needs media recovery
5895 CRITICAL OPEN 18-JUN-12 Control file needs media recovery
8 HIGH OPEN 18-JUN-12 One or more non-system datafiles need media recovery

RMAN> advise failure;

Starting implicit crosscheck backup at 18-JUN-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=125 device type=DISK
Crosschecked 3 objects
Finished implicit crosscheck backup at 18-JUN-12

Starting implicit crosscheck copy at 18-JUN-12
using channel ORA_DISK_1
Crosschecked 5 objects
Finished implicit crosscheck copy at 18-JUN-12

searching for all files in the recovery area
cataloging files…
cataloging done

List of Cataloged Files
=======================
File Name: /u01/app/oracle/flash_recovery_area/SQLFUN/backupset/2012_06_18/o1_mf_ncsnf_TAG20120618T112825_7xx83b9m_.bkp
File Name: /u01/app/oracle/flash_recovery_area/SQLFUN/autobackup.old/2012_06_18/o1_mf_s_786277031_7xx3x7pw_.bkp.old
File Name: /u01/app/oracle/flash_recovery_area/SQLFUN/autobackup.old/2012_06_18/o1_mf_s_786251074_7xwbl3l4_.bkp
File Name: /u01/app/oracle/flash_recovery_area/SQLFUN/autobackup.old/2012_06_18/o1_mf_s_786281256_7xx8184v_.bkp
File Name: /u01/app/oracle/flash_recovery_area/SQLFUN/autobackup.old/2012_06_18/o1_mf_s_786279412_7xx67nlv_.bkp

List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
———- ——– ——— ————- ——-
5898 CRITICAL OPEN 18-JUN-12 System datafile 1: ‘/u01/app/oracle/oradata/sqlfun/system01.dbf’ needs media recovery
5895 CRITICAL OPEN 18-JUN-12 Control file needs media recovery
8 HIGH OPEN 18-JUN-12 One or more non-system datafiles need media recovery

analyzing automatic repair options; this may take some time
using channel ORA_DISK_1
analyzing automatic repair options complete

Mandatory Manual Actions
========================
no manual actions available

Optional Manual Actions
=======================
1. If you have the correct version of the control file, then shutdown the database and replace the old control file
2. If you restored the wrong version of data file /u01/app/oracle/oradata/sqlfun/system01.dbf, then replace it with the correct one
3. If you restored the wrong version of data file /u01/app/oracle/oradata/sqlfun/sysaux01.dbf, then replace it with the correct one
4. If you restored the wrong version of data file /u01/app/oracle/oradata/sqlfun/undotbs01.dbf, then replace it with the correct one
5. If you restored the wrong version of data file /u01/app/oracle/oradata/sqlfun/users01.dbf, then replace it with the correct one
6. If you restored the wrong version of data file /u01/app/oracle/oradata/sqlfun/threatened_fauna_data.dbf, then replace it with the correct one

Automated Repair Options
========================
Option Repair Description
—— ——————
1 Recover database
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_2266295139.hm

RMAN> repair failure preview;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_2266295139.hm

contents of repair script:
# recover database
recover database;
alter database open resetlogs;

RMAN> repair failure noprompt;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/sqlfun/sqlfun/hm/reco_2266295139.hm

contents of repair script:
# recover database
recover database;
alter database open resetlogs;
executing repair script

Starting recover at 18-JUN-12
using channel ORA_DISK_1

starting media recovery

archived log for thread 1 with sequence 1 is already on disk as file /u01/app/oracle/oradata/sqlfun/redo01.log
archived log file name=/u01/app/oracle/oradata/sqlfun/redo01.log thread=1 sequence=1
media recovery complete, elapsed time: 00:00:01
Finished recover at 18-JUN-12

database opened
repair failure complete

RMAN>
RMAN 11g new feature - Backup Fast Recovery Area (FRA) to Disk

In Oracle 11gR2, there is a good new feature whereby we can backup the fast or flash recovery area to a disk location which could be a remote destination via a NFS attached file system.

In earlier releases, we could only backup the Flash Recovery Area to tape and not disk via RMAN.

Recovery from disk in most cases is significantly faster than recovery from a tape device especially when we have a very large tape library and the right tape needs to be located or maybe we have a case where all tape drives are already in use and we have to perform a critical database recovery at the same time.

The OSS or Oracle Suggested Strategy for backups involves a disk based backup method and level 0 datafile copies and subsequent leevl 1 incremental backupsets are all stored on local disk.

So what happens if we lose the local server and with it all our disk based backups? – we have to do a full database restore from tape which can be very time consuming.

The 11g RMAN command BACKUP RECOVERY AREA TO DESTINATION lets us specify a secondary backup location for all our backups which are stored in the Fast Recovery Area.

In this example we are backing up the FRA on a daily basis after the OSS backup to disk completes via the command:

backup recovery area to destination ‘/mnt/remote/backups/orasql/FRA_BACKUP/’

If we run a LIST BACKUP OF DATABASE we can see that there are two copies of the backupset #479. One stored in the FRA on the local server /u01 file system and one in the remote location which is a file server attached via NFS to the local server.

List of Backup Pieces for backup set 479 Copy #1
    BP Key  Pc# Status      Piece Name
    ------- --- ----------- ----------
    565     1   AVAILABLE   /u01/app/oracle/flash_recovery_area/SQLFUN/backupset/2012_08_01/o1_mf_nnnd1_ORA_OEM_LEVEL_0_81jgs7qf_.bkp

  Backup Set Copy #2 of backup set 479
  Device Type Elapsed Time Completion Time Compressed Tag
  ----------- ------------ --------------- ---------- ---
  DISK        00:00:18     01-AUG-12       NO         ORA_OEM_LEVEL_0

    List of Backup Pieces for backup set 479 Copy #2
    BP Key  Pc# Status      Piece Name
    ------- --- ----------- ----------
    571     1   AVAILABLE   /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_08_01/o1_mf_nnnd1_ORA_OEM_LEVEL_0_81jh0x4l_.bkp

Let us now test a restore using this remote backup location by simulating a total server failure where we lose all our disk based backups residing on the local server which has crashed.

To simulate a total server crash I do the following:

Shutdown the database.
Rename the directory holding the data files of the database
Rename the spfile and init.ora file
Rename the FRA directory for the database so that RMAN cannot find the local backups in the FRA

When we perform the restore and recovery, RMAN finds that it cannot access the backups stored in the FRA (because we have renamed the directory).

It will now try and restore the copy of the FRA backups which was stored in the remote location.

This can be seen from the RMAN ouput like “reading from backup piece /mnt/remote/backups/orasql/FRA_BACKUP” ….
RESTORE SPFILE

RMAN> startup force nomount;

startup failed: ORA-01078: failure in processing system parameters
LRM-00109: could not open parameter file '/u01/app/oracle/product/11.2.0/dbhome_1/dbs/initsqlfun.ora'

starting Oracle instance without parameter file for retrieval of spfile
Oracle instance started

Total System Global Area     158662656 bytes

Fixed Size                     2211448 bytes
Variable Size                 92275080 bytes
Database Buffers              58720256 bytes
Redo Buffers                   5455872 bytes

RMAN> restore spfile from '/mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_ncsnf_TAG20120528T080501_7w5oo92y_.bkp';

Starting restore at 28-MAY-12
using channel ORA_DISK_1

channel ORA_DISK_1: restoring spfile from AUTOBACKUP /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_ncsnf_TAG20120528T080501_7w5oo92y_.bkp
channel ORA_DISK_1: SPFILE restore from AUTOBACKUP complete
Finished restore at 28-MAY-12

RMAN> shutdown immediate;

Oracle instance shut down

RMAN> startup nomount;

connected to target database (not started)
Oracle instance started

Total System Global Area     801701888 bytes

Fixed Size                     2217632 bytes
Variable Size                490735968 bytes
Database Buffers             301989888 bytes
Redo Buffers                   6758400 bytes

RESTORE CONTROFILE

RMAN> restore controlfile from  '/mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_ncsnf_TAG20120528T080501_7w5oo92y_.bkp';

Starting restore at 28-MAY-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=134 device type=DISK

channel ORA_DISK_1: restoring control file
channel ORA_DISK_1: restore complete, elapsed time: 00:00:01
output file name=/u01/app/oracle/oradata/sqlfun/control01.ctl
output file name=/u01/app/oracle/flash_recovery_area/sqlfun/control02.ctl
Finished restore at 28-MAY-12

RMAN> alter database mount;

database mounted
released channel: ORA_DISK_1

RESTORE DATABASE

RMAN> catalog start with  '/mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN';

searching for all files that match the pattern /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN

List of Files Unknown to the Database
=====================================
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T081134_7w5oob2y_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T093614_7w5ongvb_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_ncsnf_TAG20120528T080501_7w5oo92y_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_nnndf_TAG20120528T080501_7w5onhys_.bkp

Do you really want to catalog the above files (enter YES or NO)? YES
cataloging files...
cataloging done

List of Cataloged Files
=======================
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T081134_7w5oob2y_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T093614_7w5ongvb_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_ncsnf_TAG20120528T080501_7w5oo92y_.bkp
File Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_nnndf_TAG20120528T080501_7w5onhys_.bkp

RMAN> restore database;

Starting restore at 28-MAY-12
using channel ORA_DISK_1

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to /u01/app/oracle/oradata/sqlfun/system01.dbf
channel ORA_DISK_1: restoring datafile 00002 to /u01/app/oracle/oradata/sqlfun/sysaux01.dbf
channel ORA_DISK_1: restoring datafile 00003 to /u01/app/oracle/oradata/sqlfun/undotbs01.dbf
channel ORA_DISK_1: restoring datafile 00004 to /u01/app/oracle/oradata/sqlfun/users01.dbf
channel ORA_DISK_1: restoring datafile 00005 to /u01/app/oracle/oradata/sqlfun/threatened_fauna_data.dbf
channel ORA_DISK_1: reading from backup piece /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_nnndf_TAG20120528T080501_7w5onhys_.bkp
channel ORA_DISK_1: piece handle=/mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_nnndf_TAG20120528T080501_7w5onhys_.bkp tag=TAG20120528T080501
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:55
Finished restore at 28-MAY-12

RECOVER DATABASE

RMAN> list backup of archivelog all;

List of Backup Sets
===================

BS Key  Size       Device Type Elapsed Time Completion Time
------- ---------- ----------- ------------ ---------------
164     68.50K     DISK        00:00:00     28-MAY-12
        BP Key: 164   Status: AVAILABLE  Compressed: NO  Tag: TAG20120528T081134
        Piece Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T081134_7w5oob2y_.bkp

  List of Archived Logs in backup set 164
 Thrd Seq     Low SCN    Low Time  Next SCN   Next Time
  ---- ------- ---------- --------- ---------- ---------
  1    386     8176419    28-MAY-12 8176669    28-MAY-12

BS Key  Size       Device Type Elapsed Time Completion Time
------- ---------- ----------- ------------ ---------------
165     68.50K     DISK        00:00:00     28-MAY-12
        BP Key: 165   Status: AVAILABLE  Compressed: NO  Tag: TAG20120528T093614
        Piece Name: /mnt/remote/backups/orasql/FRA_BACKUP/SQLFUN/backupset/2012_05_28/o1_mf_annnn_TAG20120528T093614_7w5ongvb_.bkp

  List of Archived Logs in backup set 165
  Thrd Seq     Low SCN    Low Time  Next SCN   Next Time
  ---- ------- ---------- --------- ---------- ---------
  1    386     8176419    28-MAY-12 8176669    28-MAY-12

RMAN> recover database until sequence 387;

Starting recover at 28-MAY-12
using channel ORA_DISK_1

starting media recovery
media recovery complete, elapsed time: 00:00:01

Finished recover at 28-MAY-12

RMAN> alter database open resetlogs;

database opened

A look at Parsing and Sharing of Cursors

Parsing is the first stage in processing a SQL statement – the other two being Execute and Fetch stages.

Parse once – execute many is a very important performance tuning goal.

What does parsing involve

    Syntax check – is the SQL statement syntactically correct
    Semantic check – is the SQL statement meaningful or semantically correct. Does the table exist, are the columns in the SQL part of the table, does the user have the required privileges on the table etc
    Shared Pool check – the database uses a hashing algorithm to generate a hash value for every SQL statement executed and this hash value is checked in the shared pool to see if any existing and already parsed statement has the same hash value. It can then be reused.

Hard Parse vs. Soft Parse

Soft Parse – when the parsed representation of a submitted SQL statement exists in the shared pool and can be shared – it is a library cache hit. Performs syntax and semantic checks but avoids the relatively costly operation of query optimization. Reuses the existing shared SQL area which already has the execution plan required to execute the SQL statement.

Hard Parse – if a statement cannot be reused or if it the very first time the SQL statement is being loaded in the library cache, it results in a hard parse. Also when a statement is aged out of the shared pool (because the shared pool is limited in size), when it is reloaded again, it results in another hard parse. So size of the shared pool can also affect the amount of parse calls.

Hard parse is thus when a SQL statement is executed, and the SQL statement is either not in the shared pool, or it is in the shared pool but it cannot be shared. – it is a library cache miss

Hard parse is a CPU intensive operation as the database accesses the library cache and data dictionary cache numerous times to check the data dictionary. When it does this it has to take out a latch which is a low level lock.

Excessive hard parsing can cause performance degradation due to library cache locking and mutexes.

What happens the first time a SQL statement is executed?

The RDBMS will create a hash value for text of the statement and then uses that hash value to check for parsed SQL statements already existing in the shared pool with the same hash value. Since it is the first time it is being executed, there is no hash value match and a hard parse occurs.

Costly phase of query optimization is performed now. It then stores the parse tree and execution plan in a shared SQL area.

When it is first parsed a parent and a single child are created.



Sharing of SQL code – next time same SQL is executed

The text of the SQL statement being executed is hashed.

If no matching hash value found, perform a hard parse.

If matching hash value exists in shared pool, compare the text of matched statement in shared pool with the statement which has been hashed. They need to be identical character for character, white spaces, case, comments etc.

Is objects referenced in the SQL statement match the objects referenced by the statement in the shared pool which is being attempted to be shared. If user A and user B both own EMP, SELECT * FROM EMP issued by user A will not be the same as the same identical statement being issued by user B.

Bind variables being used must match is terms of name, data type and length

Both the session’s environment needs to be identical. For example if at the database level we have OPTIMIZER_MODE=ALL_ROWS, but user A has used an ALTER SESSION command to change optimization goal for his session to say FIRST_ROWS, then that session will notbe able to use existing shared SQL areas which have a different optimization goal for them.



What happens when SQL is not shared


If using any of the criteria above, an identical statement does not exist, then the database allocates a new shared SQL area in the shared pool.
A statement with the same syntax but different semantics uses a child cursor.
Shared SQL area

Exists in the shared pool and contains the parse tree and execution plan for a single SQL statement.

Private SQL Area

Exists in the PGA of each separate session executing a SQL statement and points to a shared SQL area (in SGA). Many sessions PGA can point to the same Shared SQL Area



Let us run these three SQL statements.

select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type='TABLE';
select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type='INDEX';
select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type='RULE';

Note each SQL statement is unique and has its own SQL_ID.

Since each statement is being executed the first time, it is (hard) parsed as well.



SQL> select SQL_ID,EXECUTIONS,LOADS,PARSE_CALLS from v$sqlarea where sql_text like 'select /*TEST_NO_BINDS*/%';

SQL_ID        EXECUTIONS      LOADS PARSE_CALLS
------------- ---------- ---------- -----------
2tj15h6w34xcc          1          1           1
63zqvyxt1a0an          1          1           1
d6tqd33w7u8xa          1          1           1

Now let us run one of the earlier SQL statements again.

select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type=’TABLE';

Since the parsed form of this SQL statement already exists in the shared pool, it is re-used. Note loads remain the same(1), but both executions and parse_calls have increased (2). In this case a soft parse has happened.

How do we tell if a parse has been a hard parse or a soft parse? The V$SQL or V$SQLAREA views will not provide us this information. We will have to turn on tracing and use TKPROF to identify this.



SQL> select SQL_ID,EXECUTIONS,LOADS,PARSE_CALLS from v$sqlarea where sql_text like 'select /*TEST_NO_BINDS*/%';

SQL_ID        EXECUTIONS      LOADS PARSE_CALLS
------------- ---------- ---------- -----------
2tj15h6w34xcc          1          1           1
63zqvyxt1a0an          1          1           1
d6tqd33w7u8xa          2          1           2

We can also see how long a statement has been around in the shared pool. Note SQL statements will get invalidated and be flushed from the shared pool and will also age out in case Oracle needs to load new statements in the shared pool. Once the shared pool gets full, Oracle will use a LRU algorithm to age out the ‘older’ SQL statements.



SQL> select first_load_time from v$sqlarea where sql_text like 'select /*TEST_NO_BINDS*/%';

FIRST_LOAD_TIME
----------------------------------------------------------------------------
2012-09-04/05:26:29
2012-09-04/05:26:40
2012-09-04/05:25:31

Let us now look at the Version Count.

Remember that non-sharing of SQL and consequent high version count is one of the top causes of library cache contention and database ‘hang’ situations.

If there are too many versions if the same cursor, the parse engine has to search though a complete list of all the versions until it finds the ‘right’ version. This activity can take a lot of CPU cycles as well.



SQL>  select SQL_ID,EXECUTIONS,LOADS,PARSE_CALLS,version_count  from v$sqlarea where sql_text like 'select /*TEST_NO_BINDS*/%';

SQL_ID        EXECUTIONS      LOADS PARSE_CALLS VERSION_COUNT
------------- ---------- ---------- ----------- -------------
2tj15h6w34xcc          1          1           1             1
63zqvyxt1a0an          1          1           1             1
d6tqd33w7u8xa          2          1           2             1

SQL>  select SQL_ID,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TEST_NO_BINDS*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
2tj15h6w34xcc            0          1          1           1
63zqvyxt1a0an            0          1          1           1
d6tqd33w7u8xa            0          2          1           2

Let us now connect as another user, SCOTT who also owns a table called MYOBJECTS.



SQL> select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type=’TABLE';



We see that because there are two objects existing (SYSTEM.MYOBEJCTS and SCOTT.MYOBJECTS), the query “select /*TEST_NO_BINDS*/ distinct owner from myobjects” has led to another child and another version of the SQL statement being created in the shared pool.

Note the SQL_ID does not change regardless of the version count increasing!



SQL> select child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_id='d6tqd33w7u8xa';

CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------ ---------- ---------- -----------
           0          2          1           2
           1          1          3           1

What happens if we change some optimization setting in the users environment and run the same SQL statement again.



SQL> alter session set optimizer_mode=FIRST_ROWS;

Session altered.

SQL> select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type='TABLE';

SQL> select child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_id='d6tqd33w7u8xa';

CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------ ---------- ---------- -----------
           0          2          1           2
           1          1          3           1
           2          1          2           1

SQL>  select version_count,invalidations from v$sqlarea where sql_id='d6tqd33w7u8xa';

VERSION_COUNT INVALIDATIONS
------------- -------------
            3             3

Why was the cursor not shared?



SQL>  select hash_value,address from v$sqlarea where sql_text like 'select /*TEST_NO_BINDS*/ distinct owner from myobjects where object_type=''TABLE''';

HASH_VALUE ADDRESS
---------- ----------------
4168950698 000000008D920748

SQL> select * from v$sql_shared_cursor where address ='000000008D920748';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
d6tqd33w7u8xa 000000008D920748 00000000985A42D8            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
d6tqd33w7u8xa 000000008D920748 000000008A8D4E68            1 N N N N N N N N N N N N N Y N N N Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
d6tqd33w7u8xa 000000008D920748 000000008D9D9DA0            2 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N



Check the columns in the V$SQL_SHARED_CURSOR view and look for occurrences of ‘Y’.

We can see that the reason why the cursor was not shared is because of AUTH_CHECK_MISMATCH and TRANSLATION_MISMATCH in the first case and because of OPTIMIZER_MODE_MISMATCH reason in the second case

Tuesday, 7 July 2015

CURSOR_SHARING=SIMILAR and FORCE - some examples

The CURSOR_SHARING parameter basically influences the extent to which SQL statements (or cursors) can be shared.

 The possible values are EXACT which is the default value and SIMILAR and FORCE.

The official definitions of SIMILAR and FORCE are:

cursor_sharing=similar: “Causes statements that may differ in some literals, but are otherwise identical, to share a cursor, unless the literals affect either the meaning of the statement or the degree to which the plan is optimized.”

 cursor_sharing=FORCE: “Forces statements that may differ in some literals, but are otherwise identical, to share a cursor, unless the literals affect the meaning of the statement.”

So basically it means that the SQL statement will be shared even though literals are different as long as it does not affect the execution plan of the statement. This is the case for SIMILAR setting.

The cursor_sharing=SIMILAR parameter has been deprecated in 11gR2 because it has been found that the use of this parameter could potentially have a lot of performance implications related to the number of child cursors created for the single parent. 

 In versions prior to 11g R2, the was a limit on the number of child cursors  which can be associated with a single parent. It was 1024 and once this number was crossed the parent was marked obsolete and this invalidated it was well as all associated child cursors.

 But not having this upper limit was being found to have caused a lot of CPU usage and waits on mutexes and library cache locks in 11gR2  caused by searching the library cache for matching cursors and it was felt that  having many child cursors all associated with one parent cursor could perform much worse than having many parent cursors that would be seen with having the default setting of cursor_sharing = EXACT

 Using this parameter also was bypassing one of the big improvements made in 11g which was Adaptive Cursor Sharing.

Let us examine the behaviour with CURSOR_SHARING set to SIMILAR as opposed to FORCE and note the differences between the two.

SQL> alter system set cursor_sharing='SIMILAR';

System altered.

Let us now run these three SQL statements which are identical in text, but only differ in the LITERAL values

SQL> select /*TEST_SIMILAR*/  count(*) from system.myobjects where owner='SYS';

  SQL> select /*TEST_SIMILAR*/  count(*) from system.myobjects where owner='SYSTEM';

SQL> select /*TEST_SIMILAR*/  count(*) from system.myobjects where owner='SCOTT';

We can see how the three different SQL statements has been transformed into one single SQL statement – note the part – where owner=:”SYS_B_0″ and also the fact that there is only one single SQL_ID.

Oracle has automatically replaced the literal with a bind value.

 SQL>  select sql_id,sql_text from v$sql where sql_text like 'select /*TEST_SIMILAR*/%';

SQL_ID        SQL_TEXT
------------- --------------------------------------------------------------------------------
7qsnvbzwh79tj select /*TEST_SIMILAR*/  count(*) from system.myobjects where owner=:"SYS_B_0"

We see that the SQL statement has been loaded only once and executed 3 times

SQL> select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TEST_SIMILAR*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
7qsnvbzwh79tj            0          3          1           3

Note the number of versions – it is only one – which shows that the SQL statement has been shared.

SQL> select version_count from v$sqlarea where sql_id='7qsnvbzwh79tj';

VERSION_COUNT
-------------
            1

We need to keep in mind however that using inequalities or LIKE etc will not share cursors even if using SIMILAR

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where owner like 'A%';

SQL>  select /*TEST_SIMILAR*/  distinct owner from myobjects where owner like 'B%';

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where owner like 'C%';

Note the child cursors created and also the version count – this shows that even though we were using SIMILAR for cursor sharing, the SQL statement has not been shared.

SQL> select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TEST_SIMILAR*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
4hxkxzpas5hyq            0          1          1           1
4hxkxzpas5hyq            1          1          1           1
4hxkxzpas5hyq            2          1          1           1

SQL> select version_count from v$sqlarea where sql_id='4hxkxzpas5hyq';

VERSION_COUNT
-------------
3

Let us now change the CURSOR _SHARING to FORCE and see what the difference is.

SQL> alter system set cursor_sharing='FORCE';

System altered.

SQL> select /*FORCE*/  distinct owner from myobjects where owner like 'A%';

SQL>  select /* FORCE */  distinct owner from myobjects where owner like 'B%';

SQL> select /* FORCE */  distinct owner from myobjects where owner like 'C%';

Note that there is only one child and the version count is one which shows that this SQL statement has been shared.

SQL> select version_count from v$sqlarea where sql_id='6c4f9xwp19pff';

VERSION_COUNT
-------------
1

SQL>  select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*FORCE*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
6c4f9xwp19pff            0          3          1           3

Let us now look at the effect Histograms have on the SIMILAR setting for the cursor_sharing parameter.

The presence of Histogram statistics on a column being used in the WHERE clause can lead to the cursor not being shared because there is the possibility of the optimizer choosing different plans for different values. In that case we will see multiple children being created as in the example below.

The CBO considers these literals to be UNSAFE

In this case we have created an index on the OBJECT_TYPE column and when we have gathered statistics for the table, Oracle has created histograms for that indexed column.

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where object_type='A';

no rows selected

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where object_type='B';

no rows selected

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where object_type='C';

no rows selected

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where object_type='D';

no rows selected

SQL> select /*TEST_SIMILAR*/  distinct owner from myobjects where object_type='E';
no rows selected

SQL> select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TEST_SIMILAR*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
2m80tr9fhhbwn            0          1          1           1
2m80tr9fhhbwn            1          1          1           1
2m80tr9fhhbwn            2          1          1           1
2m80tr9fhhbwn            3          1          1           1
2m80tr9fhhbwn            4          1          1           1

SQL>  select version_count from v$sqlarea where sql_id='2m80tr9fhhbwn';

VERSION_COUNT
-------------
            5

Let us now verify why the cursor was not shared.

SQL> select hash_value,address from v$sqlarea where sql_text like 'select /*TEST_SIMILAR*/%';

HASH_VALUE ADDRESS
---------- ----------------
1560817556 0000000095B58FD8

SQL> select * from v$sql_shared_cursor where address='0000000095B58FD8';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2m80tr9fhhbwn 0000000095B58FD8 000000009160F6B8            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
2m80tr9fhhbwn 0000000095B58FD8 0000000091633E68            1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N
2m80tr9fhhbwn 0000000095B58FD8 0000000091741E10            2 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N
2m80tr9fhhbwn 0000000095B58FD8 000000008DA39108            3 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N
2m80tr9fhhbwn 0000000095B58FD8 00000000947D5B30            4 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N

We can see that the reason for the cursor not being shared is because of the ‘Y’ in the HASH_MATCH_FAILED column.

Note that this is a new column added to the V$SQL_SHARED_CURSOR view in 11gR2 . In this particular case is it because of the mismatched histogram data

Let us look at another case where cursors are not shared because of what is called a STB_OBJECT_MISMATCH case.

STB_OBJECTS refers to SQL Management Objects like SQL Profiles and SQL Plan Baselines.

If we are using SQL Plan Baselines then we see a new child cursor being created between the first and second executions of the SQL statement because a new SQL Management Object (in this case baseline) was created invalidating the cursor and causing a hard parse the next time the same SQL was executed .

In this example, with cursor_sharing=SIMILAR, because we are using SQL PLan Baselines, a new SQL PLan Management Object was created which invalidated the existing child cursor causing a new child cursor to created for the same parent.

We can see that for the second child, a SQL PLan Baseline was used which was not in the case of the first child.

SQL> select /*TEST_SIMILAR*/  count(*) from myobjects where owner='SYS';

  COUNT(*)
----------
     31129

SQL> select /*TEST_SIMILAR*/  count(*) from myobjects where owner='SYSTEM';

  COUNT(*)
----------
       539

SQL> select /*TEST_SIMILAR*/  count(*) from myobjects where owner='CTXSYS';

  COUNT(*)
----------
       366

SQL> select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TEST_SIMILAR*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
68rgrrrpfas96            0          2          1           2
68rgrrrpfas96            1          1          1           1

SQL> select version_count from v$sqlarea where sql_id='68rgrrrpfas96';

VERSION_COUNT
-------------
            2

SQL> select hash_value,address from v$sqlarea where sql_text like 'select /*TEST_SIMILAR*/%';

HASH_VALUE ADDRESS
---------- ----------------
3940901158 0000000096498EA0

SQL> select * from v$sql_shared_cursor where address='0000000096498EA0';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68rgrrrpfas96 0000000096498EA0 0000000099A374D0            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
68rgrrrpfas96 0000000096498EA0 0000000094546818            1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N N N N N N N N N

SQL> select child_number,sql_profile,sql_plan_baseline from v$sql where sql_id='7qsnvbzwh79tj';

CHILD_NUMBER SQL_PROFILE                                                      SQL_PLAN_BASELINE
------------ ---------------------------------------------------------------- ------------------------------
           0
           1                                                                  SQL_PLAN_3m43x2gkdvd0vcaeddc3c

SQL> show parameter baseline

NAME                                 TYPE                             VALUE
------------------------------------ -------------------------------- ------------------------------
optimizer_capture_sql_plan_baselines boolean                          TRUE
optimizer_use_sql_plan_baselines     boolean                          TRUE

Why do my execution plans not change after gathering statistics? 

A look at Rolling Cursor Invalidations


In releases prior to Oracle 10g, the gathering of statistics using DBMS_STATS resulted in immediate invalidations of dependent cached cursors. This was true unless NO_INVALIDATE parameter of the DBMS_STATS command was set to TRUE.

It was felt that gathering of statistics could actually have a negative impact on performance because of the fact that invalidation of a cached cursor due to gathering of statistics meant that it had to be hard-parsed the next time it is executed.

We know that excessive hard parsing could cause performance spikes because of the CPU usage taken by hard parse operations as well as contention for the library cache and shared pool latches.

In Oracle 10g the default for the NO_INVALIDATE parameter is now AUTO_INVALIDATE.

This means that Oracle will not immediately invalidate the cached cursors on gathering of fresh statistics, but wait for a period of time to elapse first.

This period of time is controlled by the parameter _optimizer_invalidation_period which defaults to a value of 18000 (seconds) or 5 hours.

This parameter specifies when dependent cursors cached in the library cache will get invalidated when statistics are gathered on referenced tables or indexes.

specify when to invalidate dependent cursors i.e. cursors cached in the library cache area of the shared pool which reference a table, index, column or fixed object whose statistics are modified by the procedure call.

So we may find that in some cases even after gathering statistics, the execution plan still remains the same. And it will remain the same unless the 5 hour period of time has elapsed or if the cursor had got invalidated for some other reason or if the cursor had been aged out of the shared pool and was then reloaded.

This reload would then trigger a new hard parse and consequently possibly a new execution plan as well.

Let us look at example of this case.

We create a table TESTME based on the ALL_OBJECTS view.

The data in the table is quite skewed – in my case the table had 18 distinct values for OBJECT_TYPE and there were about 55000 rows. The value SYNONYM for the OBJECT_TYPE column accounted for over 20,000 rows, but there were other values like RULE which just had 1 row.

We created an index on the OBJECT_TYPE column for the test.

SQL> create table testme as select * from all_objects;

Table created.

SQL> create index testme_ind on testme(object_type);

Index created.

Note the current value for NO_INVALIDATE is AUTO which is the default in 10g and above.

SQL> select dbms_stats.get_prefs('NO_INVALIDATE','SYSTEM','MYOBJECTS') from dual
  2  ;

DBMS_STATS.GET_PREFS('NO_INVALIDATE','SYSTEM','MYOBJECTS')
--------------------------------------------------------------------------------
DBMS_STATS.AUTO_INVALIDATE

We ran this SQL statement. Since it will return a single row, we can assume the CBO will choose the index in the execution plan.

SQL> select /*TESTME*/ distinct owner from testme where object_type='RULE';

SQL> select sql_id from v$sql where sql_text like 'select /*TESTME*/%';

SQL_ID
-------------
4a77d3s7xx1mc

SQL> select plan_hash_value,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TESTME*/%';

PLAN_HASH_VALUE CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
--------------- ------------ ---------- ---------- -----------
     2890121575            0          1          1           1

We then updated the table and changed the value of OBJECT_TYPE to RULE for 25000 rows – about 50% of the table

SQL> update testme set object_type='RULE' where rownum < 25001;

25000 rows updated.

SQL> commit;

Commit complete.

After this UPDATE statement, we gather fresh statistics

SQL>  exec dbms_stats.gather_table_stats(USER,'TESTME');

PL/SQL procedure successfully completed.

We now run the same query again.

SQL> select /*TESTME*/ distinct owner from testme where object_type='RULE';

Since we are now selecting a high proportion of rows from the table, we would assume that the CBO would have chosen a full table scan instead now in place of the earlier Index scan.

But has the plan changed? – it does not appear so. The executions are now 2, but the plan hash value is still the same.

So looks like the optimizer is still using the old execution plan for this statement . It still considers the table to have only one row for the OBJECT_TYPE value RULE.

The cursor in this case could potentially remain in the shared pool for up to 5 hours with an unchanged execution plan.

SQL> select plan_hash_value,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TESTME*/%';

PLAN_HASH_VALUE CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
--------------- ------------ ---------- ---------- -----------
     2890121575            0          2          1           2

SQL> select * from table(dbms_xplan.display_cursor('4a77d3s7xx1mc',null,null));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID  4a77d3s7xx1mc, child number 0
-------------------------------------
select /*TESTME*/ distinct owner from testme where
object_type=:"SYS_B_0"

Plan hash value: 2890121575

-------------------------------------------------------------------------------------------
| Id  | Operation                    | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |            |       |       |     3 (100)|          |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
|   1 |  HASH UNIQUE                 |            |     1 |    28 |     3  (34)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TESTME     |     1 |    28 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | TESTME_IND |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------

Now let us change the value of the parameter _optimizer_invalidation_period to 60

SQL> alter system set "_optimizer_invalidation_period" = 60 scope=memory;  (default is 18000 or 5 hours)

System altered.

We gather statistics again

SQL> exec dbms_stats.gather_table_stats(USER,'TESTME');

After about a minute, execute the same statement again.

SQL> select /*TESTME*/ distinct owner from testme where object_type='RULE';

This time things are different.

We see a new child cursor as the earlier child cursor has got invalidated. The version count has also changed and we see a new plan hash value (which would indicate a changed execution plan as well)

SQL>  select sql_id,child_number,EXECUTIONS,LOADS,PARSE_CALLS from v$sql where sql_text like 'select /*TESTME*/%';

SQL_ID        CHILD_NUMBER EXECUTIONS      LOADS PARSE_CALLS
------------- ------------ ---------- ---------- -----------
4a77d3s7xx1mc            0          2          3           2
4a77d3s7xx1mc            1          1          1           1

SQL> select version_count from v$sqlarea where sql_id='4a77d3s7xx1mc';

VERSION_COUNT
-------------
            2

SQL> select hash_value,address from v$sqlarea where sql_id='4a77d3s7xx1mc';

HASH_VALUE ADDRESS
---------- ----------------
266241644 0000000099A9BAD8

We see that the ROLL_INVALID_MISMATCH column of the V$SQL_SHARED_CURSOR view has a value ‘Y’. This is the reason the cursor has got invalidated.

ROLL_INVALID_MISMATCH indicates that the child had to be created because the original cursor could not be reused due to having been invalidated with rolling invalidation

SQL> select * from v$sql_shared_cursor where address='0000000099A9BAD8';

SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N
------------- ---------------- ---------------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4a77d3s7xx1mc 0000000099A9BAD8 00000000915908F0            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N

4a77d3s7xx1mc 0000000099A9BAD8 000000008A9ED0A0            1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N N