Monday, June 28, 2010

Identify Chained Rows & elimination


A Chained row occurs when there is no block which can hold the row after it underwent an update which increased its size beyond the available free space in its hosting block. The solution is to split the row over several blocks.

Results from chained rows: Degraded response for queries.

Following query finds the chained rows:
SELECT   owner c1, table_name c2, pct_free c3, pct_used c4, avg_row_len c5,
         num_rows c6, chain_cnt c7, chain_cnt / num_rows c8
    FROM dba_tables
   WHERE owner NOT IN ('SYS', 'SYSTEM')
     AND table_name NOT IN (SELECT table_name
                              FROM dba_tab_columns
                             WHERE data_type IN ('RAW', 'LONG RAW'))
     AND chain_cnt > 0
ORDER BY chain_cnt DESC

How To Rectify:

1)    Analyze the table:

To prevent an ORA-1495 (specified chained row table not found), run the $ORACLE_HOME/rdbms/admin/utlchain.sql script.
TRUNCATE TABLE CHAINED_ROWS;
ANALYZE TABLE LIST CHAINED ROWS;

2)    List the Chained rows.

col owner_name format a10
col table_name format a20
col head_rowid format a20
select owner_name, table_name, head_rowid from chained_rows;

3) You can now eliminate the Chained rows by Create Table as Select (CTAS), exporting and then importing the table or by following the next steps:

A) Create an empty copy of the table that has the Migrated or Chained rows.
CREATE TABLE TEMP_TAB AS SELECT * FROM
WHERE ROWID IN (SELECT HEAD_ROWID FROM CHAINED_ROWS WHERE TABLE_NAME='TEST');

B) Now delete the Migrated and Chained rows from the table.
DELETE FROM TEST
WHERE ROWID IN (SELECT HEAD_ROWID FROM CHAINED_ROWS WHERE TABLE_NAME='TEMP_TAB');

A)   Insert the rows back to the table.
INSERT INTO TEST SELECT * FROM ;

Truncate the chained_rows table and drop the temporary table.
Alternatively, you can move the table to a tablespace if the row cannot fit in the block and you need a tablespace with a larger block size: alter table move ;

Thursday, June 24, 2010

Oracle Flashback and Recyclebin

The Oracle 10g provides the ability to reinstating an accidentally dropped table, which is called Flashback Drop.

When a table is dropped, the database does not immediately remove the space associated with that table. Instead, the table is renamed to a system-defined name and placed in the Recycle bin. The flashback drop operations recovers from recycle bin.

SQL> DROP TABLE employee_tbl;

You can see the system-defined name of the table.
SQL> select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
BIN$gXxxELu7aQ/gQAoKd5l2Hg==$0 TABLE

You can see the dropped table in the recycle bin using
SQL> show Recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
-------------- ------------------------------ ------------ ----------------
EMPLOYEE_TBL BIN$gXxxELu7aQ/gQAoKd5l2Hg==$0 TABLE 2010-03-01:09:10:00

Recover the dropped table from Recycle bin using
SQL> FLASHBACK TABLE employee_tbl TO BEFORE DROP;

Recover the dropped table from Recycle bin with new name using
SQL> FLASHBACK TABLE employee_tbl TO BEFORE DROP RENAME TO employee_tmp;

You can also drop a table completely with out needing a flashback using
SQL> DROP TABLE employee_tbl PURGE;

The tablespace will not free up space until the table will remain until recycle bin is purged. You can purge table explicitly from recycle bin using
SQL> PURGE TABLE employee_tbl;

Purge all tables in recycle bin using
SQL> PURGE RECYCLEBIN;

As a DBA can purge all the objects in any tablespace using
SQL> PURGE DBA_RECYCLEBIN;

Purge all the objects in recycle bin in a tablespace using
PURGE TABLESPACE employee_tbs;

Purge all the objects in recycle bin in a tablespace specific to a user only using
PURGE TABLESPACE employee_tbs USER emp_user;

Friday, June 18, 2010

How to check free space in ASM


1. Connect to asm instance:

select name, state, total_mb, free_mb from v$asm_diskgroup;

NAME       STATE     TOTAL_MB FREE_MB
—————————— ———– ———- ———-
ORADATA MOUNTED 65536      53439

SELECT name, type, ceil (total_mb/1024) TOTAL_GB , ceil (free_mb/1024) FREE_GB, required_mirror_free_mb,
ceil ((usable_file_mb)/1024) FROM V$ASM_DISKGROUP;


NAME TYPE TOTAL_GB FREE_GB REQUIRED_MIRROR_FREE_MB CEIL((USABLE_FILE_MB)/1024)

ORACLE_DATA1  EXTERN         466 236           0            236
ORACLE_FLASH1 EXTERN         131  124           0            124
ORACLE_FLASH2 EXTERN         10 9 0 9

2. Using Grid Control

Go to asm host and select asm instance. Go Administration tab and input asm administration password:





3. Using ASMCMD tool

Make sure to setup ORACLE_SID and ORACLE_HOME environment variables to ASM instance.

-bash-3.2$ asmcmd -p
ASMCMD [+]>; du

Used_MB Mirror_used_MB
12011 12011

ASMCMD [+] >;

or run
lsdg command

State Type Rebal Unbal Sector Block AU Total_MB Free_MB Req_mir_free_MB Usable_file_MB Offline_disks Name
MOUNTED EXTERN N N 1024 4096 1048576 40960 37628 0 37628 0 ORADATA/
MOUNTED EXTERN N N 1024 4096 1048576 32768 32675 0 32675 0 ORADATA1/

