My Headlines

CCNA Chapter Answers, CCNA 3 Answers, CCNA 3 Final Exam Answers 2012, final exam ccna 3 answer 2012
http://ping.fm/DHlIM

Script for Undo Information

REM:**********************************************************************************************
REM: Script : Undo Informations
REM: Author: Kumar Menon
REM: Date Submitted: 16-July-2009
REM:FileName: Undoinfo.sql
REM:
REM: NOTE: PLEASE TEST THIS SCRIPT BEFORE USE.
REM: Author will not be responsible for any damage that may be cause by this script.
****************************************************************************************************


spool d:\undoinfo.txt
SELECT (UR * (UPS * DBS)) + (DBS * 24) AS "Bytes"
FROM (SELECT value AS UR FROM v$parameter WHERE name = 'undo_retention'),
(SELECT (SUM(undoblks)/SUM(((end_time - begin_time)*86400))) AS UPS FROM v$undostat),
(SELECT value AS DBS FROM v$parameter WHERE name = 'db_block_size') ;

SELECT r.name rbs,
NVL(s.username, 'None') oracle_user,
s.osuser client_user,
p.username unix_user,
TO_CHAR(s.sid)||','||TO_CHAR(s.serial#) as sid_serial,
p.spid unix_pid,
t.used_ublk * TO_NUMBER(x.value)/1024 as undo_kb
FROM v$process p,
v$rollname r,
v$session s,
v$transaction t,
v$parameter x
WHERE s.taddr = t.addr
AND s.paddr = p.addr(+)
AND r.usn = t.xidusn(+)
AND x.name = 'db_block_size'
ORDER
BY r.name ;

select l.sid, s.segment_name from dba_rollback_segs s, v$transaction t, v$lock l
where t.xidusn=s.segment_id and t.addr=l.addr ;
select to_char(begin_time,'hh24:mi:ss'),to_char(end_time,'hh24:mi:ss')
, maxquerylen,ssolderrcnt,nospaceerrcnt,undoblks,txncount from v$undostat
order by undoblks ;
set lines 160 pages 40
col machine format A20
col username format A15
select xidusn, xidslot, trans.status, start_time, ses.sid, ses.username, ses.machine ,proc.spid, used_ublk
from v$transaction trans, v$session ses , v$process proc
where trans.ses_addr =ses.saddr and ses.paddr=proc.addr
order by start_time ;

select to_char(begin_time,'hh24:mi:ss'),to_char(end_time,'hh24:mi:ss')
, maxquerylen,ssolderrcnt,nospaceerrcnt,undoblks,txncount from v$undostat
order by undoblks ;
Promot "following to show how much undo is being used:"

set pagesize 24
set lin 132
set verify off
col owner format a13
col segment_name format a25 heading 'Segment Name'
col segment_type format a15 heading 'Segment Type'
col tablespace_name format a15 heading 'Tablespace Name'
col extents format 99999999 heading 'Extent'
select
owner, segment_name, segment_type, tablespace_name,
(bytes / 1048576) "Mbytes",
extents
from sys.dba_segments
where tablespace_name = '&UNDO01'
order by owner, segment_name ;

spool off

Max 50 I/O Information

REM:**********************************************************************************************
REM: Script : Max 50 I/O Informations
REM: Author: Kumar Menon
REM: Date Submitted: 16-July-2009
REM:FileName: 50maxIO.sql
REM:
REM: NOTE: PLEASE TEST THIS SCRIPT BEFORE USE.
REM: Author will not be responsible for any damage that may be cause by this script.
****************************************************************************************************

spool D:\top50&no.lst
set termout off

declare
    cursor c1 is
    select     executions,
               disk_reads,
        buffer_gets,
        first_load_time,
               sql_text
    from    v$sqlarea
    order     by disk_reads / decode(executions,0,1,executions) desc;

    statement_ctr    number;
    i        number;

begin
    dbms_output.enable(50000);
    statement_ctr := 0;

    for inrec in c1 loop

       statement_ctr := statement_ctr + 1;
       if statement_ctr >= 51 then
          exit;
       end if;

       dbms_output.put_line('Statement Number: ' || to_char(statement_ctr));
       dbms_output.put_line('--------------------------------------------');
       dbms_output.put_line('Executions     : ' ||
                to_char(inrec.executions));
       dbms_output.put_line('Disk Reads     : ' ||
                to_char(inrec.disk_reads));
       dbms_output.put_line('Buffer Gets    : ' ||
                to_char(inrec.buffer_gets));
       dbms_output.put_line('First Load Time: ' ||
                inrec.first_load_time);
       dbms_output.put_line('SQL Statement-------->');


       i := 1;
           while i <= ceil(length(inrec.sql_text) / 72) loop

          dbms_output.put_line('.....' ||
                    substr(inrec.sql_text,((i-1)*72)+1,72));
              i := i + 1;


           end loop;


       dbms_output.put_line('--------------------------------------------');


    end loop;
end;
/

spool off
set termout on

SCRIPT FOR User Information

REM:**********************************************************************************************
REM: Script SCRIPT FOR User Informations
REM: Author:  Kumar Menon
REM: Date Submitted: 07.09.2009
REM:FileName: userinfo.sql
REM:
REM: NOTE: PLEASE TEST THIS SCRIPT BEFORE USE.
REM: Author will not be responsible for any damage that may be cause by this script.
****************************************************************************************************
set feedback off
set termout on 
set pagesize 56
set linesize 800
ttitle off
spool D:\userinfo.wri

set verify off
set heading on
Prompt Database Name:
select   'Database Name (SID): ' || name "name" from     v$database; 
prompt
prompt

prompt Database Version Informations:

select * from v$version; 

select username,profile,default_tablespace,temporary_tablespace from dba_users;

Prompt Database Character Set Informations:

select * from nls_database_parameters;

Prompt Database Segment Managment  Informations:

select TABLESPACE_NAME,BLOCK_SIZE,EXTENT_MANAGEMENT,SEGMENT_SPACE_MANAGEMENT from dba_tablespaces;

Prompt Database Object Informations:

select owner,object_type,count(1) from dba_objects Where owner not IN ('SYS','MDSYS','CTXSYS','HR','ORDSYS','OE','ODM_MTR','WMSYS','XDB','QS_WS', 'RMAN','SCOTT','QS_ADM','QS_CBADM',
'ORDSYS','OUTLN','PM','QS_OS','QS_ES','ODM','OLAPSYS','WKSYS','SH','SYSTEM','ORDPLUGINS','QS','QS_CS') group by owner,object_type order by owner;

Prompt File and Tablespace Informations:

SELECT file_name,tablespace_name,autoextensible,maxbytes/1048576 FROM dba_data_files;


spool off

Identifying corrupt blocks

Recently we had a datafile with a number of corrupt blocks and once it was fixed I resolved to try out all the methods available of identifying block corruption. Searching around I came across an excellent blog by   Asif Momen – Practising block recovery which provided me pretty much what I wanted. However I did think it worth adding a blog entry as I wanted to document all the various methods available to identify corruption.  I also wanted to cover how to test causing a corruption when using ASM datafiles.
Create a datafile, add data and find out which block that data is in
 create smallfile tablespace bad_data datafile '+DATA' size 10M;

Create table test (username varchar2(9), password varchar2(6)) tablespace bad_data;

DECLARE

u  VARCHAR2(9);

p  VARCHAR2(6);

BEGIN

FOR jump  IN 1 ..10000  LOOP

u := 'TEST'||jump;

p := 'P'||jump;

insert into test values (u,p);

END LOOP;

commit;

END;

/

PL/SQL procedure successfully completed.

select

rowid ,

to_number(utl_encode.base64_decode(utl_raw.cast_to_raw(lpad(substr(rowid, 1, 6), 8, 'A'))), 'XXXXXXXXXXXX') as objid,

to_number(utl_encode.base64_decode(utl_raw.cast_to_raw(lpad(substr(rowid, 7, 3), 4, 'A'))), 'XXXXXX') as filenum,

to_number(utl_encode.base64_decode(utl_raw.cast_to_raw(lpad(substr(rowid, 10, 6), 8, 'A'))), 'XXXXXXXXXXXX') as blocknum,

to_number(utl_encode.base64_decode(utl_raw.cast_to_raw(lpad(substr(rowid, 16, 3), 4, 'A'))), 'XXXXXX') as rowslot

from test where password='P7777'
ROWID                   OBJID    FILENUM   BLOCKNUM    ROWSLOT
—————— ———- ———- ———- ———-
AAAXaiAAHAAAACdAAr      95906          7        156         43
Copy datafile from ASM to filesystem as it is easier to manipulate there
alter tablespace bad_data offline;

Tablespace altered

RMAN> copy datafile 7 to '/home/oracle/bad_data_01.dbf';

Starting backup at 2010-04-14:10:04:29

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=306 device

channel ORA_DISK_1: starting datafile copy

input datafile file number=00007 name=+DATA/oemdev1a/datafile/bad_data.266.716292163

output file name=/home/oracle/bad_data_01.dbf tag=TAG20100414T100432 RECID=3 STAMP=716292274

channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:03

Finished backup at 2010-04-14:10:04:36

Starting Control File and SPFILE Autobackup at 2010-04-14:10:04:36

piece handle=+FRA/oemdev1a/autobackup/2010_04_14/s_716292277.459.716292277 comment=NONE

Finished Control File and SPFILE Autobackup at 2010-04-14:10:04:38

RMAN> exit
Corrupt the datafile using dd
/home/oracle $cp bad_data_01.dbf bad_data_01.dbf_good
/home/oracle $dd if=/home/oracle/bad_data_01.dbf bs=8k count=156 of=/home/oracle/bad_data_01.dbf_new
156+0 records in
156+0 records out
/home/oracle $dd if=/home/oracle/bad_data_01.dbf bs=8k count=1 >> /home/oracle/bad_data_01.dbf_new
1+0 records in
1+0 records out
/home/oracle $dd if=/home/oracle/bad_data_01.dbf bs=8k skip=157 >> /home/oracle/bad_data_01.dbf_new
1124+0 records in
1124+0 records out
/home/oracle $mv /home/oracle/bad_data_01.dbf_new /home/oracle/bad_data_01.dbf
Put the datafile online and see if any corruption exist
SQL*Plus: Release 11.1.0.7.0 - Production on Wed Apr 14 10:06:30 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production

With the Partitioning option

SQL>select file_name from dba_data_files where tablespace_name = 'BAD_DATA';

FILE_NAME

--------------------------------------------------------------------------------

+DATA/oemdev1a/datafile/bad_data.266.716292163

SQL>alter database rename file '+DATA/oemdev1a/datafile/bad_data.266.716292163' to '/home/oracle/bad_data_01.dbf';

Database altered.

SQL>alter tablespace bad_data online;

Tablespace altered.

Connected to:

Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production

With the Partitioning option

SQL>select * from test where password='P7777;

select * from test where password='P7777'

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 7, block # 156)

ORA-01110: data file 7: '/home/oracle/bad_data_01.dbf' 
SUCCESS – we have corruption, now let’s get the datafile back into ASM before we test for block corruption using various methods
Recovery Manager: Release 11.1.0.7.0 - Production on Wed Apr 14 10:14:12 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

connected to target database: OEMDEV1A (DBID=63225982)

using target database control file instead of recovery catalog

RMAN> copy datafile '/home/oracle/bad_data_01.dbf' to '+DATA';

Starting backup at 2010-04-14:10:14:38

allocated channel: ORA_DISK_1

channel ORA_DISK_1: SID=289 device

channel ORA_DISK_1: starting datafile copy

input datafile file number=00007 name=/home/oracle/bad_data_01.dbf

RMAN-00571: ===========================================================

RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============

RMAN-00571: ===========================================================

RMAN-03009: failure of backup command on ORA_DISK_1 channel at 04/14/2010 10:14:41

ORA-19566: exceeded limit of 0 corrupt blocks for file /home/oracle/bad_data_01.dbf
OOPS, RMAN does an implicit check of the datafile and does not allow it to be moved into ASM. Seems very reasonable
DB verify
/home/oracle $dbv file=/home/oracle/bad_data_01.dbf  blocksize=8192

DBVERIFY: Release 11.1.0.7.0 - Production on Wed Apr 14 10:16:58 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

DBVERIFY - Verification starting : FILE = /home/oracle/bad_data_01.dbf

Page 156 is marked corrupt

Corrupt block relative dba: 0x01c0009c (file 7, block 156)

Bad header found during dbv:

Data in bad block:

type: 0 format: 2 rdba: 0xffc00000

last change scn: 0x0000.00000000 seq: 0x0 flg: 0x00

spare1: 0x0 spare2: 0x0 spare3: 0x0

consistency value in tail: 0x00000000

check value in block header: 0x5dc4

block checksum disabled

DBVERIFY - Verification complete

Total Pages Examined         : 1280

Total Pages Processed (Data) : 27

Total Pages Failing   (Data) : 0

Total Pages Processed (Index): 0

Total Pages Failing   (Index): 0

Total Pages Processed (Other): 131

Total Pages Processed (Seg)  : 0

Total Pages Failing   (Seg)  : 0

Total Pages Empty            : 1121

Total Pages Marked Corrupt   : 1

Total Pages Influx           : 0

Total Pages Encrypted        : 0

Highest block SCN            : 8780478 (0.8780478) 
export the database to /dev/null – forces a database read but produces no output file
$exp

Export: Release 11.1.0.7.0 - Production on Wed Apr 14 10:19:12 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Username: / as sysdba

Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production

With the Partitioning option

Enter array fetch buffer size: 4096 >

Export file: expdat.dmp > /dev/null

Volume size (<ret> for no restriction) >

(1)E(ntire database), (2)U(sers), or (3)T(ables): (2)U > U

Export grants (yes/no): yes >

Export table data (yes/no): yes >

Compress extents (yes/no): yes >

Export done in US7ASCII character set and AL16UTF16 NCHAR character set

server uses AL32UTF8 character set (possible charset conversion)

About to export specified users ...

User to be exported: (RETURN to quit) > TEST

. about to export TEST's tables via Conventional Path ...

. . exporting table                           TEST

EXP-00056: ORACLE error 1578 encountered

ORA-01578: ORACLE data block corrupted (file # 7, block # 156)

ORA-01110: data file 7: '/home/oracle/bad_data_01.dbf'
RMAN to validate the database and CHECK LOGICAL.
The validate database command does not perform a backup but checks each block to see if any physical corruption can be detected. Logical corruption can also be checked at the same time by using the CHECK LOGICAL command to RMAN BACKUP DATABASE VALIDATE. Logical corruption is commonly associated with a database recovery when NOLOGGING has been used.
RMAN> <strong>BACKUP VALIDATE DATABASE ;</strong>

Starting backup at 2010-04-14:10:26:10
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00002 name=+DATA/oemdev1a/datafile/sysaux.261.710070859
input datafile file number=00001 name=+DATA/oemdev1a/datafile/system.260.710070855
input datafile file number=00005 name=/app/oracle/oradata/OEMDEV1A/mgmt.dbf
input datafile file number=00003 name=+DATA/oemdev1a/datafile/undotbs1.262.710070861
input datafile file number=00006 name=/app/oracle/oradata/OEMDEV1A/mgmt_ecm_depot1.dbf
input datafile file number=00007 name=/home/oracle/bad_data_01.dbf
input datafile file number=00004 name=+DATA/oemdev1a/datafile/users.264.710070871
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:25

List of Datafiles
=================

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
7    FAILED 0              1121         1280            8780478
File Name: /home/oracle/bad_data_01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data       0              27
Index      0              0
Other      1              132

validate found one or more corrupt blocks
See trace file /app/oracle/diag/rdbms/oemdev1a/OEMDEV1A/trace/OEMDEV1A_ora_5559.trc for details
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
List of Control File and SPFILE

RMAN> <strong>backup validate check logical database;</strong>

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
7    FAILED 0              1121         1280            8780478
File Name: /home/oracle/bad_data_01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data       0              27
Index      0              0
Other      1              132

validate found one or more corrupt blocks
See trace file /app/oracle/diag/rdbms/oemdev1a/OEMDEV1A/trace/OEMDEV1A_ora_5559.trc for details
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Using DBMS_REPAIR to check for corruption
Create a table to hold the data
  execute dbms_repair.admin_tables( 'REPAIR_TABLE',dbms_repair.repair_table,dbms_repair.create_action);
Run the dbms_repair package to check for corruption
  set serveroutput on
declare corr_count binary_integer;
begin
corr_count := 0;
dbms_repair.CHECK_OBJECT (
schema_name => 'TEST',
object_name => 'TEST',
partition_name => null,
object_type => dbms_repair.table_object,
repair_table_name => 'REPAIR_TABLE',
flags => null,
relative_fno => null,
block_start => null,
block_end => null,
corrupt_count => corr_count
);
dbms_output.put_line(to_char(corr_count));
end;
/

col object_id form 9999999999
col object_name form 20
col tablespace_id form 999
col block_id form 999999999
SQL>select object_id,object_name, tablespace_id ,block_id from repair_table;

OBJECT_ID OBJE TABLESPACE_ID   BLOCK_ID
----------- ---- ------------- ----------
95906 TEST             7        156
V$DATABASE_BLOCK_CORRUPTION
After all this testing we should be able to find something in the V$DATABASE_BLOCK_CORRUPTION view
SQL>select * from  V$DATABASE_BLOCK_CORRUPTION

FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
7        156          1                  0 CORRUPT

How to Get/Gain Real Time Experience/Exposure as a DBA!

Dear Blog Readers,

Every now and then I do receive e-mails from the novice DBAs saying that:

“We could not perform well at the interview, as the questions were too technically based on real time requirements”

“Due to not having real time experience, we failed at the interview to explain the steps/approach to resolve the issue asked”

…… and so on

When I asked them how they prepare and practice the DBA Activities, their response is as follows:

“We brought the Oracle DBA Books written by so and so authors for reference.”

“We only practiced the scenarios what was taught and given as drill in the training institute.”

“We installed the Oracle Software with starter database and get started practicing.”

…… and so on


Well, here are my opinions/suggestions/advices, to them those who are preparing and practicing as above, to gain the real time experience/exposure.

A lot of novice or junior DBAs are out there, who do not know that Oracle offers online documentations on Oracle Database Administration. Rather they simply purchase the available books in the market and get started preparing it. I would advice them to make a habit of reading the Oracle online documentations daily whenever they have time.

As far as I know, in the training institutes, the trainers will only cover the basic and required information up to some level, and discussed the scenarios which are common and basic. I suggest them to not to treat those scenarios as real time questions. The trainers will give you or left up to you to practice and do the drill at your own.

In my opinion, the real time issues are not different from the issues you face while practicing. i.e. fixing the ORA-Errors generated. My strong advice is not to create the database while installing the database, instead create the database manually with very minimal size of SGA and data files. Then, put more load i.e. Insert/Updates/Deletes and look forward for errors and the slowness of database, then fix them and tune the database accordingly. This will not be possible where you have a database with good size of SGA and enough size of data files.

As a real time requirement, install and set up the Oracle Server on Linux Operating System, this confidence will help you in stalling the same on any flavor of the Unix/Linux operating system i.e. Sun Solaris, IBM AIX, HP-UX, Red Hat, Fedora etc, All you need to know that the commands which are specific to OS during the installation.

Never just be satisfied by simply reading the solutions given over the web for such problem which are treated as real time scenarios, rather try to reproduce the problem in your database system, if you can, and do apply the different solutions for that issue.

Do not mug up the procedural steps of any major activity in the database i.e. Upgrade, Migration, Installation, etc.., Even though these are not regular tasks or not possible to do it in the practice systems, I still insist to feel the taste of doing such activities. I can say these are the real time scenarios asked in the interviews.

There are many a lot to say…but at the end what all I can say is…..

Instead of waiting for not having the proper resource to practice the database real time scenarios or activities, at least try to search over the web to get to know what are other real time scenarios, I would strongly advice one to make a habit of regularly visiting OTN Database General Forums, where all kind of basic, advanced, real time, scenarios are questioned and answered by top experts with different and different solutions.

Forum: Database - General

Another good habit is referring the good Oracle Related Blogs to know how they resolved the issues, how they implement the things in their organization with their experience.

List of Oracle-related blogs

Do not forget to read and download this great document "Grow That DBA Career"

Note: Above suggestions are only my views and need not to be the same with others. Whoever have the information of real time ideas/tips and wanted share with the blog readers, they are free allowed to comment directly in the comments section of this blog post. I will also keep update this post with more and more real time experience ideas and tips.

Update: Take a look at the Mr.TOM comment in the comment section below, where he has given his own views on real time tips further to this blog post. Thanks to TOM for adding his views to this post.

Happy Reading !!!

Download Free Oracle Certification Dumps Here!!

This blog post is for them; those who are desperately looking for free Oracle Certification dumps.
Well, you might be surprised to see the message of the post is irrelevant to the subject. All my intension is to bring your attention towards How bad it is? Cheating the Oracle Certifications by simply reading the exam dumps”.
Mr. Paul Sorensen, Director of Oracle Certification, and other certification team members have launched the Oracle Certification Blog , where they blog about everything on Oracle Certification. Interestingly, there are a couple of blog posts on Cheating Hurts the Oracle Certification Program” and others.
For list of blog posts on Cheating, then take a look at – Cheating Oracle Certifications . Do not forget to read the comments of every post in the above link.
Quick Links to Prepare for Oracle Certification
Keywords:
OCA, OCP, OCE, Dumps, Brain dumps, Practice Questions, Sample Questions, Cheat sheet, Test papers.

How we faster the process of converting a non-ASM single-instance database to RAC database with ASM using RCONFIG tool?

I have been given with a challenging task to convert one of our critical production databases, which is of 1 TB (Terabyte) in size, to Oracle 10g RAC with ASM storage option. Even though, there are many methods and tools available to perform this activity, I have preferred to use the RCONFIG tool.

We prepared an input XML file required for RCONFIG tool, and run the RCONFIG utility as follows:

$ cd /oracle/ora102/db_1/assistants/rconfig/sampleXMLs
$ rconfig ConverToRAC.xml
When we start the RCONFIG tool to convert the database to RAC, the RCONFIG tool initially moves all the non-ASM database files to ASM disk files, for this RCONFIG tool internally invokes RMAN utility to backup the target database to the ASM disk groups, eventually the database is converted to RAC using RCONFIG.

The conversion took almost 9 hours to complete the process, because during the conversion RMAN used only one channel per data file to backup to ASM disks. There was no chance of improving the RMAN copy process by allocating more channels in the input XML file, and also Oracle doesn’t recommend doing other changes in the input XML file.

One thing was observed during the RMAN copy that RMAN is using target database control file instead of recovery catalog, and also using the RMAN default preconfigured settings for that database.

To know the RMAN default preconfigured settings for the database:

$ export ORACLE_SID=MYPROD
$ rman target /
Recovery Manager: Release 10.2.0.4.0 - Production on Wed Aug 5 10:21:05 2009

Copyright (c) 1982, 2007, Oracle. All rights reserved.

connected to target database: MYPROD (DBID=1131234567)

RMAN> show all;

using target database control file instead of recovery catalog
RMAN configuration parameters are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP OFF; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET;
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/oracle/ora102/db_1/dbs/snapcf_T24MIG1.f'; # default
Here we see that the PARALLELISM is 1 (default), that’s why the RMAN using only one channel during backing up the non-ASM datafiles to ASM Disk Groups, and were taking 9 hours to complete the backup.

We have changed the PRALLELISM count to 6 (it depends upon number of CPUs you have in the server).

Solution:

RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 6;

old RMAN configuration parameters:
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET;
new RMAN configuration parameters:
CONFIGURE DEVICE TYPE DISK PARALLELISM 6 BACKUP TYPE TO BACKUPSET;
new RMAN configuration parameters are successfully stored

RMAN> show all;

RMAN configuration parameters are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP OFF; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 6 BACKUP TYPE TO BACKUPSET;
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/oracle/ora102/db_1/dbs/snapcf_T24MIG1.f'; # default
After changing the PARALLELISM count to 6, the RMAN has allocated 6 channels and the conversion process has improved greatly and reduced the downtime drastically to 4 Hours 30 minutes.

Following is the extract of rconfig.log file, this file is located under:

$ORACLE_HOME/db_1/cfgtoolslogs/rconfig
............................................................................
............................................................................
............................................................................
[17:17:16:43] Log RMAN Output=RMAN> backup as copy database to destination '+DATA_DG';
[17:17:16:53] Log RMAN Output=Starting backup at 04-AUG-09
[17:17:16:258] Log RMAN Output=using target database control file instead of recovery catalog
[17:17:16:694] Log RMAN Output=allocated channel: ORA_DISK_1
[17:17:16:698] Log RMAN Output=channel ORA_DISK_1: sid=866 devtype=DISK
[17:17:17:9] Log RMAN Output=allocated channel: ORA_DISK_2
[17:17:17:13] Log RMAN Output=channel ORA_DISK_2: sid=865 devtype=DISK
[17:17:17:324] Log RMAN Output=allocated channel: ORA_DISK_3
[17:17:17:327] Log RMAN Output=channel ORA_DISK_3: sid=864 devtype=DISK
[17:17:17:637] Log RMAN Output=allocated channel: ORA_DISK_4
[17:17:17:641] Log RMAN Output=channel ORA_DISK_4: sid=863 devtype=DISK
[17:17:17:967] Log RMAN Output=allocated channel: ORA_DISK_5
[17:17:17:971] Log RMAN Output=channel ORA_DISK_5: sid=862 devtype=DISK
[17:17:18:288] Log RMAN Output=allocated channel: ORA_DISK_6
[17:17:18:293] Log RMAN Output=channel ORA_DISK_6: sid=861 devtype=DISK
[17:17:20:416] Log RMAN Output=channel ORA_DISK_1: starting datafile copy
[17:17:20:427] Log RMAN Output=input datafile fno=00053 name=/oradata/MYPROD/users_01.dbf
[17:17:20:532] Log RMAN Output=channel ORA_DISK_2: starting datafile copy
[17:17:20:544] Log RMAN Output=input datafile fno=00021 name=/oradata/MYPROD/ users_02.dbf
[17:17:20:680] Log RMAN Output=channel ORA_DISK_3: starting datafile copy
[17:17:20:694] Log RMAN Output=input datafile fno=00022 name=/oradata/MYPROD/ users_03.dbf
[17:17:20:786] Log RMAN Output=channel ORA_DISK_4: starting datafile copy
[17:17:20:800] Log RMAN Output=input datafile fno=00023 name=/oradata/MYPROD/ users_04.dbf
[17:17:20:855] Log RMAN Output=channel ORA_DISK_5: starting datafile copy
[17:17:20:868] Log RMAN Output=input datafile fno=00024 name=/oradata/MYPROD/ users_05.dbf
[17:17:20:920] Log RMAN Output=channel ORA_DISK_6: starting datafile copy
[17:17:20:930] Log RMAN Output=input datafile fno=00011 name=/oradata/MYPROD/ users_06.dbf
............................................................................
............................................................................
............................................................................
[21:29:5:518] Log RMAN Output=Finished backup at 04-AUG-09
............................................................................
............................................................................
............................................................................

[21:39:10:723] [NetConfig.startListenerResources:5] started Listeners associated with database MYPROD
[21:39:10:723] [Step.execute:255] STEP Result=Operation Succeeded
[21:39:10:724] [Step.execute:284] Returning result:Operation Succeeded
[21:39:10:724] [RConfigEngine.execute:68] bAsyncJob=false
[21:39:10:725] [RConfigEngine.execute:77] Result= < version="1.1">


<ConvertToRAC>
    <Convert>
      <Response>
        <Result code="0" >
          Operation Succeeded
        </Result>
      </Response>
      <ReturnValue type="object">
<Oracle_Home>
         /oracle/ora102/db_1
       </Oracle_Home>
        <SIDList>
          <SID>MYPROD1<\SID>
          <SID>MYPROD2<\SID>
        <\SIDList>     </ReturnValue>
    </Convert>
  </ConvertToRAC></RConfig>

Note: For the sake of look and feel format, the above output has been trimmed neatly. You can also observer that 6 channels were being allocated, timings of backup start and end, and the success code end of the rconfig.log file.

References:

To know more about RCONFIG tool and other Metalink references on it, please take a look at the below blog post written by Mr. Syed Jaffar Hussain.

http://jaffardba.blogspot.com/2008/09/my-experience-of-converting-cross.html

Oracle 10g R2 Documentation information on RCONFIG:

http://download.oracle.com/docs/cd/B19306_01/install.102/b14205/cvrt2rac.htm#BABBAAEH

Does a STARTUP MOUNT verify datafiles ?

There seems to be a misunderstanding that a MOUNT actually verifies datafiles.
A STARTUP MOUNT  (or STARTUP NOMOUNT followed by ALTER DATABASE MOUNT) does *NOT* read the datafiles and/or verify them.  It does read the controlfile(s).

Here's a simple test :
I have a tablespace with a datafile that is "ONLINE".
SQL> create tablespace X_TBS datafile '/tmp/X_TBS.dbf' size 50M;

Tablespace created.

SQL> create table hemant.X_TBS (col_1) tablespace X_TBS
  2  as select rownum from dual connect by level < 100;

Table created.

SQL> 

SQL> select file#, status, name 
  2  from v$datafile
  3  where name like '%X_TBS%';

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/X_TBS.dbf

SQL> select file#, status, name
  2  from v$datafile_header
  3  where name like '%X_TBS%';

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/X_TBS.dbf

SQL> select owner, segment_name, bytes/1024
  2  from dba_segments
  3  where tablespace_name = 'X_TBS';

OWNER
------------------------------
SEGMENT_NAME
--------------------------------------------------------------------------------
BYTES/1024
----------
HEMANT
X_TBS
        64


SQL> 
I now shutdown the database instance and remove the datafile :
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> !ls /tmp/X_TBS.dbf
/tmp/X_TBS.dbf

SQL> !rm /tmp/X_TBS.dbf

SQL> !ls /tmp/X_TBS.dbf
ls: /tmp/X_TBS.dbf: No such file or directory

SQL> 
Does the STARTUP MOUNT succeed ?
SQL> startup mount
ORACLE instance started.

Total System Global Area  535662592 bytes
Fixed Size                  1337720 bytes
Variable Size             213911176 bytes
Database Buffers          314572800 bytes
Redo Buffers                5840896 bytes
Database mounted.
SQL>
SQL> shutdown
ORA-01109: database not open


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

Total System Global Area  535662592 bytes
Fixed Size                  1337720 bytes
Variable Size             213911176 bytes
Database Buffers          314572800 bytes
Redo Buffers                5840896 bytes
SQL> alter database mount;

Database altered.

SQL> 
Can the file be listed ? Yes. However, V$DATAFILE_HEADER no longer shows the name ! The query on V$DATAFILE_HEADER does cause Oracle to "look" for the file but it does NOT cause a failure. It simply finds it "missing".
SQL> select file#, status, name
  2  from v$datafile
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/X_TBS.dbf

SQL> select file#, status, name
  2  from v$datafile_header
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE

SQL> 
When does Oracle attempt to access the datafile ?
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01157: cannot identify/lock data file 14 - see DBWR trace file
ORA-01110: data file 14: '/tmp/X_TBS.dbf'


SQL> 
Even as the OPEN failed with an ORA-01157, the datafile is present in the controlfile :
SQL> select file#, status, name
  2  from v$datafile
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/X_TBS.dbf

SQL> select file#, status, name
  2  from v$datafile_header
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE

SQL> 
I hope that I have you convinced that a MOUNT does NOT verify the datafiles. If you are still not convinced, read the Backup and Recovery documentation about how to do a FULL DATABASE RESTORE and RECOVER -- where you restore the controlfile and mount the database before you even restore datafiles. How would the MOUNT succeed with the controlfile alone ?

Now, here's something more. You'd understand this if you understand how RECOVER works. Do NOT try this if you are not sure about how I was able to "recreate" the datafile. Do NOT try this if you do not know how data is inserted in the X_TBS table when the database is in NOARCHIVELOG mode.

SQL> alter database create datafile 14 as '/tmp/new_X_TBS.dbf';

Database altered.

SQL> recover datafile 14;
Media recovery complete.
SQL> select file#, status, name
  2  from v$datafile
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/new_X_TBS.dbf

SQL> select file#, status, name
  2  from v$datafile_header
  3  where file#=14;

     FILE# STATUS  NAME
---------- ------- ----------------------------------------
        14 ONLINE  /tmp/new_X_TBS.dbf

SQL> alter database open;

Database altered.

SQL> select tablespace_name from dba_tables
  2  where owner = 'HEMANT'
  3  and table_name = 'X_TBS';

TABLESPACE_NAME
------------------------------
X_TBS

SQL> 
SQL> select file_name from dba_data_files
  2  where file_id=14;

FILE_NAME
--------------------------------------------------------------------------------
/tmp/new_X_TBS.dbf

SQL>
SQL> select count(*) from hemant.X_TBS;
select count(*) from hemant.X_TBS
                            *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 14, block # 131)
ORA-01110: data file 14: '/tmp/new_X_TBS.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option


SQL> 

Happy simulating and testing on your own database.

Understanding RESETLOGS

Whenever we do an Incomplete Recovery (recovery until CANCEL or until a specific SCN/CHANGE#, SEQUENCE# or TIME), we have to OPEN the database with a RESETLOGS.

RESETLOGS_TIME has to be indicated by Oracle if we were to query the database later. This is the time when the RESETLOGS was issued. RESETLOGS_CHANGE# is the SCN for the database at the issuance of the command. Oracle also provides information of the RESETLOGS_ID for each "incarnation". A RESETLOGS creates a new "incarnation" of the database.

Thus, my database has this information :
SQL> select sysdate from dual;

SYSDATE
---------
29-JAN-12

SQL> select resetlogs_time from v$database;

RESETLOGS
---------
01-JAN-12

SQL> select incarnation#, resetlogs_change#, resetlogs_time, resetlogs_id                            
  2  from v$database_incarnation
  3  order by 1;

INCARNATION# RESETLOGS_CHANGE# RESETLOGS RESETLOGS_ID
------------ ----------------- --------- ------------
           1                 1 13-AUG-09    694825248
           2            754488 30-OCT-09    701609923
           3           4955792 01-JAN-12    771419578
           4           4957614 01-JAN-12    771421939

SQL> 
As of today, 29-Jan, we can see that the database has undergone 4 RESETLOGS, the latest having been on 01-JAN-12 (in fact, there were two RESETLOGS that date). Why does this query report duplicate entries for the same SEQUENCE# ?
SQL> l
  1  select sequence#, trunc(first_time)
  2  from v$archived_log
  3  where first_time > to_date('31-DEC-11','DD-MON-RR')
  4* order by 1
SQL> /

 SEQUENCE# TRUNC(FIR
---------- ---------
         1 01-JAN-12
         1 01-JAN-12
         1 01-JAN-12
         1 01-JAN-12
         1 01-JAN-12
         2 01-JAN-12
         2 01-JAN-12
         2 14-JAN-12
         2 01-JAN-12
         2 01-JAN-12
         3 01-JAN-12
         3 01-JAN-12
         3 15-JAN-12
         3 01-JAN-12
         4 15-JAN-12
         5 15-JAN-12
       180 01-JAN-12
       180 01-JAN-12
       180 01-JAN-12
       181 01-JAN-12
       181 01-JAN-12
       181 01-JAN-12
       182 01-JAN-12
       182 01-JAN-12

24 rows selected.

SQL> 
It does seem very confusing to have SEQUENCE#1 to SEQUENCE#3 report 5 entries each. And why is there a gap between SEQUENCE#5 and SEQUENCE#180 ?   Can we dig deeper ?
I can collect more information thus :
SQL> select resetlogs_id, sequence#, trunc(first_time)
  2  from v$archived_log
  3  order by 1,2
  4  /

RESETLOGS_ID  SEQUENCE# TRUNC(FIR
------------ ---------- ---------
   701609923        179 26-DEC-11
   701609923        180 01-JAN-12
   701609923        180 01-JAN-12
   701609923        180 01-JAN-12
   701609923        181 01-JAN-12
   701609923        181 01-JAN-12
   701609923        181 01-JAN-12
   701609923        182 01-JAN-12
   701609923        182 01-JAN-12
   771419578          1 01-JAN-12
   771419578          1 01-JAN-12
   771419578          1 01-JAN-12
   771419578          1 01-JAN-12
   771419578          2 01-JAN-12
   771419578          2 01-JAN-12
   771419578          2 01-JAN-12
   771419578          2 01-JAN-12
   771419578          3 01-JAN-12
   771419578          3 01-JAN-12
   771419578          3 01-JAN-12
   771421939          1 01-JAN-12
   771421939          2 14-JAN-12
   771421939          3 15-JAN-12
   771421939          4 15-JAN-12
   771421939          5 15-JAN-12

25 rows selected.

SQL> 
Now, I can see that the SEQUENCE# 179 to 182 are for 26-DEC-11 to 01-JAN-12 for INCARNATION#2 which existed from 30-OCT-09 to 01-JAN-12 (this information is retrieved from V$DATABASE_INCARNATION from the earlier query). Yet, there are repeated entries from the same SEQUENCE# (180 and 181 have three entries each while 182 has two entries) !   Was each log file archived more than once ?  Similarly, in INCARNATION#3 I have three entries for each of SEQUENCE# 1 to 3.  Then, the latest INCARNATION#4  (for RESETLOGS_ID 771421939) has only 1 entry each for SEQUENCE# 1 to 5.

Were there really multiple archivelogs created from SEQUENCE# 180 to 182 and again for 1 to 3 on 01-JAN-12 ?
Here's a listing of archivelog files :

[oracle@linux64 2012_01_01]$ pwd
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01
[oracle@linux64 2012_01_01]$ ls -ltr
total 10200
-rw-rw---- 1 oracle oracle 5261824 Jan  1 10:59 o1_mf_1_179_7hzlzvcg_.arc
-rw-rw---- 1 oracle oracle   90112 Jan  1 11:00 o1_mf_1_180_7hzm1ogl_.arc
-rw-rw---- 1 oracle oracle  483840 Jan  1 11:02 o1_mf_1_181_7hzm5frg_.arc
-rw-rw---- 1 oracle oracle  377856 Jan  1 11:12 o1_mf_1_182_7hzmst65_.arc
-rw-rw---- 1 oracle oracle  483840 Jan  1 11:12 o1_mf_1_181_7hzmst4n_.arc
-rw-rw---- 1 oracle oracle   90112 Jan  1 11:12 o1_mf_1_180_7hzmst70_.arc
-rw-rw---- 1 oracle oracle 1486336 Jan  1 11:25 o1_mf_1_1_7hznjsy3_.arc
-rw-rw---- 1 oracle oracle   15872 Jan  1 11:26 o1_mf_1_2_7hznmzh7_.arc
-rw-rw---- 1 oracle oracle  590848 Jan  1 11:52 o1_mf_1_3_7hzp3my5_.arc
-rw-rw---- 1 oracle oracle   15872 Jan  1 11:52 o1_mf_1_2_7hzp3mxw_.arc
-rw-rw---- 1 oracle oracle 1486336 Jan  1 11:52 o1_mf_1_1_7hzp3mvq_.arc
[oracle@linux64 2012_01_01]$ 
That's curious ! I dont' see three archivelog files, but I do see two archivelogs for SEQUENCE# 180 and 181 and 1 and 2!!

Can anyone explain this ?
Hint : I did an OPEN RESETLOGS.

.
.
UPDATE 06-Feb :
Since there hasn't been a response ....
some more information ...
SQL> l
  1  select sequence#, resetlogs_id,
  2  to_char(first_time,'DD-MON HH24:MI:SS'), to_char(completion_time,'DD-MON HH24:MI:SS'),
  3  nvl(name,'Name is a NULL')
  4  from v$archived_log
  5  where sequence# in (1,2,3,180,181,182)
  6* order by sequence#, resetlogs_id, completion_time
SQL> /

 SEQUENCE# RESETLOGS_ID TO_CHAR(FIRST_TIME,'DD-M TO_CHAR(COMPLETION_TIME,
---------- ------------ ------------------------ ------------------------
NVL(NAME,'NAMEISANULL')
--------------------------------------------------------------------------------
         1    771419578 01-JAN 11:12:58          01-JAN 11:25:14
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
_7hznjsy3_.arc

         1    771419578 01-JAN 11:12:58          01-JAN 11:48:44
Name is a NULL

         1    771419578 01-JAN 11:12:58          01-JAN 11:50:00
/home/oracle/app/oracle/oradata/orcl/redo01.log

         1    771419578 01-JAN 11:12:58          01-JAN 11:52:19
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
_7hzp3mvq_.arc

         1    771421939 01-JAN 11:52:19          14-JAN 23:48:56
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_14/o1_mf_1_1
_7k38z82o_.arc

         2    771419578 01-JAN 11:25:13          01-JAN 11:26:55
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_2
_7hznmzh7_.arc

         2    771419578 01-JAN 11:25:13          01-JAN 11:48:44
Name is a NULL

         2    771419578 01-JAN 11:25:13          01-JAN 11:50:00
/home/oracle/app/oracle/oradata/orcl/redo02.log

         2    771419578 01-JAN 11:25:13          01-JAN 11:52:19
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_2
_7hzp3mxw_.arc

         2    771421939 14-JAN 23:48:55          15-JAN 22:47:38
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_15/o1_mf_1_2
_7k5srb64_.arc

         3    771419578 01-JAN 11:26:55          01-JAN 11:48:44
Name is a NULL

         3    771419578 01-JAN 11:26:55          01-JAN 11:50:00
/home/oracle/app/oracle/oradata/orcl/redo03.log

         3    771419578 01-JAN 11:26:55          01-JAN 11:52:19
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_3
_7hzp3my5_.arc

         3    771421939 15-JAN 22:47:38          15-JAN 23:14:40
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_15/o1_mf_1_3
_7k5vc0nf_.arc

       180    701609923 01-JAN 10:59:07          01-JAN 11:00:05
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
80_7hzm1ogl_.arc

       180    701609923 01-JAN 10:59:07          01-JAN 11:11:00
Name is a NULL

       180    701609923 01-JAN 10:59:07          01-JAN 11:12:58
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
80_7hzmst70_.arc

       181    701609923 01-JAN 11:00:05          01-JAN 11:08:38
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
81_7hzm5frg_.arc

       181    701609923 01-JAN 11:00:05          01-JAN 11:11:00
Name is a NULL

       181    701609923 01-JAN 11:00:05          01-JAN 11:12:58
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
81_7hzmst4n_.arc

       182    701609923 01-JAN 11:02:05          01-JAN 11:11:00
Name is a NULL

       182    701609923 01-JAN 11:02:05          01-JAN 11:12:58
/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_1
82_7hzmst65_.arc


22 rows selected.

SQL> 
Look at the number of occurrences of SEQUENCE#1. Check the COMPLETION TIME for these entries. Why is the NAME a NULL value for some occurrences ?

.....  OK .... since it is unlikely that anyone will yet reply to the latest question .....
Here's more information from the alert.log :
Sun Jan 01 11:25:13 2012
ALTER SYSTEM ARCHIVE LOG
Sun Jan 01 11:25:13 2012
Thread 1 advanced to log sequence 2 (LGWR switch)
  Current log# 2 seq# 2 mem# 0: /home/oracle/app/oracle/oradata/orcl/redo02.log
Sun Jan 01 11:25:14 2012
Archived Log entry 10 added for thread 1 sequence 1 ID 0x4d6fd925 dest 1:


Sun Jan 01 11:33:24 2012
alter database mount
Sun Jan 01 11:33:28 2012
Successful mount of redo thread 1, with mount id 1299165956
Database mounted in Exclusive Mode
Lost write protection disabled
Completed: alter database mount
Sun Jan 01 11:35:19 2012
Errors in file /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_m000_4414.trc:
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
ORA-01122: database file 14 failed verification check
ORA-01110: data file 14: '/oradata/add_tbs.dbf'
ORA-01565: error in identifying file '/oradata/add_tbs.dbf'
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
Checker run found 1 new persistent data failures
Sun Jan 01 11:36:21 2012
Errors in file /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_m000_4427.trc:
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
ORA-01122: database file 14 failed verification check
ORA-01110: data file 14: '/oradata/add_tbs.dbf'
ORA-01565: error in identifying file '/oradata/add_tbs.dbf'
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
Sun Jan 01 11:36:23 2012
Full restore complete of datafile 7 /home/oracle/app/oracle/oradata/orcl/FLOW_1146416395631714.dbf.  Elapsed time: 0:00:00
  checkpoint is 4956847
  last deallocation scn is 960623
Full restore complete of datafile 4 /home/oracle/app/oracle/oradata/orcl/users01.dbf.  Elapsed time: 0:00:08
  checkpoint is 4956847
  last deallocation scn is 4932522
Sun Jan 01 11:36:38 2012
Full restore complete of datafile 6 /home/oracle/app/oracle/oradata/orcl/FLOW_1046101119510758.dbf.  Elapsed time: 0:00:00
  checkpoint is 4956853
  last deallocation scn is 833081
Full restore complete of datafile 8 /home/oracle/app/oracle/oradata/orcl/FLOW_1170420963682633.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956853
  last deallocation scn is 969921
Full restore complete of datafile 5 /home/oracle/app/oracle/oradata/orcl/example01.dbf.  Elapsed time: 0:00:03
  checkpoint is 4956853
  last deallocation scn is 985357
Full restore complete of datafile 9 /home/oracle/app/oracle/oradata/orcl/FLOW_1194425963955800.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956856
  last deallocation scn is 976123
Full restore complete of datafile 10 /home/oracle/app/oracle/oradata/orcl/FLOW_1218408858999342.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956856
  last deallocation scn is 981657
Full restore complete of datafile 11 /home/oracle/app/oracle/oradata/orcl/FLOW_1242310449730067.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956856
  last deallocation scn is 1367698
Full restore complete of datafile 12 /home/oracle/app/oracle/oradata/orcl/FLOW_1266412439758696.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956856
  last deallocation scn is 2558126
Full restore complete of datafile 13 /home/oracle/app/oracle/oradata/orcl/APEX_1295922881855015.dbf.  Elapsed time: 0:00:01
  checkpoint is 4956856
Sun Jan 01 11:37:41 2012
Signalling error 1152 for datafile 4!
Signalling error 1152 for datafile 5!
Signalling error 1152 for datafile 6!
Signalling error 1152 for datafile 7!
Signalling error 1152 for datafile 8!
Signalling error 1152 for datafile 9!
Signalling error 1152 for datafile 10!
Signalling error 1152 for datafile 11!
Signalling error 1152 for datafile 12!
Signalling error 1152 for datafile 13!
Errors in file /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_m000_4436.trc:
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
ORA-01122: database file 14 failed verification check
ORA-01110: data file 14: '/oradata/add_tbs.dbf'
ORA-01565: error in identifying file '/oradata/add_tbs.dbf'
ORA-27037: unable to obtain file status
Linux Error: 13: Permission denied
Additional information: 3
Checker run found 12 new persistent data failures
Sun Jan 01 11:41:53 2012
Signalling error 1152 for datafile 4!
Signalling error 1152 for datafile 5!
Signalling error 1152 for datafile 6!
Signalling error 1152 for datafile 7!
Signalling error 1152 for datafile 8!
Signalling error 1152 for datafile 9!
Signalling error 1152 for datafile 10!
Signalling error 1152 for datafile 11!

Sun Jan 01 11:44:09 2012
Full restore complete of datafile 1 /home/oracle/app/oracle/oradata/orcl/system01.dbf.  Elapsed time: 0:01:09
  checkpoint is 4956816 
  last deallocation scn is 2681676
  Undo Optimization current scn is 4717725

Sun Jan 01 11:45:38 2012
Full restore complete of datafile 2 /home/oracle/app/oracle/oradata/orcl/sysaux01.dbf.  Elapsed time: 0:01:13
  checkpoint is 4956816
  last deallocation scn is 4862545

Sun Jan 01 11:45:57 2012
Full restore complete of datafile 3 /home/oracle/app/oracle/oradata/orcl/undotbs01.dbf.  Elapsed time: 0:00:10
  checkpoint is 4956816
  last deallocation scn is 4718440
  Undo Optimization current scn is 4717725

Sun Jan 01 11:48:02 2012
Full restore complete of datafile 14 to datafile copy /home/oracle/app/oracle/oradata/orcl/add_tbs.dbf.  Elapsed time: 0:00:00 
  checkpoint is 4956816

Switch of datafile 14 complete to datafile copy
  checkpoint is 4956816

alter database recover datafile list clear
Completed: alter database recover datafile list clear
alter database recover datafile list
 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14
Completed: alter database recover datafile list
 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14
alter database recover if needed
 start until cancel using backup controlfile
Media Recovery Start
 started logmerger process
Parallel Media Recovery started with 4 slaves
ORA-279 signalled during: alter database recover if needed
 start until cancel using backup controlfile
...
alter database recover logfile '/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_2_7hznmzh7_.arc'
Media Recovery Log /home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_2_7hznmzh7_.arc
Sun Jan 01 11:50:01 2012
ORA-279 signalled during: alter database recover logfile '/home/oracle/app/oracle/flash_recovery_area/ORCL/archivelog/2012_01_01/o1_mf_1_2_7hznmzh7_.arc'...
alter database recover logfile '/home/oracle/app/oracle/oradata/orcl/redo03.log'
Media Recovery Log /home/oracle/app/oracle/oradata/orcl/redo03.log
Sun Jan 01 11:50:01 2012
Incomplete recovery applied all redo ever generated.
Recovery completed through change 4957613 time 01/01/2012 11:30:06
Media Recovery Complete (orcl)
Completed: alter database recover logfile '/home/oracle/app/oracle/oradata/orcl/redo03.log'
Sun Jan 01 11:52:19 2012
alter database open resetlogs
Archived Log entry 18 added for thread 1 sequence 1 ID 0x4d6fd925 dest 1:
Archived Log entry 19 added for thread 1 sequence 2 ID 0x4d6fd925 dest 1:
Archived Log entry 20 added for thread 1 sequence 3 ID 0x4d6fd925 dest 1:
RESETLOGS after complete recovery through change 4957613
Resetting resetlogs activation ID 1299175717 (0x4d6fd925)
Sun Jan 01 11:52:23 2012
Setting recovery target incarnation to 4
Sun Jan 01 11:52:23 2012
Assigning activation ID 1299165956 (0x4d6fb304)

Sun Jan 01 11:52:24 2012
ARC2 started with pid=20, OS id=4534
Thread 1 opened at log sequence 1
  Current log# 1 seq# 1 mem# 0: /home/oracle/app/oracle/oradata/orcl/redo01.log
Successful open of redo thread 1

Do you notice how SEQUENCE#1 was Archive Log Entry 10 and again entry 18 after an OPEN RESETLOGS. The actual Online Redo Log files were *still present* and yet, I did an Incomplete Recovery and OPEN RESETLOGS. The Onlne Redo Log file that was present on disk was *again* archived out by Oracle (and a new activiation ID and target incarnation assigned). Thus, this was an OPEN RESETLOGS with Online Redo Logs present. Oracle automatically detected that the files were present and archived them out ! . .

HOWTO: Disaster Recovery: Recovering the RMAN catalog database using RMAN

What's the first step in a DR scenario? Recovering the RMAN catalog database of course!

Can you use RMAN to recover RMAN? Yes, you can!

For my money, the best feature of RMAN is that even though the catalog database itself will not startup without recovery, it can still be used. Which is great, because otherwise we have one of those dreaded Star Trek space-time paradoxes (what do you do to recover your recovery system?!), and those make my head hurt. Even better, it's really pretty easy if you know what to do.

My scenario is:
I walk into work one morning and the production box that my RMAN catalog is running on got hosed-up somehow over night (i'm not naming any names... *cough* sysadmin *cough*) and now all of the databases on the box are down and in need of recovery as well as the RMAN database.

Note that in this particular case, the RMANDB database needed archive logs that were not on the system in order to be recovered. This is what necessitates the use of Step 5 below to retrieve the file, otherwise, this step could be skipped.

Here's how we fix the RMAN catalog database:
  1. Set your Oracle environment variables as normal (I use "oraenv")
    1. $ . oraenv
  2. Start rman
    1. $ rman
  3. Connect to the target DB and then the catalog (I use the "rman" user as my catalog owner and i've named my RMAN catalog database "rmandb")
    1. RMAN> connect target
    2. RMAN> connect catalog rman@rmandb
      1. RMAN-00571: ===========================================================
        RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
        RMAN-00571: ===========================================================
        RMAN-04004: error from recovery catalog database: ORA-01034: ORACLE not available
        ORA-27101: shared memory realm does not exist
        IBM AIX RISC System/6000 Error: 2: No such file or directory
  4. Recover the database
    1. RMAN> startup force nomount;
      1. Oracle instance started
        Total System Global Area 2164260864 bytes
        Fixed Size 2074256 bytes
        Variable Size 704645488 bytes
        Database Buffers 1442840576 bytes
        Redo Buffers 14700544 bytes
    2. RMAN> alter database mount;
      1. database mounted
  5. Get the missing archive logs back from tape/disk/TSM/whatever
    1. NOTE: When I first tried the "startup" command the database it told me it need archive log 241 and up, so that is where the value below came from (you can always use "restore archivelog all")
    2. RMAN> run {
      allocate channel oem_restore type sbt parms 'ENV=(TDPO_OPTFILE=/usr/tivoli/tsm/client/oracle/bin64/tdpo.opt)';
      allocate channel oem_restore_disk type disk;
      restore archivelog from logseq=241 thread=1;
      }
  6. Open the database
    1. RMAN> alter database open resetlogs;
Having gone through this exercise just a couple of months ago, I can tell you that I was absolutely thrilled when this worked!!

HowTo: Clearing Alerts in OEM 10g Grid Control

I was browsing the Oracle Forums earlier today and this post with a bit of SQL to clear OEM alerts from mnazim, who always has good advice to offer:
To clear the alert:

1. Make a SELECT * from MGMT_CURRENT_SEVERITY and show for the TARGET_GUID, METRIC_GUID and KEY_VALUE.

2. Connect to db user SYSMAN and execute:
exec EM_SEVERITY.delete_current_severity(TARGET_GUID, METRIC_GUID, KEY_VALUE);

for example:
exec EM_SEVERITY.delete_current_severity('0DEB8E6980695B7548CF98871084AD10', 'F95BA0D95585002889E1ABF92B2DA7C3', 'SYS');

HowTo: Resolve Oracle 11g X-Windows installer issues on UNIX

Have you run the new Oracle 11g installer on *NIX and received a nasty message?

It happened to me this week! So, let's say you download the oracle11g installer for AIX, start x-windows (I prefer CygWin), export your display, test with xclock, then go into the "database" folder and do: ./runInstaller

These are the errors I received:

Starting Oracle Universal Installer...

Checking Temp space: must be greater than 190 MB. Actual 11907 MB Passed
Checking swap space: must be greater than 150 MB. Actual 19968 MB Passed
Checking monitor: must be configured to display at least 256 colors. Actual 16777216 Passed
Preparing to launch Oracle Universal Installer from /oracle/tmp/OraInstall2010-03-11_12-25-37PM. Please wait ...
[oracle@myserver 12:26:03] (brent01) /oracle/INSTALL/database
$ Exception in thread "main" java.lang.UnsatisfiedLinkError: /oracle/tmp/OraInstall2010-03-11_12-25-37PM/jdk/jre/bin//motif21/libmawt.a ( 0509-022 Cannot load module /oracle/tmp/OraInstall2010-03-11_12-25-37PM/jdk/jre/bin//motif21/libmawt.a.
0509-150 Dependent module /usr/lpp/X11/lib/libXt.a(shr_64.o) could not be loaded.
0509-152 Member shr_64.o is not found in archive
0509-022 Cannot load module /oracle/tmp/OraInstall2010-03-11_12-25-37PM/jdk/jre/bin//motif21/libmawt.a.
0509-150 Dependent module /oracle/tmp/OraInstall2010-03-11_12-25-37PM/jdk/jre/bin//motif21/libmawt.a could not be loaded.)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:986)

Well, that's a fine mess!

Before you comb MetaLink and create soft links to other libraries, etc. do yourself a favor and try this:

$ env | grep -i libpath

If your LIBPATH environment variable contains the system's X11 lib, then that's your problem. Mine showed:

LIBPATH=/lib:/usr/lpp/X11/lib:/oracle/oracle8i/product/8.1.7/lib

Removing "/usr/lpp/X11/lib" piece from my LIBPATH resolved the error.

$ export LIBPATH="/lib"
$ ./runInstaller

Success!

HowTo: Create a universal UDM report page in OEM

HowTo: Create a universal UDM report page in OEM

PROBLEM:
  • You have a bunch of User Defined Metrics (UDM) setup in OEM, and you want to know the staus of each of them.
  • OEM does not provide a single page to show the status of UDMs - users must navigate to each instance and look at the UDM page.
SOLUTION:
  • Create a standard OEM Report to display all of your UDMs in one place!
STEPS:
  1. First, if you have not already discovered this the hard way, you cannot create a Report against a non-EMREP/non-Repository tables. Why, i'll never know. But, whatever. The thing is, if you try to create a report using something easy like showing how many records are in an Target Database table, it will return the error "ORA-00942: table or view does not exist"
  2. In this case, we are actually hitting an OEM Repository table, but it's not one of the objects we are allowed to query via the "Table From SQL" report element type.
  3. Fortunately, "bwolter" found a work-around for this sorry situation and published how to it in this Oracle OEM Forum post.
  4. Follow his 3 easy steps, then continue with my Step 5 below.
  5. Create a new Report and choose whatever you want for Category, etc.
  6. Set the "Targets" value to the "Use the specified target" radio-button and select your Repository SID
  7. Set the "Privileges" value to "Run report using target privileges of the report owner (SYSTEM)"
  8. Click the "Elements" sub-tab, then Add a new element using the new "target_user_table_from_sql" type.
  9. Click the "Set Parameters" icon and enter your SQL. Note that your value of KEY_VALUE will be different than mine!
  10. SELECT DISTINCT UPPER(target_name) "Target Name",
           key_value || '__' "Metric Name",
           TO_CHAR(collection_timestamp, 'MM-DD-YYYY HH24:MI') "Last Collected_____",
           string_value "Metric Value"
      FROM sysman.em$current_metrics
     WHERE metric_name = 'SQLUDM'
       AND UPPER(key_value) LIKE 'ENSURE%'
       AND string_value IS NOT NULL
     ORDER BY 1, 2
  11. My KEY_VALUE (the "Name" you used for the UDM) is "Ensure PMON is running as MST", so obviously you will set your value to whatever the Name of your UDM is.
  12. Rinse-and-repeat Steps 8-10 for each UDM type or gorup you want to show on the Report.
NOTES:
  • I use underscore in my column alias names to stretch the columns out for easy reading.
  • During this project I found a UDM which had encountered errors and stopped running! OEM showed no indication outside of a small icon on the Instance's UDM page (nor did it send a notification). This report will save you from that potential embarrasement!!
RESULTS:
  • Here is what my final UDM Report looks like:

HowTo: Remove parameters from the spfile

Here's a question that comes up often:
  • How do you remove an SPFILE parameter (not change the value of, but actually purge it outright)?
Answer:
  • Use "ALTER SYSTEM RESET ..." (For database versions 9i and up)
Syntax:
  • ALTER SYSTEM RESET PARAMETER SID='SID|*'
  • ALTER SYSTEM RESET "_TRACE_FILES_PUBLIC" SCOPE=SPFILE SID='*';
NOTE: The "SID='SID|*'" argument is REQUIRED!

HowTo: Setup SSH equivalency

Here's a simple approach to setting up SSH (Secure SHell) equivalency across 2 UNIX boxes. This is also known as "using SSH and SCP without passwords".

There are a variety of reasons to setup SSH equivalency across UNIX boxes. I assume you already have a desire to do so or you would not be reading this, so let's skip the sales patch and get to the howto part.

While there are scripts that do this for you (especially if you're doing this for OEM setup), this is really easy to do on your own, so forget those kludgey scripts!

NOTE: I'm using "UNIX01" and "UNIX02" below to represent 2 different UNIX boxes along with user "oracle" - you can use whatever user you want, just ensure it's the same on both boxes.

STEPS:
  1. On UNIX01:
    1. Create $HOME/.ssh, if it does not already exist
    2. $ cd $HOME/.ssh
    3. Generate your RSA key (NOTE: Your path may vary!)
      1. /usr/bin/ssh-keygen -t rsa
      2. When prompted for a passphrase, just press (ENTER) (leave it blank)
    4. Generate your DSA key
      1. /usr/bin/ssh-keygen -t dsa
      2. When prompted for a passphrase, just press (ENTER) (leave it blank)
    5. Store the 2 keys into the authorized_keys file
      1. cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
      2. cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
  2. On UNIX02:
    1. Repeat steps 1-5 above
  3. On UNIX01:
    1. Copy the 2 lines from authorized_keys on UNIX02
    2. Add them to the authorized_keys file
  4. On UNIX02:
    1. Copy the 2 lines from authorized_keys on UNIX01
    2. Add them to the authorized_keys file
That's it!

Test your setup as follows:
  • [oracle@UNIX01] $ ssh -l oracle unix02 date
It should just show you the date without prompting for a password.

Now you can use scp and other ssh commands with ease!

HOWTO: Connect to Oracle 11g on Windows Vista

After installing 11g on Windows Vista, everything works fine. The listener is up, I can connect with SQL*Plus and misc case tools, etc.

However, no other Windows box on the same network segment (and in the same Workgroup) can access the instance on Vista.

Even a simple ping from a nearby XP box fails with "request timed out."

Google searches for things like "unable to ping vista from xp", etc. yielded the usual "check these" suspects:
  • Workgroup name is the same
  • Simple file sharing is on
  • Network discovery is on
  • Network is Private
All check out on both boxes for me.  I even have both Windows Firewalls disabled, and neither computer has McAfee or Norton, so that's not it.

Finally after 2 days or trying, I figure it's time to do a Crazy Ivan. This is Microsoft we're dealing with... so, I do something crazy; I turn on the Windows Firewall on Vista.  I then clicked over to the second tab on the Firewall dialog and looked thru the checklists.

Do you know what I noticed?  The "File and Printer Sharing" checkbox isn't checked. (Thanks Microsoft for letting me enable file sharing in the Network and Sharing Center and not telling me it was off in the firewall!)

So, [click], I enable that sucker.  Then, since I was already here, I created a new rule (the "Add port..." button) for port 1522:


Now it's back to the XP box again... and VOILA! the ping starts working.  I can even ping the Vista box by it's Windows name (that failed before).  More importantly, I can connect to the ORCL database on vista from XP now!

So, I ~200,000 results in Google for "unable to ping Vista from XP" and it's as simple as a checkbox or two.  This is a newer Vista install, so it appears that this checkbox is off by default, couple that with the inability of Vista to warn you when you enable file sharing, and I can see why almost a quarter million people are going "WTF?!"

ENUM in Oracle

What is ENUM?

ENUM is short for enumeration. Its a useful programming type that contains an ordered list of string values. The programmer can define the valid values depending on their application.

Some good examples of ENUMs would be days and months, or something like directions ('North', 'South', 'East', 'West').

Is there an Oracle 'ENUM' type?

No, not really. But there are other ways of accomplishing the same thing.

For tables, just set it to a string and add a constraint that it is within a certain set.

CREATE TABLE atable (
col1 varchar2(10),
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday'))
);

SQL> INSERT INTO atable (col1) VALUES ('Monday');

1 row created.

SQL> INSERT INTO atable (col1) VALUES ('Blingday');
insert into atable (col1) values ('Blingday')
*
ERROR at line 1:
ORA-02290: check constraint (ROBERT.CONS_ATABLE_COL1) violated

What happens if you use this type in a procedure? Will the constraint be checked? No.

CREATE OR REPLACE PROCEDURE MyProc (in_col IN atable.col1%TYPE)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE(in_col);
END;

SET SERVEROUTPUT ON;

EXEC MyProc('Monday');
EXEC MyProc('Blingday');

So can you create a package subtype for this? That would be more elegant anyway.

But according to Oracle PL/SQL Programming by Steven Feuerstein Chapter 4, I don't think you can (check comments for any refutations to this).

http://www.amazon.com/exec/obidos/ASIN/0596003811/
qid=1117039808/sr=2-1/ref=pd_bbs_b_2_1/102-9543590-3979349


I think the best thing to do in this case is to create a procedure to validate your input.

CREATE OR REPLACE PROCEDURE MyCheck (in_col IN atable.col1%TYPE)
AS
BEGIN
IF (in_col NOT IN ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')) THEN
-- Throw Exception here, be sure to catch it in MyProc!!
NULL;
END IF;
END;

This approach is consistent with Steven Feuerstein's approach to programming. He suggests separating these things into separate procedures. Then when a future release of Oracle supports a concept, or when you figure out how to do it, you can make the change in a single place.

So what is a guy to do?
1. If you want to use enum in a table, use a check constraint.
2. If you want to use enum in a stored procedure, write a separate procedure to validate the input.

NOCOPY Hint

What is NOCOPY?

'NOCOPY' is an optional 'hint' to tell the PL/SQL 'compiler' not to go through the overhead of making a copy of the variable, instead just send a reference. This is generally because we don't plan on modifying it within the procedure.

My first surprise was that you couldn't use "IN NOCOPY." Isn't NOCOPY your way of telling Oracle you don't plan on messing around with the parameter? Yes, but you CAN'T mess with IN parameters, try it!

CREATE OR REPLACE PROCEDURE MyProc (in_value IN number)
AS
BEGIN
in_value := 3;
END;

PLS-00363: expression 'IN_VALUE' cannot be used as an assignment target

Therefore, it is always safe to send IN parameters by reference, making NOCOPY redundant.

My second surprise was that you had to specify NOCOPY for an OUT parameter. Because by definition isn't an OUT parameter stating that you plan on modifying the variable? Why would it be an OUT variable if you weren't touching it? So why would you NOT want NOCOPY? The answer (like so many) comes from Ask Tom:

http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:2047154868085

Tom explains one situation where you want a copy rather than a reference for an OUT or IN OUT parameter. When you change a NOCOPY parameter, it changes right away, instead of upon successful completion of the stored procedure.

Imagine you modified the parameter, but threw an exception before successful completion. But that parameter has been changed and the calling procedure could be stuck with a bogus value.

Despite how much I trust Tom, everybody knows that I don't believe things until I see for myself. And neither should you! Besides, things change. Here's my example.

CREATE OR REPLACE PROCEDURE NoCopyProc (in_value IN OUT NOCOPY number)
AS
x number;
BEGIN
DBMS_OUTPUT.PUT_LINE(in_value || ' NoCopyProc');
in_value := 2;
x := 1/0;
END;

CREATE OR REPLACE PROCEDURE CopyProc (in_value IN OUT number)
AS
x number;
BEGIN
DBMS_OUTPUT.PUT_LINE(in_value || ' CopyProc');
in_value := 4;
x := 1/0;
END;

CREATE OR REPLACE PROCEDURE InterProc (in_value IN OUT NOCOPY number)
AS
BEGIN
IF (in_value = 1) THEN NoCopyProc(in_value);
ELSE CopyProc(in_value);
END IF;
EXCEPTION
WHEN OTHERS THEN NULL;
END;

CREATE OR REPLACE PROCEDURE MyProc
AS
the_value NUMBER(1);
BEGIN
the_value := 1;
InterProc(the_value);
DBMS_OUTPUT.PUT_LINE(the_value);

the_value := 3;
InterProc(the_value);
DBMS_OUTPUT.PUT_LINE(the_value);
END;

BEGIN MyProc; END;

1 NoCopyProc
2
3 CopyProc
3

For an excellent and more detailed overview of NOCOPY, complete with examples, restrictions and performance analysis, I once again refer you to Steven Feuerstein's writings. Although I encourage you to add his books to your collection, this chapter happens to be on-line for free:

Oracle PL/SQL Programming Guide to Oracle8i Features
http://www.unix.org.ua/orelly/oracle/guide8i/ch10_01.htm

So what is a guy to do?

Well, first of all, it was suggested to me that I should find a more gender-neutral way of summing up an article. Allow me to rephrase.

So what should we do?

1. Understand what NOCOPY means and its uses and restrictions (by following those links)
2. Take advantage of NOCOPY when you want the performance advantage of avoiding the cost of the temporary storage for OUT or IN OUT parameters.
3. Avoid NOCOPY when you don't want the side effects if the procedure fails early.

Remember, in the end, that NOCOPY is just a "hint" and Oracle will do whatever it wants anyway. Like all hints, you have to ask yourself what makes it necessary, and what makes you think Oracle is going to choose incorrectly.

Improving your SQL Queries

Greetings! You probably found this page either through a Search Engine, an aggregator that doesn't delete blogs for inactivity, or possibly from a site with a very long blogroll, so let me introduce myself to you.

My name is Robert Vollman. Those who were active in the on-line Oracle community from mid-2005 until mid-2007 may remember me either from this site or sites like it, from the Oracle Technology Network, DBASupport.com forums, or the Dizwell forum.

For those who joined our community more recently, I'm essentially your typical database specialist, and one who enjoys both learning more about Oracle, and in sharing that knowledge with others. I am not Oracle certified, but I've been working with Oracle (and other databases) ever since Oracle 8 about 10 years ago, and most recently I was Technical Editor on Alice Rischert's Oracle SQL By Example, 4th Edition. If you'd like to know more, I've kept all of my old articles, so I encourage you to peruse my archive.

Recently I've been of service to some of my colleagues who have been writing SQL Queries. Based on their feedback, I have helped them write faster-performing queries, in a shorter period of time, with fewer mistakes, and in such a way that maintenance was simpler. If you have found any use in what I'm about to present, you can thank them for encouraging me to dust off my blog and make another contribution to the community. Let's begin!

1. Document Clear Requirements


Some database analysts I've known have actually refused to even begin until they're given clear, documented requirements about what information is to be retrieved, and in what format.

While some of you might not be in a position to put your foot down quite so firmly, I think it's reasonable for you to insist that a certain amount of time is spent gathering and documenting requirements so that both you and those that come later know exactly what your SQL Query is/was meant to do.

Taking the time to get a solid understanding of your goal will help you carefully design your work before you begin, simultaneously reducing development time and decreasing the likelihood of errors.

2. Don't Re-invent the Wheel

Think carefully about the requirements you've been given. Unless they're really unusual, it's very possible that someone has already both seen and solved your problem.

Whether it's a pivot or crosstab query, a hierarchical query, or a task to find nearby rows, there's likely already an easy solution available. It could involve analytical functions, or something like translate or rownum/rowid.

If you're not sure, let me give you the same advice that I give frustrated strangers that find my blog and send me emails. Break down your big problem into smaller, more manageable pieces. Once you've mastered the smaller components of the requirements, start adding it all together.

3. Reduce Complexity

I remember a time when I would use the most sophisticated approach to any problem, and go home thinking I was extremely clever. Since then I've learned that sometimes you should choose to forfeit an improvement in performance if it requires an increase in complexity.

Not everyone has as sophisticated a knowledge of databases as you do, and it's foolish to create complicated queries if it's possible to write simpler ones -- especially if there's no trade-off in performance.

For just a couple of suggestions, consider using ANSI joins instead of the old-school joins, because separating your join clauses from your where clauses might make it easier for others to read. Another idea is to use views as a means to reduce the complexity of any one particular query.

4. Handle NULLs Correctly

Perhaps the most common mistake I encounter is caused by forgetting about NULLs. If someone brings me a query that is either returning rows that it shouldn't, or failing to find rows that it should, quite often it's because the query compares a field to a set value in some fashion, and the fields are NULL for the rows in question.

Databases handle NULLs are handled atypically, something I've covered several times in the past (like here and here). Provided you have this awareness, there are a lot of ways to deal with NULLs, including explicit checks (IS NULL), or something like nvl or decode.

5. Check your Types

Most of what I know I've learned either through experience, or by taking advantage of the experience of others. One of my favourites of which has always been Tom Kyte. He taught me to always be aware of my types when making comparisons: never to compare strings to dates, nor dates to strings.

Take his advice, and beware implicit conversions of dates and numbers. For more of his advice on types, check tips 9-13 in this collection of his tips.

6. Correct handling of duplicates


The next most common error when writing SQL is failing to consider how your query will handle duplicates. Sometimes you want to keep them, sometimes you only want one.

An awareness of how duplicates should be handled not only helps you write your query correctly, but it can sometimes even lead to performance boosts. For example, if you don't mind the duplicates, use UNION ALL instead of UNION.

7. Avoid Unnecessary Tuning

Performance tuning may be fun and high-profile, but most of the time it's unnecessary. Obviously you don't want to go out of your way to write sloppy SQL, but at the same time you don't need to tune your query unless you have a performance problem.

There's no harm in adopting some handy rules of thumb. For example, select only the columns you need instead of selecting *, since there may be an index that will cover your query and get you your rows faster. But if you find yourself commenting your SQL query to override the optimizer plan, then there's a very good chance that you've gone too far, and need to take a step back and find the real problem.

And don't bend over backwards trying to avoid joins. "Joins are not evil, databases were born to join," said Tom Kyte.

8. Use Bind Variables

Failure to use bind variables is one of the red flags that stand out when someone shows me a query. If you see code like this, whether it's generated dynamically or not:

SELECT something FROM somewhere WHERE something = 1234;

Then you could have a performance problem. Why? Because the exact same query with a different value (eg 4321) will be considered a different query, will not be found in the shared pool, and will require another hard parse to generate. That may not be a problem in my simple example, but it become a problem later.

Unless there's no chance a similar query will ever be written using a different value, the correct approach would be to write something like this instead:

SELECT something FROM somewhere WHERE something = :certain_something;

Now it will be found in the shared pool, require only a soft parse, and yield faster returns.

9. Use Source Control

This one is more a matter of personal preference. Ever had a query go missing? Ever had questions about a query, but didn't know who wrote it? Ever made a change to a query, screwed something up, and want to go back?

Don't keep a lot of back-up files kicking around, and don't clutter everything with needless documentation. Find and use a good, central source control repository and organise all your queries within.

10. Test, Test, Test

The three most important words in the Database world.

Furthermore, you want to test your queries on real data, with real volumes, with multiple users, and on a system that's either in use, or has simulated use closely matching the real world. Otherwise you might miss issues that only crop up in a live, high-demand system.

Well, that wraps up my list of suggestions. I really hope you found this helpful, and I'd like to thank you for reading. As always, my comments section are open, so please feel free to add more suggestions of your own, or to comment further on some of mine.

Popular Posts

Followers