Monday, June 14, 2010

Rename/Relocate SYSAUX tablespace

METHOD 1 (move the datafile(s) with the database open
============================================
1) ALTER TABLESPACE sysaux OFFLINE NORMAL;

2) Rename the datafile(s) at the OS level

3) ALTER TABLESPACE sysaux RENAME DATAFILE "\SYSAUX01.DBF";

4) ALTER TABLESPACE sysaux ONLINE;

NOTE : This method may not work at all times as there are processes that need to use the SYSAUX tablespace
and if they are using it ... the tablespace will not alter offline ... in which case you will need to use METHOD 1



METHOD 2 (move the datafiles in mount mode)
====================================

1) SHUTDOWN IMMEDIATE

2) Relocate the SYSAUX datafile(s) to the desired location

3) STARTUP MOUNT

4) ALTER DATABASE RENAME FILE
'/FULL_PATH_OF_OLD_LOCATION/AND_DATAFILE_NAME.DBF'
TO
'/FULL_PATH_OF_NEW_LOCATION/AND_DATAFILE_NAME.DBF';

5) ALTER DATABASE OPEN;



METHOD 3 (move the datafiles by recreating the controlfiles)
===============================================

1) ALTER DATABASE BACKUP CONTROLFILE TO TRACE;

2) Locate the trace file created in step 1 ... it will be in the USER_DUMP_DEST

3) Edit the create controlfile statement in the created trace ... change the location of the SYSAUX datafile(s) to their desired location

4) SHUTDOWN the database

5) Relocate the SYSAUX datafile(s) to the desired location

6) Run the script that was created in step 1 and modified in Step 3

Friday, June 11, 2010

Tablespace export/import

Following command is not Transportable Tablespace but datapump export/import for tablespace.
Below steps can be performed, if it is required to drop and recreate a tablespace on the same database.

To import on different instance, you'll require to create the tablespace before importing

Tablespace EXPORT/IMPORT:

1. Datapump Export Tablespace
 
expdp system/**** full=n tablespaces=SCOTT_DATA directory=dump 
dumpfile=scott_data.dmp logfile=scott.log 
 
2. Drop tablespace

DROP TABLESPACE SCOTT_DATA INCLUDING contents 
And datafiles cascade constraints;

3. Create tablespace 

4. Datapump Import Tablespace

impdp system/**** directory=dump dumpfile=scott_data.dmp full=y 
logfile=scott_imp.log
 
 

Thursday, June 10, 2010

RMAN 11G : Data Recovery Advisor - RMAN command line example

The Data Recovery Advisor is a tool that helps you to diagnose and repair data failures and corruptions. The Data Recovery Advisor analyzes failures based on symptoms and intelligently determines optimal repair strategies. The tool can also automatically repair diagnosed failures.

The Data Recovery Advisor is available from Enterprise Manager (EM) Database Control and Grid Control. You can also use it via the RMAN command-line.

In this example you will see examples of via the RMAN command line utilising the DRA commands:

Three DRA commands are available within RMAN:

List Failure - lists the results of previously executed failure assessments. Revalidates existing failures and closes them, if possible.

Advise Failure - presents manual and automatic repair options

Repair Failure - automatically fix failures by running optimal repair option, suggested by ADVISE FAILURE. Revalidates existing failures when completed.

Below is a demonstration of DRA.

1. Take Full RMAN backup;

2. RMAN> validate check logical datafile 2;
Show that the datafile is free from corruption.

RMAN> validate check logical datafile 2;

Starting validate at 2008/11/10 09:52:36
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=132 device type=DISK
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00002 name=/oradata/V11/sysaux01.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:25
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
2 OK 0 28279 104896 2885460
File Name: /oradata/V11/sysaux01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 21440
Index 0 24664
Other 0 30513

Finished validate at 2008/11/10 09:53:02

3. Corrupt several Blocks within the sysaux tablespace

SQL> @corrupt_blocks.sql

4. RMAN> validate check logical datafile 2;

This should show the corruption and indicate the # of blocks corrupted.

RMAN> validate check logical datafile 2;

Starting validate at 2008/11/10 09:57:05
using channel ORA_DISK_1
channel ORA_DISK_1: starting validation of datafile
channel ORA_DISK_1: specifying datafile(s) for validation
input datafile file number=00002 name=/oradata/V11/sysaux01.dbf
channel ORA_DISK_1: validation complete, elapsed time: 00:00:07
List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
2 FAILED 0 28273 104896 2894632
File Name: /oradata/V11/sysaux01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 21440
Index 0 24663
Other 10 30520


validate found one or more corrupt blocks
See trace file /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/trace/V11_ora_22522.trc for details
Finished validate at 2008/11/10 09:57:12


Review: /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/trace/V11_ora_22522.trc
Open the trace file to show the errors that have been picked up.


Corrupt block relative dba: 0x00800024 (file 2, block 36)
Completely zero block found during validation
Reread of blocknum=36, file=/oradata/V11/sysaux01.dbf. found same corrupt data
Reread of blocknum=36, file=/oradata/V11/sysaux01.dbf. found same corrupt data
Reread of blocknum=36, file=/oradata/V11/sysaux01.dbf. found same corrupt data
Reread of blocknum=36, file=/oradata/V11/sysaux01.dbf. found same corrupt data
Reread of blocknum=36, file=/oradata/V11/sysaux01.dbf. found same corrupt data
Hex dump of (file 2, block 37)
We can now issue list failure & list failure detail to get more about the issue.

5. RMAN> list failure;
RMAN> list failure ### detail; ( where ### equlas the failure number)


RMAN> list failure;

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

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
351261 HIGH OPEN 2008/11/10 09:56:33 Datafile 2: '/oradata/V11/sysa
ux01.dbf' contains one or more corrupt blocks

RMAN> list failure 351261 detail;

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

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
351261 HIGH OPEN 2008/11/10 09:56:33 Datafile 2: '/oradata/V11/sysa
ux01.dbf' contains one or more corrupt blocks
Impact: Some objects in tablespace might be unavailable
List of child failures for parent failure ID 351261
Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
List of Database Failures
=========================

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
351261 HIGH OPEN 2008/11/10 09:56:33 Datafile 2: '/oradata/V11/sysa
ux01.dbf' contains one or more corrupt blocks
Impact: Some objects in tablespace might be unavailable
List of child failures for parent failure ID 351261
Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
352028 HIGH OPEN 2008/11/10 09:56:35 Block 37 in datafile 2: '/or
adata/V11/sysaux01.dbf' is media corrupt

At this point you are able to issue the advise keyword which will prompt DBA will be advise on how to solve the current scenario.

6. RMAN> Advise Failure;

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

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
351261 HIGH OPEN 2008/11/10 09:56:33 Datafile 2: '/oradata/V11/sysa
ux01.dbf' contains one or more corrupt blocks
Impact: Some objects in tablespace might be unavailable
List of child failures for parent failure ID 351261
Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------------- -------
352028 HIGH OPEN 2008/11/10 09:56:35 Block 37 in datafile 2: '/or
adata/V11/sysaux01.dbf' is media corrupt
..
..
..
Impact: Object I_SMB$CONFIG_PKEY owned by SYS might be unavailable
351974 HIGH OPEN 2008/11/10 09:56:33 Block 28 in datafile 2: '/or
adata/V11/sysaux01.dbf' is media corrupt
Impact: Object I_SMB$CONFIG_PKEY owned by SYS might be unavailable

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 a standby database is available, then consider a Data Guard switchover or failover

Automated Repair Options
========================
Option Repair Description
------ ------------------
1 Recover multiple corrupt blocks in datafile 2

Strategy: The repair includes complete media recovery with no data loss

Repair script: /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/hm/reco_189110358.hm

RMAN>

Review File: : /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/hm/reco_189110358.hm

[oracle@aulnx7 hm]$ vi reco_189110358.hm

# block media recovery for multiple blocks
recover datafile 2 block 28 to 37;


As can be seen above one option is to perform rman block recovery. The next step for the DBA is to proceed with the repair preview.


7. RMAN> repair failure preview;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/hm/reco_42
19629556.hm

contents of repair script:
# block media recovery for multiple blocks
recover datafile 2 block 28 to 37;
Then you are ready to perform the fix.

8. RMAN> repair failure;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/product/11.1.0/db_1/diag/rdbms/v11/V11/hm/reco_42
19629556.hm

contents of repair script:
# block media recovery for multiple blocks
recover datafile 2 block 28 to 37;

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

Starting recover at 2008/11/10 10:18:48
using channel ORA_DISK_1

channel ORA_DISK_1: restoring block(s)
channel ORA_DISK_1: specifying block(s) to restore from backup set
restoring blocks of datafile 00002
channel ORA_DISK_1: reading from backup piece /recovery_area/V11/backupset/2008_
11_10/o1_mf_nnndf_TAG20081110T093808_4kgslm1w_.bkp
channel ORA_DISK_1: piece handle=/recovery_area/V11/backupset/2008_11_10/o1_mf_n
nndf_TAG20081110T093808_4kgslm1w_.bkp tag=TAG20081110T093808
channel ORA_DISK_1: restored block(s) from backup piece 1
channel ORA_DISK_1: block restore complete, elapsed time: 00:00:35

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

Finished recover at 2008/11/10 10:19:27
repair failure complete

RMAN>
At this point the the blocks have been fully recovered.

Repair corrupt oracle blocks in 11g

Oracle has introduced a new feature in 11g which can be used to get assistance in case of loss or corruption of datafiles, redo log files or controlfiles. This tool is called data recovery advisor and is accessible from the command line as well as from the GUI.

The command line interface is implemented as new commands for RMAN, the graphical interface is integrated into the Enterprise Manager. In the following little demo I want to show how we can deal with corrupted blocks in11g.

I proactively check for block corruption in the database on a regular basis and strongly recommend this to my customers.

By default RMAN checks for physically corrupted blocks automatically with every backup it creates, no matter if it is a backup set or an image copy.

Logical corruption is only checked with the additional syntax CHECK LOGICAL. The VALIDATE keyword causes that no physical backup is created, but RMAN only reads all blocks through the input puffers but does not write them to the output buffer into a backup set.
RMAN> backup validate check logical database;

Starting backup at 03-FEB-08
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=131 device type=DISK
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/u01/app/oracle/oradata/orcl/system01.dbf
input datafile file number=00002 name=/u01/app/oracle/oradata/orcl/sysaux01.dbf
input datafile file number=00003 name=/u01/app/oracle/oradata/orcl/undotbs01.dbf
input datafile file number=00005 name=/u01/app/oracle/oradata/orcl/ORCL/datafile/o1_mf_encrypt__3sd9vvs5_.dbf
input datafile file number=00004 name=/u01/app/oracle/oradata/orcl/users01.dbf
channel ORA_DISK_1: backup set complete, elapsed time: 00:01:26
List of Datafiles
. . .

=================



In 11g RMAN directly informs us about corrupted blocks it has found in the output of backup command and creates a trace file in the Automatic Diagnostic Repository (ADR) :

. . .
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
1 OK 0 11128 76800 622989
File Name: /u01/app/oracle/oradata/orcl/system01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 54455
Index 0 9080
Other 0 2137

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
2 OK 0 20756 59896 622994
File Name: /u01/app/oracle/oradata/orcl/sysaux01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 10864
Index 0 9779
Other 0 18497

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
3 OK 0 0 40960 622994
File Name: /u01/app/oracle/oradata/orcl/undotbs01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 0
Index 0 0
Other 0 40960

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
4 OK 0 632 640 11608
File Name: /u01/app/oracle/oradata/orcl/users01.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 0
Index 0 0
Other 0 8

File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
5 FAILED 0 523 1280 602803
File Name: /u01/app/oracle/oradata/orcl/ORCL/datafile/o1_mf_encrypt__3sd9vvs5_.dbf
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 708
Index 0 1
Other 4 48

validate found one or more corrupt blocks
See trace file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_10321.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
===============================
File Type Status Blocks Failing Blocks Examined
------------ ------ -------------- -----
SPFILE OK 0 2
Control File OK 0 594
Finished backup at 03-FEB-08


This already is a great improvement because in pre 11g Releases we would have had to find out yourself if there were corrupted blocks found by selecting the information in the dynamic view v$database_block_corruption.

A check like this which has returned corrupted blocks in 11g immediately creates a failure in the database. A failure could also be produces by an inaccessible datafile or a lost control- or redo logfile.

There are multiple checkers available in 11g which are automatically run by the server as soon as a critical error is raised. These include health checks like database structure checks, integrity checks for the data dictionary as well as block corruption check.

These checks can also be started manually by the DBA by using the new package DBMS_HM .

Also the DBA can run these checks from the ADVISER CENTRAL in OEM. There is a new checkers-pane next to the advisers.

Once a failure has been detected it is possible to ask RMAN for possible repair options.

RMAN has the following set of new commands to deal with failures:



- LIST FAILURE

- ADVISE FAILURE

- CHANGE FAILURE

- REPAIR FAILURE



Let’s first have a look at the LIST FAILURE command:

RMAN> list failure;

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

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------- -------
21821 HIGH OPEN 03-FEB-08 Datafile 5: '/u01/app/oracle/oradata/orcl/ORCL/datafile/o1_mf_encrypt__3sd9vvs5_.dbf' contains one or more corrupt blocks

Now the question for the DBA is



Á “What is the fastest way
to get the problem solved?”

And it might not always be easy to give the correct answer:

It could be that it is faster to restore the file(s) and recover it (them). This would be the case if very many blocks need media recovery.

Or it could be faster to get the list of corrupted blocks and use block media recovery with RMAN to resolve the situation.

As of 11g RMAN can also choose to use block copies from the flashback logs instead of a backup for block media recovery.

The ADVISE FAILURE command comes in very handy here:
RMAN> advise failure;

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

Failure ID Priority Status Time Detected Summary
---------- -------- --------- ------------- -------
21821 HIGH OPEN 03-FEB-08 Datafile 5: '/u01/app/oracle/oradata/orcl/ORCL/datafile/o1_mf_encrypt__3sd9vvs5_.dbf' contains one or more corrupt blocks

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
=======================
no manual actions available

Automated Repair Options
========================
Option Repair Description
------ ------------------
1 Recover multiple corrupt blocks in datafile 5
Strategy: The repair includes complete media recovery with no data loss
Repair script: /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_2984746849.hm


This command gives us comprehensive information about the best possible option for a repair and it also automatically generates a repair script which contains the commands that should be run for the repair action. This script can either be run manually or with a repair command. RMAN> host;


[oracle@rhas4 ~]$ cat /u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_2984746849.hm

# block media recovery for multiple blocks
recover datafile 5 block 43 to 46;

RMAN> repair failure;

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

contents of repair script:
# block media recovery for multiple blocks
recover datafile 5 block 43 to 46;

At this point RMAN asks us to confirm the repair actoin.
It is also possible to run the REPAIR FAILURE command with NOPROMPT.

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

Starting recover at 03-FEB-08
using channel ORA_DISK_1

channel ORA_DISK_1: restoring block(s) from datafile copy /u01/app/oracle/flash_recover/ORCL/datafile/o1_mf_encrypt__3t1w5bkp_.dbf

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

Finished recover at 03-FEB-08
repair failure complete



The REPAIR FAILURE command can be run with PREVIEW option which does not execute the repair script but shows it.

There are a number of dynamic views for monitoring failures and the repair actions:

SYSTEM @ orcl SQL> SELECT table_name FROM dict WHERE lower(table_name) like 'v$ir%';

TABLE_NAME
------------------------------
V$IR_FAILURE
V$IR_FAILURE_SET
V$IR_MANUAL_CHECKLIST
V$IR_REPAIR

SYSTEM @ orcl SQL> desc V$IR_FAILURE
Name Null? Type
-------------- -------- -------
FAILURE_ID NUMBER
PARENT_ID NUMBER
CHILD_COUNT NUMBER
CLASS_NAME VARCHAR2(32)
TIME_DETECTED DATE
MODIFIED DATE
DESCRIPTION VARCHAR2(1024)
IMPACTS VARCHAR2(1024)
PRIORITY VARCHAR2(8)
STATUS VARCHAR2(12)

SYSTEM @ orcl SQL> desc V$IR_FAILURE_SET
Name Null? Type
----------------- -------- -------------
ADVISE_ID NUMBER
FAILURE_ID NUMBER
MANUAL_REPAIRS_ONLY VARCHAR2(3)

SYSTEM @ orcl SQL> desc V$IR_MANUAL_CHECKLIST
Name Null? Type
---------------- -------- -------------
ADVISE_ID NUMBER
RANK NUMBER
REQUIRED VARCHAR2(3)
MESSAGE VARCHAR2(1024)


SYSTEM @ orcl SQL> desc V$IR_REPAIR
Name Null? Type
--------------- -------- ---------------
REPAIR_ID NUMBER
ADVISE_ID NUMBER
SUMMARY VARCHAR2(32)
RANK NUMBER
TIME_DETECTED DATE
EXECUTED DATE
ESTIMATED_DATA_LOSS VARCHAR2(20)
DETAILED_DESCRIPTION VARCHAR2(1024)
REPAIR_SCRIPT VARCHAR2(512)
ESTIMATED_REPAIR_TIME NUMBER
ACTUAL_REPAIR_TIME NUMBER
STATUS VARCHAR2(7)


Let’s take a look at a failure from here:

SYSTEM @ orcl SQL> SELECT repair_id, detailed_description, repair_script FROM V$IR_REPAIR;

REPAIR_ID DETAILED_DESCRIPTION REPAIR_SCRIPT
---------- ----------------------------------- --------------------------------- 21882 The repair includes complete media
/u01/app/oracle/diag/rdbms/orcl/orcl/hm/reco_2984746849.hm

Wednesday, June 09, 2010

Temporary tablespace

The creation and use of temporary tablespaces has just taken another leap in performance and manageability, which should make us all re-think how we have created and assigned our users to temporary tablespaces.

The TEMPORARY Tablespace

When a users executes a SQL statement that requires sorting or does some sort of database maintenance that requires the creation of temporary segments, it is the temporary tablespace that assists in that sorting or holding of those temporary segments. If we did not have an area designated as "temporary", these operations and segments would have to cohabitate with permanent segments. We realized quite a few releases back in Oracle that this was not a good idea and that we need to separate the temporary segments from the permanent segments. If we did not allow this, we were imposing undo harm within our database and to the performance of other SQL statements accessing and manipulating the segments in those tablespaces.

The Evolution of the TEMPORARY Tablespace

1. Oracle allowed DBAs to create a normal tablespace and assign this to users to use as a temporary tablespace through the CREATE USER or ALTER USER commands. These tablespaces could hold temporary segments and permanent segments. Oracle's position at that time was to advise everyone not to place permanent segments into these tablespaces that were also being used as TEMPORARY tablespaces for users.
2. Oracle then implemented the notion of a true TEMPORARY tablespace. These TEMPORARY tablespaces were to be assigned to users at creation time and could only hold temporary segments. This was a great step in the right direction because now we could not place permanent objects into them and no longer could users be assigned permanent tablespaces as their temporary tablespaces.
3. Oracle then went one step further and allowed us to create a DEFAULT TEMPORARY tablespace for the entire database. The benefit this gives is, if we forget to specify a temporary tablespace for the user, they will inherit the DEFAULT TEMPORARY tablespace as theirs.
4. Now in Oracle 10g, Oracle lets us group temporary tablespaces together to gain a bit more flexibility that allows us to create multiple temporary tablespaces and to create tablespace groups and assign these tablespace groups to users.

Tablespace Groups

Oracle now has the concept of grouping multiple tablespaces together in what they call a tablespace group. This allows you to create multiple temporary tablespaces, assign these temporary tablespaces to a tablespace group, and then use the tablespace group as the default temporary tablespace for the database or user. The benefit this has is that a single SQL statement or set of SQL statements may use more than the one temporary tablespace you have created in the past and now span multiple tablespaces. This has the following benefits if you create your temporary tablespaces and tablespace groups properly.

1. You can tailor user load to individual temporary tablespaces.

2. You can allow large sort operations to span and consume multiple temporary tablespaces if needed.

3. Finer granularity so you can distribute operations across temporary tablespaces.

4. Reduced contention when multiple temporary tablespaces are defined.

The Life of a Tablespace Group

You can implicitly create a tablespace group during the creation of a temporary tablespace with the CREATE TEMPORARY TABLESPACE command and by specifying the TABLESPACE GROUP clause. There is no CREATE TABLESPACE GROUP statement. Therefore, during the creation of a temporary tablespace called GTEMP01 we can add this tablespace to a tablespace group called GTEMP by using the following statement.


CREATE TEMPORARY TABLESPACE GTEMP01
TEMPFILE 'C:\ORACLE\PRODUCT\10.1.0\ORADATA\DATEN\GTEMP01.DBF' SIZE 100M
TABLESPACE GROUP GTEMP;


The tablespace group name must be an existing tablespace group name or one that does not exists. In addition, it must not be the name of an existing tablespace or you will get an error such as the following that notifies you that the tablespace already exists.


CREATE TEMPORARY TABLESPACE GTEMP
TEMPFILE 'C:\ORACLE\PRODUCT\10.1.0\ORADATA\DATEN\GTEMP.DBF' SIZE 100M
SQL> /
CREATE TEMPORARY TABLESPACE GTEMP
*
ERROR at line 1:
ORA-01543: tablespace 'GTEMP' already exists


We can also switch a tablespace's group, add a tablespace to a group or create a new tablespace group by using the following statement.


ALTER TABLESPACE GTEMP02 TABLESPACE GROUP GTEMP;
ALTER TABLESPACE GTEMP03 TABLESPACE GROUP GTEMP;


If you wanted to remove a tablespace from a tablespace group and not assign it to a new tablespace group, you would use the following statement where the TABLESPACE GROUP clause is used but an empty string is used for the group.


ALTER TABLESPACE GTEMP03 TABLESPACE GROUP '';


You cannot get rid of a tablespace group explicitly. In order for a tablespace group to be implicitly removed from the database, you need to alter those tablespaces to either use another tablespace group or alter them not to use any tablespace groups by assigning them to an explicit tablespace.

DBA_TABLESPACE_GROUPS View

You can always take a look at what tablespace groups you have defined by looking at the DBA_TABLESPACE_GROUPS view. Issue the following SQL and you can see what we have already defined for our running example.


SQL> SELECT group_name, tablespace_name
FROM dba_tablespace_groups;

GROUP_NAME TABLESPACE_NAME
------------------------------ -------------------
GTEMP GTEMP01
GTEMP GTEMP02


Setting the Default Temporary Tablespace

Now that we have defined multiple tablespaces to be part of a tablespace group called GTEMP, we can now use this tablespace group just as any other tablespace. One use of a tablespace group can be for the default temporary tablespace. If you wish to assign this new tablespace group as the default temporary tablespace, just issue the following SQL. Now any user who you have not given a temporary tablespace at user creation time will be assigned this new tablespace group as their temporary tablespace.


SQL> ALTER DATABASE DEFAULT TEMPORARY TABLESPACE GTEMP;
Database altered.


The temporary tablespace within large organizations that require many sort operations typically would experience high levels of contention. It was then left up to the DBA to segregate sort operations by users and create islands of temporary tablespaces so that those operations would not contend for similar resources that are associated with a single temporary tablespace. The problem with this is that the very large operations would typically need independent large temporary tablespaces. This would lead to wasted resources. With the addition of tablespace groups, Oracle now allows us to group multiple temporary tablespaces together so that we have one more choice in the usage patterns of these temporary tablespaces. We now need to ask ourselves if an operation truly needs its own individual temporary tablespace or the operation can span multiple temporary tablespaces and work without contention with the other operations that are occurring. If so, we can consolidate, reduce disk consumption, and possibly contention.

Wednesday, June 02, 2010

Indexing on Partitoned Tables:

Local Indexes:
A local index on a partition table will have the same partition schema as the table. Each partition in a local index will have similar entries like the corresponding data in the table partition.
eg.:
Creating a table first:
SQL> CREATE TABLE DATA_LOAD
( DATA_id NUMBER(6),
source_id NUMBER,
load_date DATE,
data_size NUMBER,
state VARCHAR2(20))
PARTITION BY RANGE (load_date)
SUBPARTITION BY LIST (state)
SUBPARTITION TEMPLATE (
SUBPARTITION NORTH_01 VALUES ('DELHI', 'JAMMU KASHMIR', 'PUNJAB', 'HARYANA') TABLESPACE DATA_01,
SUBPARTITION WEST_01 VALUES ('RAJASTHAN', 'GUJRAT', 'MAHARASTRA') TABLESPACE DATA_02,
SUBPARTITION SOUTH_01 VALUES ('TAMIL NADU', 'KERELA', 'KARNATAKA') TABLESPACE DATA_03,
SUBPARTITION EAST_01 VALUES ('ASSAM', 'WEST BENGAL', 'NAGALAND') TABLESPACE DATA_04,
SUBPARTITION NO_REGION VALUES (NULL) TABLESPACE USERS,
SUBPARTITION OTHER VALUES (DEFAULT) TABLESPACE USERS
)
( PARTITION data_2006 VALUES LESS THAN (TO_DATE('01-JAN-2007','DD-MON-YYYY')) ,
PARTITION data_2007 VALUES LESS THAN (TO_DATE('01-JAN-2008','DD-MON-YYYY')) ,
PARTITION data_2008 VALUES LESS THAN (TO_DATE('01-JAN-2009','DD-MON-YYYY')) ,
PARTITION data_2009 VALUES LESS THAN (TO_DATE('01-JAN-2010','DD-MON-YYYY'))
);
Table created.

SQL> create index DATA_LOAD_LOCAL1 on DATA_LOAD (load_date) LOCAL;
Index created.

SQL> insert into DATA_LOAD values (1,1,sysdate-1200,10,'DELHI');
1 row created.
SQL> insert into DATA_LOAD values (2,2,sysdate-1100,20,'RAJASTHAN');
1 row created.
SQL> insert into DATA_LOAD values (3,3,sysdate-1000,30,'KERELA');
1 row created.
SQL> insert into DATA_LOAD values (4,4,sysdate-1300,40,'ASSAM');
1 row created.
SQL> insert into DATA_LOAD values (5,5,sysdate-900,50,'NAGALAND');
1 row created.
SQL> insert into DATA_LOAD values (6,6,sysdate-300,60,'PUNJAB');
1 row created.
SQL> insert into DATA_LOAD values (7,7,sysdate,70,'HARYANA');
1 row created.
SQL> commit;
Commit complete.
SQL> analyze table DATA_LOAD compute statistics;
Table analyzed.

SQL> analyze index DATA_LOAD_LOCAL1 compute statistics ;
Index analyzed.

SQL> select INDEX_NAME,COMPOSITE,PARTITION_NAME,SUBPARTITION_COUNT,NUM_ROWS from user_ind_partitions where index_name='DATA_LOAD_LOCAL1';

INDEX_NAME COM PARTITION_NAME SUBPARTITION_COUNT NUM_ROWS
------------------------------ --- --------------- ------------------ ----------
DATA_LOAD_LOCAL1 YES DATA_2006 6 5
DATA_LOAD_LOCAL1 YES DATA_2007 6 0
DATA_LOAD_LOCAL1 YES DATA_2008 6 1
DATA_LOAD_LOCAL1 YES DATA_2009 6 1

SO we can see the index partitions were created the same way as the table partition, same subpartitions also.

Prefixed LOCAL Index:
A prefixed local index is an index in which the left most column used in the index definition is the same as the table partitioning key. The above example is a local prefixed index.

LOCAL NON-Prefixed Index:
As the name suggests its opposite to the prefixed local index. In this index the left most key is not the partition key column.

SQL> create index DATA_LOAD_LOCAL2 on DATA_LOAD (source_id) LOCAL;
Index created.

SQL> analyze index DATA_LOAD_LOCAL2 compute statistics;
Index analyzed.

SQL> select INDEX_NAME,COMPOSITE,PARTITION_NAME,SUBPARTITION_COUNT,NUM_ROWS from user_ind_partitions where index_name='DATA_LOAD_LOCAL2';
INDEX_NAME COM PARTITION_NAME SUBPARTITION_COUNT NUM_ROWS
------------------------------ --- --------------- ------------------ ----------
DATA_LOAD_LOCAL2 YES DATA_2006 6 5
DATA_LOAD_LOCAL2 YES DATA_2007 6 0
DATA_LOAD_LOCAL2 YES DATA_2008 6 1
DATA_LOAD_LOCAL2 YES DATA_2009 6 1

We can see that even in the NON-Prefixed index has the same partitioning scheme as the partition table.
Each partition of the NON-Prefixed Local index will contain the whole range of possible partition key values, so this might we inefficient at time if we are not using parallel option while selecting. As here the partitions for the index are created like the that of the table using the partition key, but the index key is something else.

GLOBAL INDEXES:
Basically Global Indexes are indexes on which we can define the parition scheme, we define how many partitions we want of the index using which ever table column we would like to use. A global index can be created with the table partition key as the leftmost column or with any other column and in the create statement we can define the partition values for the key.

SQL> CREATE INDEX DATA_LOAD_GLOBAL ON DATA_LOAD (load_date,data_size)
GLOBAL PARTITION BY RANGE (load_date)
(PARTITION p1 VALUES LESS THAN (TO_DATE('01-JAN-2008','DD-MON-YYYY')),
PARTITION p2 VALUES LESS THAN (MAXVALUE)
);
Index created.

SQL> select INDEX_NAME,COMPOSITE,PARTITION_NAME,SUBPARTITION_COUNT,NUM_ROWS from user_ind_partitions where index_name='DATA_LOAD_GLOBAL';
INDEX_NAME COM PARTITION_NAME SUBPARTITION_COUNT NUM_ROWS
------------------------------ --- --------------- ------------------ ----------
DATA_LOAD_GLOBAL NO P1 0 5
DATA_LOAD_GLOBAL NO P2 0 2

We can see that the partition definition of the index is different from the table.

Actually the Global indexes are more useful when using other column for indexing the table rather than the partition key column of the table. As in our case the partitions are done on the basic on load_date, what if we use the column data_size more often to query than the load_date. In this case if we create a local index on data_size (non-prefixed local index) than its partition defination doesn't help the query as it is partitions are based on the table partitioning.
In our case:
Every partition based on load_date can have all the values of data_size. Say the data size column has values from 1 to 100.
Then DATA_2006 can have values 1 to 100, DATA_2007 can have values 1 to 100 and so on. So this does not help quering this index so much.

Instead we can create a global index on this column and define the correct partition scheme for the index using data_size as the partition key for the index.
SQL> CREATE INDEX DATA_LOAD_GLOBAL2 on DATA_LOAD (data_size)
GLOBAL PARTITION BY RANGE (data_size)
(PARTITION p1 VALUES LESS THAN (30),
PARTITION p2 VALUES LESS THAN (50),
PARTITION p3 VALUES LESS THAN (80),
PARTITION p4 VALUES LESS THAN (MAXVALUE)
);
Index created.

SQL> select INDEX_NAME,COMPOSITE,PARTITION_NAME,SUBPARTITION_COUNT,NUM_ROWS from user_ind_partitions where index_name='DATA_LOAD_GLOBAL2';
INDEX_NAME COM PARTITION_NAME SUBPARTITION_COUNT NUM_ROWS
------------------------------ --- --------------- ------------------ ----------
DATA_LOAD_GLOBAL2 NO P2 0 2
DATA_LOAD_GLOBAL2 NO P3 0 3
DATA_LOAD_GLOBAL2 NO P4 0 0
DATA_LOAD_GLOBAL2 NO P1 0 2

Note: Global indexed should have same left most index key and the index partition key, they cannot be different.
Else we will receive the below error. They are different from the non-prefixed local partition in this context.

SQL> CREATE INDEX DATA_LOAD_GLOBAL2 on DATA_LOAD (data_size)
GLOBAL PARTITION BY RANGE (source_id)
(PARTITION p1 VALUES LESS THAN (30),
PARTITION p2 VALUES LESS THAN (50),
PARTITION p3 VALUES LESS THAN (80),
PARTITION p4 VALUES LESS THAN (MAXVALUE)
); 2 3 4 5 6 7
GLOBAL PARTITION BY RANGE (source_id)
*
ERROR at line 2:
ORA-14038: GLOBAL partitioned index must be prefixed

Similarly we can have hash and list partition Global indexes:

SQL> CREATE INDEX DATA_LOAD_GLOBAL3 on DATA_LOAD (data_size) GLOBAL PARTITION BY HASH (data_size) PARTITIONS 4;
CREATE INDEX DATA_LOAD_GLOBAL3 on DATA_LOAD (data_size) GLOBAL PARTITION BY HASH (data_size) PARTITIONS 4
*
ERROR at line 1:
ORA-01408: such column list already indexed
We received the above error as we already create an index with the above column.

SQL> CREATE INDEX DATA_LOAD_GLOBAL3 on DATA_LOAD (data_size,source_id) GLOBAL PARTITION BY HASH (data_size) PARTITIONS 4;
Index created.

And so on....

Problem : Ora-14074 When Trying To Add Partition

Symptoms
Adding a partition to a table generates an ORA-14074 error.

.

Cause
You will need to split the partition when adding a partition to the beginning or middle of the
table.



Error: ORA 14074
Text: partition bound must collate higher than that of the last partition
Cause: Partition bound specified in ALTER TABLE ADD PARTITION statement did
not collate higher than that of the table's last partition, which is illegal.


Action: Ensure that the partition bound of the partition to be added collates
higher than that of the table's last partition.

.


Solution
In this example PARTITION SALES_Q1_1998 is the first partition in the table.
Use the alter table split partition command to add the new partitions.
To split this partition and add a new partition use this command.


ALTER TABLE range_sales SPLIT PARTITION SALES_Q1_1998
AT (TO_DATE('01-JAN-1998','DD-MON-YYYY'))
INTO (PARTITION SALES_Q4_1997, PARTITION SALES_Q1_1998);


Here's an example of how to get around this errror.


drop table range_sales;

CREATE TABLE range_sales
( prod_id NUMBER(6)
, cust_id NUMBER
, time_id DATE
, channel_id CHAR(1)
, promo_id NUMBER(6)
, quantity_sold NUMBER(3)
, amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
(PARTITION SALES_Q1_1998 VALUES LESS THAN (TO_DATE('01-APR-1998','DD-MON-YYYY')),
PARTITION SALES_Q2_1998 VALUES LESS THAN (TO_DATE('01-JUL-1998','DD-MON-YYYY')),
PARTITION SALES_Q3_1998 VALUES LESS THAN (TO_DATE('01-OCT-1998','DD-MON-YYYY')),
PARTITION SALES_Q4_1998 VALUES LESS THAN (TO_DATE('01-JAN-1999','DD-MON-YYYY')),
PARTITION SALES_Q1_1999 VALUES LESS THAN (TO_DATE('01-APR-1999','DD-MON-YYYY')),
PARTITION SALES_Q2_1999 VALUES LESS THAN (TO_DATE('01-JUL-1999','DD-MON-YYYY')),
PARTITION SALES_Q3_1999 VALUES LESS THAN (TO_DATE('01-OCT-1999','DD-MON-YYYY')),
PARTITION SALES_Q4_1999 VALUES LESS THAN (TO_DATE('01-JAN-2000','DD-MON-YYYY')),
PARTITION SALES_Q1_2000 VALUES LESS THAN (TO_DATE('01-APR-2000','DD-MON-YYYY')),
PARTITION SALES_Q2_2000 VALUES LESS THAN (TO_DATE('01-JUL-2000','DD-MON-YYYY')),
PARTITION SALES_Q3_2000 VALUES LESS THAN (TO_DATE('01-OCT-2000','DD-MON-YYYY')),
PARTITION SALES_Q4_2000 VALUES LESS THAN (MAXVALUE));

-- error reported here
alter table range_sales add partition SALES_Q4_1997 VALUES LESS THAN
(TO_DATE('01-JAN-1998','DD-MON-YYYY'));


-- Split the partition to avoid the error
ALTER TABLE range_sales SPLIT PARTITION SALES_Q1_1998
AT (TO_DATE('01-JAN-1998','DD-MON-YYYY'))
INTO (PARTITION SALES_Q4_1997, PARTITION SALES_Q1_1998);



select TABLE_NAME, PARTITION_NAME, HIGH_VALUE from USER_TAB_PARTITIONS
where table_name ='RANGE_SALES';



insert into RANGE_SALES values
(1,1,TO_DATE('12-DEC-1996','DD-MON-YYYY'), 'a',1,1,1);

select * from RANGE_SALES;

select * from RANGE_SALES partition (SALES_Q3_2000);

select * from RANGE_SALES partition (SALES_Q4_1997);