Oracle DBA Code Examples
Oracle DBA Code Examples
Prerequisites
The document assumes that the reader has already the knowledge of Oracle database
administration.
Usage Terms
• Anyone is authorized to copy this document to any means of storage and present it in any
format to any individual or organization for non-commercial purpose free.
• No individual or organization may use this document for commercial purpose without a
written permission from the editor.
• This document is for informational purposes only, and may contain typographical errors and
technical inaccuracies.
• There is no warranty of any type for the code or information presented in this
document. The editor is not responsible for any loses or damage resulted from
using the information or executing the code in this document.
• If any one wishes to correct a statement or a typing error or add a new piece of information,
please send the request to info@ahmedbaraka.com
Using Windows___________________________________________________170
Recovering from Lost Control File by Re-Creating the Control File ___________218
Obtaining Information about and related to RMAN using Dictionary Views _____224
Roles __________________________________________________________276
Defining Access Paths and Joins for the Query Optimizer __________________326
Enabling and Disabling Statistic Gathering for End to End Tracing ___________338
Configuring the RMAN Control File and SPFILE Autobackup Feature __________416
Quick-Start Node and Database Instance Addition and Deletion Procedures ___437
Adding an Oracle Clusterware Home to a New Node __________________________ 437
Adding an Oracle Home with RAC to a New Node ____________________________ 437
Deleting an Oracle Home with RAC from an Existing Node _____________________ 437
Deleting an Oracle Clusterware Home from an Existing Node ___________________ 437
Detailed Node and Database Instance Addition and Deletion Procedures ______437
Step 2: Extending Oracle Software to New Nodes at the Oracle Clusterware ___437
Adding Nodes that Already Have Clusterware and Oracle Software to a Cluster 438
Installation Environment
• Emulation software: VMWare Server 2 on for Windows
• OS: Oracle Linux Enterprise 4.5 for x86: kernel 2.6.9
Required Software
• Oracle Database 10g Release 2 for Linux x86 32-bit
Used Hardware
• In the VMWare: create one virtual machine (oradb1) with the following specs:
o 2 GB RAM
o an ethernet card
o one local hardisk with 20 GB
Installation Plan
1. Preinstallation tasks:
o Hardware requirements
o Software requirements
o Environment configuration
2. Oracle Database 10g Software Installation
3. Apply Patchset 3 (10.2.0.4) for Clusterware and Database Software
4. Create Database
5. Configure Listeners
6. Postinstallation tasks
1. Preinstallation tasks
• Install Oracle Enterprise Linux in the first local hardisk. Install nothing in the remaining
disks.
Note: for a production system, consider becoming an Oracle Unbreakable Linux customer
and register your server on the Unbreakable Linux Network.
o Give the ethernet card IP 192.168.4.21 and the hostname oradb1.mydomain.com.
Define a gateway. If it does not exist, make it same as the host IP address.
o Insall the following packages:
Desktop Environments
o GNOME Desktop Environment
# from CD 3
rpm -Uvh libaio*
rpm -Uvh openmotif21-2.1.30-11.RHEL4.6.i386.rpm
rpm -Uvh openmotif-2.2.3-10.1.el4.i386.rpm
cd /u01/stage10g/patch10.2.0.4/Disk1
./runInstaller
Select path of ORACLE_HOME ->Next
4. Create Database
cd /u01/app/oracle/product/10.2.0/db_1/bin
./dbca &
follow the steps to create a customized database of SID "ora10g" and Global
nmae "ora10g.oradb1".
The DBCA may pop up the following message in the end of db creation:
"Error securing Database control, Database Control has been brought up in non-
secure mode. To secure the Database Control execute the following commands:
... "
5. Configure Listeners
cd /u01/app/oracle/product/10.2.0/db_1/bin
./netca &
Add a new listener
6. Postinstallation Tasks
• Verify OEM:
# verify that OEM is working
http://oradb1:1158/em
# restart the dbconsole if required
emctl status dbconsole
emctl stop dbconsole
emctl start dbconsole
• Verify iSQL*Plus:
# in the browser
http://oradb1:5560/isqlplus
# if not running:
isqlplusctl start
-- Database Edition
select banner from v$version where BANNER like '%Edition%';
-- 10g
SELECT COMPONENT , CURRENT_SIZE/1024/1024 MB
FROM V$SGA_DYNAMIC_COMPONENTS
WHERE CURRENT_SIZE <>0
-- Oracle 11g
SELECT COMPONENT, ROUND(CURRENT_SIZE/1024/1024) CURRENT_SIZE ,
ROUND(MIN_SIZE/1024/1024) MIN, ROUND(MAX_SIZE/1024/1024) MAX
FROM V$MEMORY_DYNAMIC_COMPONENTS;
-- To know how Oracle has modified the memory area sizes by time
select START_TIME, END_TIME, STATUS, COMPONENT, OPER_TYPE, OPER_MODE,
PARAMETER, INITIAL_SIZE/1024/1024 INITIAL_SIZE_MB,
TARGET_SIZE/1024/1024 TARGET_SIZE_MB, FINAL_SIZE/1024/1024 FINAL_SIZE_MB
from V$MEMORY_RESIZE_OPS
order by START_TIME, END_TIME
Startup Levels
Shutdown Levels
/* Example 1 */
#(1) login as root
#(2) Set it to Y in /etc/oratab
mydb:/u01/app/oracle/product/10.2.0/db_1:Y
#!/bin/sh
#
# /etc/rc.d/init.d/dbora
# Description: Starts and stops the Oracle database and listeners
#
case "$1" in
start)
/* Example 2 */
#(1) login as root
#(2) Set it to Y in /etc/oratab
mydb:/u01/app/oracle/product/10.2.0/db_1:Y
#!/bin/bash
#
# oracle Init file for starting and stopping
# Oracle Database. Script is valid for 10g and 11g versions.
#
# chkconfig: 35 80 30
# description: Oracle Database startup script
. /etc/rc.d/init.d/functions
ORACLE_OWNER="oracle"
ORACLE_HOME="/u01/app/oracle/product/10.2.0/db_1"
case "$1" in
start)
echo -n $"Starting Oracle DB:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME"
echo "OK"
echo -n "Starting Oracle Listeners:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/lsnrctl start"
echo "OK"
;;
stop)
echo -n $"Stopping Oracle DB:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbshut $ORACLE_HOME"
echo "OK"
echo -n "Stopping Oracle Listeners:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/lsnrctl stop"
echo "OK"
;;
*)
echo $"Usage: $0 {start|stop}"
esac
Quiescing a Database
• Users will remain logged in, and they can continue to execute their requests that are in
progress, while the database is in the quiesced state. The database, however, will block all
new transactional requests except those made by the users SYS and SYSTEM (not DBA
grantees).
ALTER SYSTEM QUIESCE RESTRICTED;
ALTER SYSTEM UNQUIESCE;
SELECT instance_name, status, shutdown_pending, active_state FROM v$instance;
Suspending a Database
• All reads from and writes to the datafiles and control files are suspended.
ALTER SYSTEM SUSPEND;
ALTER SYSTEM RESUME;
SELECT instance_name, status, shutdown_pending, active_state FROM v$instance;
Dropping a Database
• Datafiles, redo log files, and control files are removed automatically. Alert log and
parameter file are not deleted.
CONNECT sys/sys_passwd AS SYSDBA
SHUTDOW IMMEDIATE
STARTUP RESTRICT MOUNT
SELECT name FROM v$database;
DROP DATABASE;
Initialization Files
In Oracle 11g
-- undocumented parameters
SELECT
a.ksppinm parameter, a.ksppdesc description,
b.ksppstvl session_value, c.ksppstvl instance_value
FROM x$ksppi a, x$ksppcv b, x$ksppsv c
WHERE
a.indx = b.indx
AND a.indx = c.indx
AND SUBSTR (a.ksppinm,1,1) = '_'
ORDER BY a.ksppinm;
2. Copy an existing control file to a new location, using operating system commands.
Note: if you are using SPFILE, STARTUP NOMOUNT then use ALTER SYSTEM SET ..
SCOPE=SPFILE command.
Specify the RESETLOGS clause if you have lost any redo log groups in addition to control files.
In this case, you will need to recover from the loss of the redo logs (step 8). You must specify
the RESETLOGS clause if you have renamed the database. Otherwise, select the
NORESETLOGS clause.
10. If you did not perform recovery, open the database normally.
ALTER DATABASE OPEN;
If you specified RESETLOGS when creating the control file:
ALTER DATABASE OPEN RESETLOGS;
• If a datafile exists in the data dictionary but not in the new control file, the database creates
a placeholder entry in the control file under the name MISSINGnnnn, where nnnn is the file
number in decimal. MISSINGnnnn is flagged in the control file as being offline and requiring
media recovery.
o If the actual datafile corresponding to MISSINGnnnn is read-only or offline normal,
then you can make the datafile accessible by renaming MISSINGnnnn to the name
of the actual datafile.
# GROUP n is optional
ALTER DATABASE ADD LOGFILE GROUP 3
('/ORADATA/u01/log3a.rdo', '/ORADATA/u02/log3b.rdo')
SIZE 1M;
SHUTDOWN
Copy the redo log files to the new location.
STARTUP MOUNT
ALTER DATABASE
RENAME FILE '/diska/logs/log1a.rdo', '/diska/logs/log2a.rdo'
TO '/diskc/logs/log1c.rdo', '/diskc/logs/log2c.rdo';
ALTER DATABASE OPEN;
# it defaults to TURE
alter system set DB_BLOCK_CHECKSUM=true ;
CONN / AS SYSDBA
SHUTDOWN
Back up the database
see Specifying Archive Destinations ( next section )
STARTUP MOUNT
ALTER DATABASE ARCHIVELOG; -- or NOARCHIVELOG
ALTER DATABASE OPEN;
SHUTDOWN IMMEDIATE
Back up the database
-- to local destinations
LOG_ARCHIVE_DEST_1 = 'LOCATION=/disk1/archive'
LOG_ARCHIVE_DEST_1 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST'
-- to a standby db
LOG_ARCHIVE_DEST_4 = 'SERVICE = standby1'
-- LOG_ARCHIVE_TRACE defaults to 0
select value from v$parameter where upper(name)='LOG_ARCHIVE_TRACE';
-- database must be mounted but not open.
ALTER SYSTEM SET LOG_ARCHIVE_TRACE=12;
Managing Tablespaces
-- data files
select FILE_NAME,FILE_ID,T.TABLESPACE_NAME,
F.STATUS FILE_STATUS,
RELATIVE_FNO,
AUTOEXTENSIBLE,
ROUND(BYTES/1024/1024,2) FILESIZE_MB,
ROUND(MAXBYTES/1024/1024,2) MAXSIZE_MB,
ROUND((INCREMENT_BY*T.BLOCK_SIZE)/1024/1024,2) AUTOEXTENSION_SIZE_MB,
ROUND(USER_BYTES/1024/1024,2) AVAILABLE_FOR_DATA_MB -- remaining size used
from DBA_DATA_FILES F, DBA_TABLESPACES T -- for storing metadata
where F.TABLESPACE_NAME = T.TABLESPACE_NAME
order BY TABLESPACE_NAME, F.RELATIVE_FNO
select FILE_NAME,FILE_ID,T.TABLESPACE_NAME,
F.STATUS FILE_STATUS,
RELATIVE_FNO,
AUTOEXTENSIBLE,
ROUND(BYTES/1024/1024,2) FILESIZE_MB,
ROUND(MAXBYTES/1024/1024,2) MAXSIZE_MB,
ROUND((INCREMENT_BY*T.BLOCK_SIZE)/1024/1024,2) AUTOEXTENSION_SIZE_MB
from DBA_TEMP_FILES F, DBA_TABLESPACES
where F.TABLESPACE_NAME = T.TABLESPACE_NAME
order BY TABLESPACE_NAME, F.RELATIVE_FNO
-- tablespace groups
select GROUP_NAME, TABLESPACE_NAME
from DBA_TABLESPACE_GROUPS
order BY TABLESPACE_NAME
-- user qoutas
SELECT
USERNAME,TABLESPACE_NAME, BYTES/1024 SIZE_KB,
DECODE(MAX_BYTES,-1,-1,MAX_BYTES/1024/1024) MAX_MB
FROM DBA_TS_QUOTAS
ORDER BY USERNAME
Renaming a Tempfile
Renaming Tablespaces
Dropping Tablespaces
declare
v_segname varchar2(100) := 'EMPLOYEES';
v_segowner varchar2(100) :='HR';
v_segtype varchar2(100) :='TABLE';
v_tbs varchar2(100);
begin
select tablespace_name
into v_tbs
from dba_segments
where segment_name=v_segname and owner=v_segowner
and segment_type=v_segtype;
DBMS_SPACE_ADMIN.ASSM_SEGMENT_VERIFY (
segment_owner =>v_segowner,
segment_name =>v_segname,
segment_type =>v_segtype,
partition_name =>'',
verify_option => DBMS_SPACE_ADMIN.SEGMENT_VERIFY_DEEP
);
end;
declare
v_segname varchar2(100) := 'EMPLOYEES';
v_segowner varchar2(100) :='HR';
v_segtype varchar2(100) :='TABLE';
v_tbs varchar2(100);
begin
select tablespace_name
into v_tbs
from dba_segments
where segment_name=v_segname and owner=v_segowner
and segment_type=v_segtype;
DBMS_SPACE_ADMIN.ASSM_SEGMENT_VERIFY (
segment_owner =>v_segowner,
segment_name =>v_segname,
segment_type =>v_segtype,
partition_name =>'',
verify_option => DBMS_SPACE_ADMIN.SEGMENT_VERIFY_SPECIFIC,
attrib => DBMS_SPACE_ADMIN.BMB_CHECK
);
end;
/
select relative_fno
into v_rfno
from dba_data_files where tablespace_name = v_tbs and file_id=v_fno;
DBMS_SPACE_ADMIN.SEGMENT_VERIFY(
tablespace_name =>v_tbs,
begin
DBMS_SPACE_ADMIN.ASSM_TABLESPACE_VERIFY(
tablespace_name =>'EXAMPLE',
ts_option => DBMS_SPACE_ADMIN.TS_VERIFY_DEEP,
segment_option =>NULL);
end;
/
declare
v_segname varchar2(100) := 'EMPLOYEES';
v_segowner varchar2(100) :='HR';
v_tbs varchar2(100);
v_fno number ;
v_rfno number;
v_hdr number;
begin
-- retreive tablespace name, absolute file number
select tablespace_name, header_file, header_block
into v_tbs, v_fno, v_hdr
from dba_segments
where segment_name=v_segname and owner=v_segowner;
select relative_fno
into v_rfno
from dba_data_files
where tablespace_name = v_tbs and file_id=v_fno;
DBMS_SPACE_ADMIN.SEGMENT_CORRUPT (
tablespace_name =>v_tbs,
header_relative_file =>v_rfno,
header_block =>v_hdr,
corrupt_option =>DBMS_SPACE_ADMIN.SEGMENT_MARK_CORRUPT);
end;
declare
v_segname varchar2(100) := 'EMP';
v_segowner varchar2(100) :='HR';
v_tbs varchar2(100);
v_fno number ;
v_rfno number;
v_hdr number;
begin
-- retreive tablespace name, absolute file number
select tablespace_name, header_file, header_block
into v_tbs, v_fno, v_hdr
from dba_segments
where segment_name=v_segname and owner=v_segowner;
select relative_fno
into v_rfno
from dba_data_files
where tablespace_name = v_tbs and file_id=v_fno;
DBMS_SPACE_ADMIN.SEGMENT_DROP_CORRUPT(
tablespace_name =>v_tbs,
header_relative_file =>v_rfno,
header_block => v_hdr);
select relative_fno
into v_rfno
from dba_data_files
where tablespace_name = v_tbs and file_id=v_fno;
DBMS_SPACE_ADMIN.SEGMENT_DUMP(
tablespace_name =>v_tbs,
header_relative_file =>v_rfno,
header_block =>v_hdr,
dump_option => DBMS_SPACE_ADMIN.SEGMENT_DUMP_EXTENT_MAP);
end;
conn sys
begin
DBMS_SPACE_ADMIN.TABLESPACE_REBUILD_BITMAPS (
tablespace_name =>'EXAMPLE',
conn sys
exec DBMS_SPACE_ADMIN.TABLESPACE_REBUILD_QUOTAS('USERS');
Scenario 1: Fixing Bitmap When Allocated Blocks are Marked Free (No Overlap)
The TABLESPACE_VERIFY procedure discovers that a segment has allocated blocks that are
marked free in the bitmap, but no overlap between segments is reported.
In this scenario, perform the following tasks:
1. Call the SEGMENT_DUMP procedure to dump the ranges that the administrator allocated to
the segment.
2. For each range, call the TABLESPACE_FIX_BITMAPS procedure with the
TABLESPACE_EXTENT_MAKE_USED option to mark the space as used.
3. Call TABLESPACE_REBUILD_QUOTAS to fix up quotas.
Note: You must have been granted the EXECUTE_CATALOG_ROLE role (initially signed to SYS)
to execute this procedure.
set serveroutput on
DECLARE
V_WOPERATOR BINARY_INTEGER;
V_WVALUE VARCHAR2(50);
V_COPERATOR BINARY_INTEGER;
V_CVALUE VARCHAR2(50);
V_OBS_PERIOD BINARY_INTEGER;
V_CON_PERIOD BINARY_INTEGER;
FUNCTION GET_OPERATOR_NAME( P_OPER IN BINARY_INTEGER) RETURN VARCHAR2
IS
BEGIN
IF P_OPER =0 THEN
RETURN 'GT';
ELSIF P_OPER =1 THEN
RETURN 'EQ';
ELSIF P_OPER =2 THEN
RETURN 'LT';
ELSIF P_OPER =3 THEN
RETURN 'LE';
ELSIF P_OPER =4 THEN
DBMS_SERVER_ALERT.SET_THRESHOLD(
metrics_id => DBMS_SERVER_ALERT.TABLESPACE_PCT_FULL, -- tablespace USAGE by
%
warning_operator => DBMS_SERVER_ALERT.OPERATOR_DO_NOT_CHECK,
warning_value => '0',
critical_operator => DBMS_SERVER_ALERT.OPERATOR_DO_NOT_CHECK,
critical_value => '0',
observation_period => 1,
consecutive_occurrences => 1,
instance_name => NULL,
object_type => DBMS_SERVER_ALERT.OBJECT_TYPE_TABLESPACE,
object_name => 'USERS');
END;
/
SELECT *
FROM dba_thresholds
where object_name = 'USERS' and object_type='TABLESPACE';
SELECT *
FROM dba_thresholds
where object_name = 'USERS' and object_type='TABLESPACE';
SELECT *
FROM dba_thresholds
where object_name = 'USERS' and object_type='TABLESPACE';
Viewing Alerts
-- outstanding alerts (to be cleared)
SELECT
SEQUENCE_ID,OWNER,
OBJECT_NAME,OBJECT_TYPE,SUBOBJECT_NAME,
REASON_ID, REASON,TIME_SUGGESTED,
SUGGESTED_ACTION,ADVISOR_NAME,METRIC_VALUE,
MESSAGE_TYPE,MESSAGE_GROUP,MESSAGE_LEVEL,
HOSTING_CLIENT_ID,MODULE_ID,PROCESS_ID,
HOST_ID,HOST_NW_ADDR,INSTANCE_NAME,
INSTANCE_NUMBER,USER_ID,EXECUTION_CONTEXT_ID,CREATION_TIME
FROM DBA_OUTSTANDING_ALERTS
-- alert types
select
INST_ID,REASON_ID,OBJECT_TYPE,TYPE,GROUP_NAME,SCOPE,INTERNAL_METRIC_CATEGORY,
INTERNAL_METRIC_NAME
from GV$ALERT_TYPES
order by OBJECT_TYPE,TYPE
Creating Datafiles
CREATE TABLESPACE
CREATE TEMPORARY TABLESPACE ge 8-9
ALTER TABLESPACE ... ADD DATAFILE
ALTER TABLESPACE ... ADD TEMPFILE ge 8-9
CREATE DATABASE
ALTER DATABASE ... CREATE DATAFILE
Dropping Datafiles
• The following restrictions apply:
o The database must be open.
o The datafile must be empty, otherwise use drop the tablespace.
o You cannot drop datafiles in a read-only tablespace.
o You cannot drop datafiles in the SYSTEM tablespace.
o If a datafile in a locally managed tablespace is offline, it cannot be dropped.
BEGIN
DBMS_FILE_TRANSFER.PUT_FILE(
SOURCE_DIRECTORY_OBJECT => 'SOURCE_DIR',
SOURCE_FILE_NAME => 'mydata1.dbf',
DESTINATION_DIRECTORY_OBJECT => 'DEST_DIR',
index height
distinct index blocks in the lower level |
RBA block at position zero | |
| | | |
branch: 0×1c3588a 29579402 (0: nrow: 222, level: 1)
number of entries
lead block number (starts from -1) | non-deleted entries
| | |
leaf: 0×1c3588b 29579403 (-1: nrow: 485 rrow: 485)
leaf: 0×1c3588c 29579404 (0: nrow: 479 rrow: 479)
leaf: 0×1c3588d 29579405 (1: nrow: 479 rrow: 479)
leaf: 0×1c3588e 29579406 (2: nrow: 479 rrow: 479)
-- also, you can find the root block ( it is the block following the header bloc):
SELECT header_file, header_block+1 FROM dba_segments WHERE segment_name='MYINDEX';
-- undo segments
select SEGMENT_NAME,OWNER,STATUS from DBA_ROLLBACK_SEGS;
-- undo extents
select
e.SEGMENT_NAME,
e.TABLESPACE_NAME,
e.EXTENT_ID,
e.FILE_ID,
e.BLOCK_ID,
e.BYTES/1024 SIZE_KB,
e.RELATIVE_FNO,
e.STATUS -- ACTIVE EXPIRED UNEXPIRED
from DBA_UNDO_EXTENTS e
order by e.STATUS ASC
set serveroutput on
DECLARE
tid NUMBER; -- task ID
tname VARCHAR2(30); -- task name
oid NUMBER;
SELECT DBA_ADVISOR_RECOMMENDATIONS.GET_TASK_REPORT('TASKNAME')
FROM DUAL;
-----------------------------------------------------------------
/* Interval Partitioning */
-- You can’t use a partitioning key that includes more than one column
-- system generated partions have names SYS_Pn
CREATE TABLE interval_sales
( prod_id NUMBER(6),
cust_id NUMBER,
time_id DATE,
..)
-----------------------------------------------------------------
/* Hash Partitioning */
-- used when range distribution is not predictable and for high cardinality columns
-- Updates that would cause a record to move across partition boundaries are not allowed
CREATE TABLE sales_data
(ticket_no NUMBER,
sale_year INT NOT NULL,
sale_month INT NOT NULL,
sale_day INT NOT NULL )
PARTITION BY HASH (ticket_no)
PARTITIONS 4
STORE IN (ts1,ts2,ts3,ts4);
-----------------------------------------------------------------
/* List Partitioning */
CREATE TABLE sales_data
(ticket_no NUMBER,
sale_year INT NOT NULL,
-----------------------------------------------------------------
/* Reference Partitioning */
-- put child table data into parent table partitions
-- You can use all partitioning strategies with reference partitioning, except interval
partitioning
-----------------------------------------------------------------
-----------------------------------------------------------------
-----------------------------------------------------------------
/* System Partitioning */
-- the application decided where to store the data
CREATE TABLE docs
( ID NUMBER,
Name VARCHAR2(255),
Desc VARCHAR2(1000))
PARTITION BY SYSTEM
( PARTITION docs_p1 TABLESPACE ts1,
PARTITION docs_p2 TABLESPACE ts2,
PARTITION docs_p3 TABLESPACE ts3,
PARTITION docs_p4 TABLESPACE ts4 );
-----------------------------------------------------------------
/* Range-Hash Partitioning */
-----------------------------------------------------------------
/* Range-List Partitioning */
-----------------------------------------------------------------
-- Splitting a Partition
ALTER TABLE ticket_sales
SPLIT PARTITION ticket_sales01 AT (2000) INTO
(PARTITION ticket_sales01A, ticket_sales01B);
-- Merging Partitions
ALTER TABLE ticket_sales
MERGE PARTITIONS ticket_sales01, ticket_sales02 INTO PARTITION ticket_sales02;
-- Renaming Partitions
ALTER TABLE RENAME PARTITION fight_sales01 TO quarterly_sales01;
-- Exchanging Partitions
-- convert a regular nonpartitioned table into a partition of a partitioned table
-- it only renames the source and destination
ALTER TABLE ticket_sales
EXCHANGE PARTITION ticket_sales02 WITH ticket_sales03;
-- Dropping Partitions
-- Coalescing Partitions
-- applied on hash-partitioned and list-partitioned
-- to reduce number of partitions
ALTER TABLE ticket_sales COALESCE PARTITION;
begin
DBMS_STATS.GATHER_SCHEMA_STATS (
ownname =>'HR',
estimate_percent =>NULL,
method_opt =>'FOR ALL COLUMNS SIZE AUTO',
degree => DBMS_STATS.DEFAULT_DEGREE,
granularity =>'ALL',
cascade =>TRUE,
options =>'GATHER AUTO');
end;
/
/*
-- If the error is related to undo segments, log error, send email
-- to DBA, and abort the statement. Otherwise, set timeout to 8 hours.
--
-- sys.rbs_error is a table which is to be
-- created by a DBA manually and defined as
-- (sql_text VARCHAR2(1000), error_msg VARCHAR2(4000), suspend_time DATE)
*/
SELECT SID,SEQ#,EVENT,
P1TEXT,P1,P1RAW,
P2TEXT,P2,P2RAW,
P3TEXT,P3,P3RAW,
WAIT_CLASS_ID,WAIT_CLASS#,WAIT_CLASS,
WAIT_TIME,SECONDS_IN_WAIT,STATE
FROM V$SESSION_WAIT
WHERE EVENT LIKE '%statement suspended%'
exec DBMS_RESUMABLE.ABORT(159);
select DBMS_RESUMABLE.GET_SESSION_TIMEOUT(159) from dual;
exec DBMS_RESUMABLE.SET_SESSION_TIMEOUT(sessionID=>159,timeout=>8000);
-- space usage of data blocks under the segment High Water Mark with
-- auto segment space management Tablespaces
-- following code in Oracle 10g
set serveroutput on
declare
-- IN vars
v_segment_owner VARCHAR2(100):='HR';
v_segment_name VARCHAR2(100) :='NAMES2';
v_segment_type VARCHAR2(100) :='TABLE';
v_partition_name VARCHAR2(100) :=null;
exception
/* Using Views */
-- segment info
select OWNER,SEGMENT_NAME,PARTITION_NAME,SEGMENT_TYPE,S.TABLESPACE_NAME,
HEADER_FILE,HEADER_BLOCK,S.BYTES/1024/1024 SEGMENT_SIZE_MB,
D.BLOCKS SEGMENT_BLOCKS,EXTENTS,S.INITIAL_EXTENT,
S.NEXT_EXTENT NEXT_EXTENT_SIZE, S.MIN_EXTENTS,S.MAX_EXTENTS,S.PCT_INCREASE,
FREELISTS,FREELIST_GROUPS,D.RELATIVE_FNO, D.FILE_NAME
from DBA_SEGMENTS S, DBA_TABLESPACES T, DBA_DATA_FILES D
where S.TABLESPACE_NAME = T.TABLESPACE_NAME AND T.TABLESPACE_NAME =
D.TABLESPACE_NAME
AND S.RELATIVE_FNO = D.RELATIVE_FNO
AND T.TABLESPACE_NAME NOT IN ('SYSAUX','SYSTEM')
order BY S.TABLESPACE_NAME;
-- extent info
SELECT EXTENT_ID, E.BLOCK_ID,E.BYTES/1024 EXTENT_SIZE_KB,
E.OWNER,E.SEGMENT_NAME,E.PARTITION_NAME,
E.SEGMENT_TYPE,D.FILE_NAME, S.TABLESPACE_NAME,HEADER_FILE,
HEADER_BLOCK SEG_HEADER_BLOCK,S.BYTES/1024/1024 SEGMENT_SIZE_MB,D.BLOCKS
SEGMENT_BLOCKS, EXTENTS SEG_EXTENTS
FROM DBA_EXTENTS E, DBA_SEGMENTS S, DBA_DATA_FILES D
WHERE E.OWNER=S.OWNER AND E.SEGMENT_NAME = S.SEGMENT_NAME
AND NVL(E.PARTITION_NAME,'0') = NVL(S.PARTITION_NAME,'0')
AND E.SEGMENT_TYPE = S.SEGMENT_TYPE
AND E.FILE_ID = D.FILE_ID
AND S.TABLESPACE_NAME NOT IN ('SYSAUX','SYSTEM')
ORDER BY E.SEGMENT_NAME, E.OWNER, E.PARTITION_NAME,E.EXTENT_ID;
dbms_advisor.set_task_parameter(
task_name => v_name,
parameter => 'recommend_all',
value => 'TRUE');
dbms_advisor.execute_task(v_name);
end;
/
SELECT OWNER,TASK_ID,TASK_NAME,
FINDING_ID,TYPE,PARENT,
OBJECT_ID,IMPACT_TYPE,IMPACT,MESSAGE,MORE_INFO
FROM DBA_ADVISOR_FINDINGS
WHERE TASK_ID = :ID
-- analyzed objects
SELECT OWNER,OBJECT_ID,TYPE,TYPE_ID,
TASK_ID,TASK_NAME,ATTR1,ATTR2,
ATTR3,ATTR4,ATTR5,OTHER
FROM DBA_ADVISOR_OBJECTS
WHERE TASK_ID = :ID
-- defrage and don't move HWM (later you can SHRINK SPACE)
-- shrink partition
ALTER TABLE customers MODIFY PARTITION cust_P1 SHRINK SPACE;
-- IOT
ALTER TABLE cities SHRINK SPACE CASCADE;
DBMS_SPACE.CREATE_TABLE_COST (
tablespace_name => v_tablespace_name,
avg_row_size => v_avg_row_size,
row_count => v_row_count,
pct_free => v_pct_free,
used_bytes => v_used_bytes,
alloc_bytes => v_alloc_bytes);
SELECT *
FROM
table(
DBMS_SPACE.OBJECT_GROWTH_TREND (
object_owner =>'HR',
object_name =>'NAMES',
object_type =>'TABLE',
partition_name =>NULL,
start_time =>NULL,
end_time =>NULL,
interval =>to_dsinterval('0 00:10:00') , -- Day to Second interval
skip_interpolated => 'FALSE',
timeout_seconds =>NULL,
single_datapoint_flag =>'TRUE')
)
-- reset the task ( remove all recommendations, and intermediate data from
the task)
DBMS_ADVISOR.RESET_TASK(TASK_NAME => l_taskname);
IF l_num_found = 0 THEN
DBMS_ADVISOR.CREATE_SQLWKLD(WORKLOAD_NAME => l_wkld_name);
END IF;
IF l_num_found = 0 THEN
DBMS_ADVISOR.ADD_SQLWKLD_REF(
TASK_NAME => l_taskname,
WORKLOAD_NAME => l_wkld_name);
END IF;
-- Execute the task: control will not return till the execution finishes
DBMS_ADVISOR.execute_task(task_name => l_taskname);
END;
/
-- reset the task ( remove all recommendations, and intermediate data from
the task)
DBMS_ADVISOR.RESET_TASK(TASK_NAME => l_taskname);
-- create STS
DBMS_SQLTUNE.CREATE_SQLSET(SQLSET_NAME => l_sts_name, DESCRIPTION =>'To
test Access Advisor');
-- Next the statements and their statistics are loaded into the STS
DBMS_SQLTUNE.LOAD_SQLSET( SQLSET_NAME=>l_sts_name,
POPULATE_CURSOR=>baseline_cur);
end;
-- (Option 2) Load l_sts_name with SQL statements that are not owned by SYS
and
-- their elapsed time is greater than 20,000 seconds.
declare
sql_cur DBMS_SQLTUNE.SQLSET_CURSOR;
begin
-- a ref cursor is opened to select the required SQL statments
OPEN sql_cur FOR
SELECT VALUE(p)
FROM TABLE (DBMS_SQLTUNE.SELECT_CURSOR_CACHE('parsing_schema_name <>
''SYS'' and elapsed_time > 2000000',NULL, NULL, NULL, NULL,1, NULL, 'ALL'))
p;
-- the statements are loaded into the STS
DBMS_SQLTUNE.LOAD_SQLSET( SQLSET_NAME=>l_sts_name,
POPULATE_CURSOR=>sql_cur);
end;
-- (Option 3) Copy the contents of a SQL workload object to a SQL Tuning Set
-- check the example above for creating a workload
DBMS_ADVISOR.COPY_SQLWKLD_TO_STS ('My_WorkLoad', l_sts_name, 'REPLACE');
*/
-- Execute the task: control will not return till the execution finishes
DBMS_ADVISOR.EXECUTE_TASK(task_name => l_taskname);
END;
/
Following are examples of how to manage the task and obtain information about the advisor’s
output repot:
-- while the task is being executed, you can monitor it using the following
query:
select TASK_NAME, STATUS, PCT_COMPLETION_TIME, ERROR_MESSAGE
from DBA_ADVISOR_LOG
where TASK_NAME ='sql_access_test_task';
-- columns
SELECT
OWNER,TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_TYPE_MOD,DATA_TYPE_OWNER,DATA_LENGTH,DATA_P
RECISION,DATA_SCALE,NULLABLE,COLUMN_ID,DEFAULT_LENGTH,DATA_DEFAULT,NUM_DISTINCT,LOW_VAL
UE,HIGH_VALUE,DENSITY,NUM_NULLS,NUM_BUCKETS,LAST_ANALYZED,SAMPLE_SIZE,CHARACTER_SET_NAM
E,CHAR_COL_DECL_LENGTH,GLOBAL_STATS,USER_STATS,AVG_COL_LEN,CHAR_LENGTH,CHAR_USED,V80_FM
T_IMAGE,DATA_UPGRADED,HISTOGRAM
FROM DBA_TAB_COLUMNS
WHERE TABLE_NAME='EMP' AND OWNER='HR';
-- comments
select * from DBA_TAB_COMMENTS;
select * from DBA_COL_COMMENTS;
-- nologging
-- compression
CREATE TABLE mytb ( ... ) COMPRESS FOR ALL OPERATIONS; -- OK in OLTP
CREATE TABLE sales_history ( ... ) COMPRESS FOR DIRECT_LOAD OPERATIONS; -- OK in OLAP
CREATE TABLE sales_history ( ... ) COMPRESS; -- same as above
CREATE TABLE sales
(saleskey number, quarter .. region varchar2(10)) COMPRESS
PARTITION BY LIST (region)
(PARTITION northwest VALUES ('NORTHWEST'),
PARTITION southwest VALUES ('SOUTHWEST'),
PARTITION northeast VALUES ('NORTHEAST') NOCOMPRESS,
PARTITION southeast VALUES ('SOUTHEAST'),
PARTITION western VALUES ('WESTERN'))
-- temporary table
-- transaction level
CREATE GLOBAL TEMPORARY TABLE mytb (..) ON COMMIT DELETE ROWS;
-- session level
CREATE GLOBAL TEMPORARY TABLE mytb (..) ON COMMIT PRESERVE ROWS;
• When you are inserting in parallel DML mode, direct-path INSERT is the default. In order
to run in parallel DML mode, the following requirements must be met:
o You must have Oracle Enterprise Edition installed.
o You must enable parallel DML in your session. To do this, run the following statement:
ALTER SESSION { ENABLE | FORCE } PARALLEL DML;
o You must specify the parallel attribute for the target table, either at create time or
subsequently, or you must specify the PARALLEL hint for each insert operation.
insert /*+ parallel */ into names3 (select * from names)
• If nologging is specified, the insert will finish faster.
select logging from dba_tables where owner='HR' and table_name='EMPLOYEES';
select logging from dba_tablespaces where tablespace_name = 'USERS';
• Index maintenance is done by end of command. Consider drop and then re-creating the
indexes after the statement.
• Exclusive table lock is acquired.
Altering Tables
• If you enable compression for all operations on a table, you can drop table columns. If you
enable compression for direct-path inserts only, you cannot drop columns.
-- move the table to a new segment
-- indexes will be UNUSABLE and must be rebuilt
-- statistics must be regathered
ALTER TABLE hr.emp MOVE
STORAGE ( INITIAL 20K
NEXT 40K
MINEXTENTS 2
MAXEXTENTS 20
PCTINCREASE 0 );
alter table emp MOVE TABLESPACE example ;
alter table emp move storage (
NEXT 1024K
PCTINCREASE 0 )
COMPRESS;
Redefining a Table
/*
This example illustrates online redefinition of the previously created table
hr.admin_emp, which at this point only contains columns: empno, ename,
job,deptno.
The table is redefined as follows:
-New columns mgr, hiredate, sal, and bonus are added.
-The new column bonus is initialized to 0
-The column deptno has its value increased by 10.
-The redefined table is partitioned by range on empno.
*/
--1 Verify that the table is a candidate for online redefinition.
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE(
UNAME => 'HR',
TNAME => 'ADMIN_EMP',
OPTIONS_FLAG => dbms_redefinition.cons_use_pk); -- OR
DBMS_REDEFINITION.CONS_USE_ROWID
END;
/
-- 2. Create an interim table hr.int_admin_emp.
CREATE TABLE hr.int_admin_emp
(empno NUMBER(5) PRIMARY KEY,
ename VARCHAR2(15) NOT NULL,
job VARCHAR2(10),
mgr NUMBER(5),
hiredate DATE DEFAULT (sysdate),
sal NUMBER(7,2),
deptno NUMBER(3) NOT NULL,
bonus NUMBER (7,2) DEFAULT(1000))
PARTITION BY RANGE(empno)
(PARTITION emp1000 VALUES LESS THAN (1000) TABLESPACE admin_tbs,
PARTITION emp2000 VALUES LESS THAN (2000) TABLESPACE admin_tbs2);
/* Note that the ignore_errors argument is set to TRUE for this call. The
reason is that the interim table was created with a primary key constraint,
and when COPY_TABLE_DEPENDENTS attempts to copy the primary key constraint
and index from the original table, errors occurs. You can ignore these
errors, but you must run the query shown in the next step to see if there are
other errors. */
/* The table hr.admin_emp is locked in the exclusive mode only for a small
CONNECT pm
declare
col_mapping VARCHAR2(1000);
begin
-- map all the columns in the interim table to the original table
col_mapping :='c_id c_id , '||'c_zip c_zip , '||'c_name c_name, '||'c_lob
c_lob';
DBMS_REDEFINITION.START_REDEF_TABLE('pm', 'cust', 'cust_int', col_mapping);
end;
declare
error_count pls_integer := 0;
begin
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('pm', 'cust', 'cust_int',
1, TRUE,TRUE,TRUE,FALSE, error_count);
DBMS_OUTPUT.PUT_LINE('errors := ' || TO_CHAR(error_count));
end;
-- to prove that the primary key on the c_id column is preserved after
migration.
INSERT INTO cust VALUES(1, 94065, 'hhh', 'ttt');
SELECT * FROM cust;
-- more options
-- in ACCESS PARAMETERS you can add
LOAD WHEN (job != MANAGER)
-- access driver processes only the columns in the select list (default)
ALTER TABLE admin_ext_employees PROJECT COLUMN REFERNCED;
-- the access driver processes all of the columns
-- This setting always provides a consistent set of returned rows
ALTER TABLE admin_ext_employees PROJECT COLUMN ALL;
-- default directory
ALTER TABLE admin_ext_employees DEFAULT DIRECTORY admin_dat2_dir;
-- access parameter
ALTER TABLE admin_ext_employees ACCESS PARAMETERS (FIELDS TERMINATED BY ';');
-- location
ALTER TABLE admin_ext_employees LOCATION ('empxt3.txt', 'empxt4.txt');
Using Indexes
• When creating an extremely large index, consider allocating a larger temporary tablespace
specially for the index creation.
• If you want the optimizer to consider the invisible indexes in its operation, you can set the
new initialization parameter OPTIMIZER_USE_INVISIBLE_INDEXES to TRUE (the default is
FALSE). You can set the parameter in the system and session levels.
-- obtain info about indexes
select * from DBA_INDEXES;
select * from DBA_IND_COLUMNS;
-- for funcation-based indexes
select * from DBA_IND_EXPRESSIONS;
-- optimizer stats
select * from DBA_IND_STATISTICS;
-- obtained from ANALYZE INDEX...VALIDATE STRUCTURE
select * from INDEX_STATS;
-- create index
CREATE INDEX emp_ename ON emp(ename)
TABLESPACE users
STORAGE (INITIAL 20K
NEXT 20k
PCTINCREASE 75);
CREATE INDEX emp_ename ON emp(ename) COMPUTE STATISTICS;
CREATE INDEX emp_name ON emp (mgr, emp1, emp2, emp3) ONLINE;
CREATE UNIQUE INDEX dept_unique_index ON dept (dname) TABLESPACE indx;
CREATE TABLE emp ( empno NUMBER(5) PRIMARY KEY, age INTEGER) ENABLE PRIMARY
KEY USING INDEX TABLESPACE users;
CREATE TABLE a ( a1 INT PRIMARY KEY USING INDEX (create index ai on a (a1)));
CREATE TABLE b( b1 INT, b2 INT,
CONSTRAINT bu1 UNIQUE (b1, b2)
USING INDEX (create unique index bi on b(b1, b2)),
CONSTRAINT bu2 UNIQUE (b2, b1) USING INDEX bi);
CREATE TABLE c(c1 INT, c2 INT);
CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;
-- bitmap index
CREATE BITMAP INDEX gender_idx ON employee(gender) TABLESPACE emp_index_05;
-- Reverse-Key Indexes
-- good when you do sequential insertion of values into the index
CREATE INDEX reverse_idx ON employee(emp_id) REVERSE;
-- function based
CREATE INDEX area_index ON rivers (area(geo));
-- compress
CREATE INDEX emp_ename ON emp(ename) TABLESPACE users COMPRESS 1;
ALTER INDEX emp_ename REBUILD NOCOMPRESS;
-- rebuilding an index
ALTER INDEX emp_name REBUILD;
ALTER INDEX emp_name REBUILD ONLINE;
Partitioned Indexes
-- Global Indexes
-- can be nonpartitioned or partitioned indexes
CREATE INDEX ticketsales_idx ON
ticket_sales(month) GLOBAL
PARTITION BY range(month)
(PARTITION ticketsales1_idx VALUES LESS THAN (3)
PARTITION ticketsales1_idx VALUES LESS THAN (6)
PARTITION ticketsales2_idx VALUES LESS THAN (9)
PARTITION ticketsales3_idx VALUES LESS THAN (MAXVALUE));
-- Local Indexes
CREATE INDEX ticket_no_idx ON
ticket_sales(ticket__no) LOCAL TABLESPACE localidx_01;
-- mv log
-- you must specify the ROWID, SEQUENCE and the INCLUDING NEW VALUES
-- For aggregate materialized views, it must also contain every column
-- in the table referenced in the materialized view
CREATE MATERIALIZED VIEW LOG
ON employees WITH SEQUENCE, ROWID
(employee_id,department_id,salary) INCLUDING NEW VALUES;
-- create mv
-- the options
BUILD IMMEDIATE | DEFERRED
REFRESH NEVER, FAST, FORCE, COMPLETE - on commit or on demand
ENABLE QUERY REWRITE -- is a must for rewriting queries. DISABLE
WITH PRIMARY KEY
START WITH ROUND(SYSDATE + 1) + 11/24 NEXT NEXT_DAY(TRUNC(SYSDATE), 'MONDAY')
+ 15/24
recommended to gather stats on it then
EXECUTE DBMS_STATS.GATHER_TABLE_STATS ( 'HR','DEPT01_MV', estimate_percent
=> 20, block_sample => TRUE, cascade => TRUE);
/* commenting on mvs */
COMMENT ON MATERIALIZED VIEW sales_mv IS 'sales materialized view';
SELECT MVIEW_NAME, COMMENTS
FROM USER_MVIEW_COMMENTS WHERE MVIEW_NAME = 'SALES_MV';
/* Column Alias */
-- failed example
CREATE MATERIALIZED VIEW sales_mv
ENABLE QUERY REWRITE AS
SELECT s.time_id sales_tid, c.time_id costs_tid
FROM sales s, products p, costs c
WHERE s.prod_id = p.prod_id AND c.prod_id = p.prod_id AND
p.prod_name IN (SELECT prod_name FROM products);
-- the right way
CREATE MATERIALIZED VIEW sales_mv (sales_tid, costs_tid)
ENABLE QUERY REWRITE AS
SELECT s.time_id, c.time_id
FROM sales s, products p, costs c
WHERE s.prod_id = p.prod_id AND c.prod_id = p.prod_id AND
p.prod_name IN (SELECT prod_name FROM products);
/* Rewrite Integrity */
-- QUERY_REWRITE_INTEGRITY: ENFORCED (returned data is 100% correct), TRUSTED,
STALE_TOLERATED
ReWrite Hints
/* REWRITE and NOREWRITE Hints */
SELECT /*+ NOREWRITE */ ...
SELECT /*+ REWRITE (sum_sales_pscat_week_mv) */ ...
/* NO_MULTIMV_REWRITE hint prevents the query from being rewritten with more
than one materialized
NO_BASETABLE_MULTIMV_REWRITE hint prevents the query from being rewritten
with a combination of materialized views and the base tables
*/
DBMS_MVIEW.EXPLAIN_MVIEW (
mv -- mv, a SELECT or a CREATE MATERIALIZED VIEW statement
statement_id -- any id
SELECT MSGTXT
FROM MV_CAPABILITIES_TABLE
WHERE STATEMENT_ID='ID01'
ORDER BY SEQ
/
-- create cluster
CREATE CLUSTER emp_dept (deptno NUMBER(3))
SIZE 600
TABLESPACE users
STORAGE (INITIAL 200K
NEXT 300K
MINEXTENTS 2
MAXEXTENTS 20
PCTINCREASE 33);
CREATE TABLE emp (
empno NUMBER(5) PRIMARY KEY,
ename VARCHAR2(15) NOT NULL,
. . .
deptno NUMBER(3) REFERENCES dept)
CLUSTER emp_dept (deptno);
CREATE TABLE dept (
deptno NUMBER(3) PRIMARY KEY, . . . )
CLUSTER emp_dept (deptno);
-- dropping a cluster
-- no tables
DROP CLUSTER emp_dept;
-- there are tables
DROP CLUSTER emp_dept INCLUDING TABLES;
DROP CLUSTER emp_dept INCLUDING TABLES CASCADE CONSTRAINTS;
-- drop a table in the cluster
drop table dept;
-- obtain info
selet * from DBA_CLUSTERS ;
-- create views
CREATE VIEW sales_staff AS
SELECT empno, ename, deptno FROM emp WHERE deptno = 10
WITH CHECK OPTION CONSTRAINT sales_staff_cnst;
-- Creating Views with Errors
CREATE FORCE VIEW AS ...;
-- creating sequence
CREATE SEQUENCE emp_sequence
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
CACHE 10;
-- alter a sequence
ALTER SEQUENCE emp_sequence
INCREMENT BY 10
MAXVALUE 10000
CYCLE
CACHE 20;
-- Creating Synonyms
CREATE PUBLIC SYNONYM public_emp FOR jward.emp;
-- Oracle 11g: to allow DDL wait for lock instead or returning error
ALTER SESSION SET ddl_lock_timeout = 30;
select SID,
DECODE(TYPE,'TM','DML enqueue','TX','Transaction enqueue','UL','User
supplied',TYPE) LOCK_TYPE,
DECODE(TO_CHAR(LMODE),'0','None','1','Null','2','Row-S (SS)','3','Row-X
(SX)','4','Share (S)','5','S/Row-X (SSX)','6','Exclusive (X)') HELD_LMODE,
DECODE(TO_CHAR(REQUEST),'0','None','1','Null','2','Row-S (SS)','3','Row-X
(SX)','4','Share (S)','5','S/Row-X (SSX)','6','Exclusive (X)') REQUEST_LMODE
from v$lock
where BLOCK=1;
-- privs
begin
dbms_wm.grantSystemPriv (
'ACCESS_ANY_WORKSPACE, ' ||
'MERGE_ANY_WORKSPACE, ' ||
'CREATE_ANY_WORKSPACE, ' ||
'REMOVE_ANY_WORKSPACE, ' ||
'ROLLBACK_ANY_WORKSPACE' ,
'USER1' ,
'YES');
end;
/
conn user1
-- testing data
-- Note: rows cannot be inserted if the Workspace isn't
-- in its latest version by DBMS_WM.GotoSavePoint();
insert into dept values (1,'d1');
commit;
insert into emp values (1,'e1',1);
insert into emp values (2,'e2',1);
commit;
begin
select to_char(sysdate, 'dd.mm.yyyy hh24:mi:ss') into :dt_1 from dual;
end;
/
-- disable versioning
begin
dbms_wm.disableVersioning('DEPT');
dbms_wm.disableVersioning('EMP');
end;
/
conn user1
-- create workspaces
begin
-- you won't see changes made in the LIVE workspace nor the changes
-- made in the WS1 workspace.
select * from emp, dept where emp.deptno=dept.deptno;
-- move to WS1
begin
dbms_wm.gotoworkspace('WS1');
end;
/
-- MERGE WS2
begin
dbms_wm.mergeworkspace('WS2');
end;
/
-- cleaning up
begin
dbms_wm.disableversioning ('dept, emp', true);
end;
/
begin
dbms_wm.gotoworkspace ('LIVE');
dbms_wm.removeworkspace('WS1');
dbms_wm.removeworkspace('WS2');
end;
/
/* Resolving Conflicts */
-- privs
begin
dbms_wm.grantSystemPriv (
'ACCESS_ANY_WORKSPACE, ' ||
'MERGE_ANY_WORKSPACE, ' ||
'CREATE_ANY_WORKSPACE, ' ||
'REMOVE_ANY_WORKSPACE, ' ||
'ROLLBACK_ANY_WORKSPACE' ,
'USER1' ,
'YES');
end;
/
-- make an update
update emp set ename='in WS1' where empno=1;
commit;
-- make an update
update emp set ename='in LIVE' where empno=1;
commit;
-- Cleaning up
begin
dbms_wm.gotoworkspace('LIVE');
dbms_wm.removeworkspace('WS1');
dbms_wm.disableversioning('emp,dept');
end;
/
• Possible Values:
o OFF: No block checking (except for SYSTEM) (default)
o LOW: Basic block header checks are performed after block contents change in memory
o MEDIUM: All LOW checks, as well as block checking for all non-index-organized table
blocks, are performed.
o FULL: All LOW and MEDIUM checks, as well as checks on index blocks, are performed.
alter system set DB_BLOCK_CHECKING=FULL;
• A data block lost write occurs when an I/O subsystem acknowledges the completion of the
block write, while in fact the write did not occur in the persistent storage.
DB_LOST_WRITE_PROTECT = { NONE | TYPICAL | FULL }
off this value means any values you set for any of the three parameters will not be
overridden.
data and index The effective value of the parameters will be as follows:
Parameter Active Value
DB_BLOCK_CHECKING full
DB_LOST_WRITE_PROTECT typical
DB_BLOCK_CHECKSUM. full
Using DBMS_REPAIR
-- 2. report corruptions
SET SERVEROUTPUT ON
DECLARE
num_corrupt INT;
BEGIN
num_corrupt := 0;
DBMS_REPAIR.CHECK_OBJECT (
schema_name => 'HR',
object_name => 'DEPARTMENTS',
repair_table_name => 'REPAIR_TABLE',
corrupt_count => num_corrupt);
END;
/
-- 3. make the object usable: ignoring corruptions during table and index
scans
-- mark corrupted blocks
SET SERVEROUTPUT ON
DECLARE num_fix INT;
BEGIN
num_fix := 0;
DBMS_REPAIR.FIX_CORRUPT_BLOCKS (
schema_name => 'HR',
object_name => 'DEPARTMENTS',
object_type => DBMS_REPAIR.TABLE_OBJECT,
repair_table_name => 'REPAIR_TABLE',
fix_count => num_fix);
END;
/
SET SERVEROUTPUT ON
DECLARE num_orphans INT;
BEGIN
num_orphans := 0;
DBMS_REPAIR.DUMP_ORPHAN_KEYS(
schema_name => 'SCOTT',
object_name => 'PK_DEPT',
object_type => DBMS_REPAIR.INDEX_OBJECT,
repair_table_name => 'REPAIR_TABLE',
orphan_table_name => 'ORPHAN_KEY_TABLE',
key_count => num_orphans);
DBMS_OUTPUT.PUT_LINE('Orphan Key Count: ' ||TO_CHAR(num_orphans));
END;
/
-- disable
BEGIN
DBMS_AUTO_TASK_ADMIN.DISABLE(
client_name => 'sql tuning advisor',
operation => NULL,
window_name => NULL); -- null means all widows
END;
/
-- enable
BEGIN
DBMS_AUTO_TASK_ADMIN.ENABLE(
client_name => 'sql tuning advisor',
operation => NULL,
window_name => NULL);
END;
/
• The steps:
1. Create a pending area.
2. Create a resource consumer group.
3. Create a resource plan.
4. Create a plan directive.
5. Validate the pending area.
6. Submit the pending area
-- required privs
exec DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SYSTEM_PRIVILEGE -
(GRANTEE_NAME => 'scott', PRIVILEGE_NAME => 'ADMINISTER_RESOURCE_MANAGER');
begin
dbms_resource_manager.create_consumer_group (
CONSUMER_GROUP => 'PROGRAMMERS',
COMMENT => 'IT programmers',
CPU_MTH => 'ROUND-ROBIN' -- other possible value is RUN_TO_COMPLETION
);
end;
/
begin
dbms_resource_manager.create_consumer_group (
CONSUMER_GROUP => 'CLERKS',
COMMENT => 'Group of Clerks',
CPU_MTH => 'ROUND-ROBIN'
);
begin
dbms_resource_manager.set_consumer_group_mapping(
ATTRIBUTE => dbms_resource_manager.oracle_user, -- it is constant (no
quots)
VALUE => 'U2',
CONSUMER_GROUP => 'CLERKS');
end;
/
-- Resource Plans
-- Simple Resource Plan (single-level resource plans for allocating CPU)
/* 10g (deprecated in 11g) */
BEGIN
DBMS_RESOURCE_MANAGER.CREATE_SIMPLE_PLAN(
SIMPLE_PLAN => 'JOBS_PLAN',
CONSUMER_GROUP1 => 'PROGRAMMERS',
GROUP1_CPU => 75,
CONSUMER_GROUP2 => 'CLERKS',
GROUP2_CPU => 25);
end;
/
-- Note: the final output is still multi-level
begin
DBMS_RESOURCE_MANAGER.DELETE_PLAN ('JOBS_PLAN');
end;
/
-- *****************
/* Complex Plan: CG, Resource P., Res. Plan Dir. */
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'NW_PLAN',
COMMENT => 'Clerks CPU quota',
GROUP_OR_SUBPLAN => 'CLERKS',
CPU_P2=> 30);
end;
/
BEGIN
dbms_resource_manager.create_plan_directive(
PLAN => 'NW_PLAN',
COMMENT => 'Progs CPU quota',
GROUP_OR_SUBPLAN => 'PROGRAMMERS',
CPU_P2=> 70);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'NW_PLAN',
COMMENT => 'OTHER_GROUPS CPU ALLOCATION',
GROUP_OR_SUBPLAN => 'OTHER_GROUPS',
CPU_P3=> 100);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'NW_PLAN',
COMMENT => 'SWITCH PROGRAMMERS TEMPORARILY',
GROUP_OR_SUBPLAN => 'PROGRAMMERS',
SWITCH_TIME_IN_CALL => 900,
SWITCH_GROUP => 'LOW_GROUP',
SWITCH_ESTIMATE => TRUE);
end;
/
OFF_HOURS_PLAN
SYS_GROUP 10
NIGHT_GROUP 5
REPORTS_GROUP 2
OTHER_GROUPS 1
DAY_PLAN
LEVEL1 SYS_GROUP 100%
LEVEL2 OLTP_PLAN 100%
LEVEL1 OLTP_GROUP 90% DREPORTS_GROUP 10%
LEVEL2 OTHERS_GROUPS 100%
LEVEL3 OTHERS_GROUPS 100%
exec dbms_resource_manager.create_pending_area();
begin
dbms_resource_manager.create_consumer_group('OLTP_GROUP','Incoming orders');
end;
/
begin
dbms_resource_manager.create_consumer_group('DREPORTS_GROUP','DAYTIME
REPORTS');
end;
/
begin
dbms_resource_manager.create_consumer_group('NIGHT_GROUP','BULK LOADS');
end;
/
begin
dbms_resource_manager.create_consumer_group('REPORTS_GROUP','OFF HOURS
REPORTS');
end;
/
begin
dbms_resource_manager.create_plan
(PLAN => 'OLTP_PLAN', COMMENT => 'ORDER ENTRY SUB-PLAN');
end;
/
-- PLAN DIRECTIVE
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'OFF_HOURS_PLAN',
GROUP_OR_SUBPLAN => 'SYS_GROUP',
COMMENT => 'CPU ALLOCATION FOR SYS_GROUP',
CPU_P1 => 10);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'OFF_HOURS_PLAN',
GROUP_OR_SUBPLAN => 'NIGHT_GROUP',
COMMENT => 'CPU ALLOCATION FOR NIGHTLY JOBS',
CPU_P1 => 5);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'OFF_HOURS_PLAN',
GROUP_OR_SUBPLAN => 'REPORTS_GROUP',
COMMENT => 'CPU ALLOCATION FOR NIGHTLY REPORTS',
CPU_P1 => 2);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'OFF_HOURS_PLAN',
GROUP_OR_SUBPLAN => 'OTHER_GROUPS',
COMMENT => 'CPU ALLOCATION FOR OTHER_GROUPS',
CPU_P1 => 1);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'OLTP_PLAN',
GROUP_OR_SUBPLAN => 'OTHER_GROUPS',
COMMENT => 'CPU ALLOCATION FOR OTHER_GROUPS',
CPU_P2 => 100);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'DAY_PLAN',
GROUP_OR_SUBPLAN => 'OLTP_PLAN',
COMMENT => 'CPU ALLOCATION FOR OLTP_PLAN SUB-PLAN',
CPU_P2 => 100);
end;
/
begin
dbms_resource_manager.create_plan_directive(
PLAN => 'DAY_PLAN',
GROUP_OR_SUBPLAN => 'OTHER_GROUPS',
COMMENT => 'CPU ALLOCATION FOR OTHER_GROUPS',
CPU_P3 => 100);
end;
/
exec dbms_resource_manager.validate_pending_area;
exec dbms_resource_manager.submit_pending_area;
exec dbms_resource_manager.create_pending_area();
begin
dbms_resource_manager.set_consumer_group_mapping(
ATTRIBUTE => dbms_resource_manager.oracle_user,
VALUE => 'U1',
CONSUMER_GROUP => 'NIGHT_GROUP');
end;
/
begin
dbms_resource_manager_privs.grant_switch_consumer_group(
GRANTEE_NAME => 'U1', -- a role name can be given as well
CONSUMER_GROUP => 'NIGHT_GROUP',
GRANT_OPTION => FALSE);
end;
/
begin
dbms_resource_manager_privs.grant_switch_consumer_group(
GRANTEE_NAME => 'U2',
CONSUMER_GROUP => 'REPORTS_GROUP',
GRANT_OPTION => FALSE);
end;
/
begin
dbms_resource_manager.set_consumer_group_mapping(
ATTRIBUTE => dbms_resource_manager.oracle_user, -- it is constant (no
quots)
VALUE => 'U2',
CONSUMER_GROUP => 'REPORTS_GROUP');
end;
/
begin
dbms_resource_manager_privs.grant_switch_consumer_group(
GRANTEE_NAME => 'U3',
CONSUMER_GROUP => 'OLTP_GROUP',
GRANT_OPTION => FALSE);
end;
/
begin
dbms_resource_manager.set_consumer_group_mapping(
ATTRIBUTE => dbms_resource_manager.oracle_user,
VALUE => 'U3',
CONSUMER_GROUP => 'OLTP_GROUP');
end;
/
exec dbms_resource_manager.submit_pending_area;
SET SERVEROUTPUT ON
-- resource directives
select
PLAN,GROUP_OR_SUBPLAN,TYPE,CPU_P1,CPU_P2,CPU_P3,CPU_P4,CPU_P5,CPU_P6,CPU_P7,C
PU_P8,MGMT_P1,MGMT_P2,MGMT_P3,MGMT_P4,MGMT_P5,MGMT_P6,MGMT_P7,MGMT_P8,ACTIVE_
SESS_POOL_P1,QUEUEING_P1,PARALLEL_DEGREE_LIMIT_P1,SWITCH_GROUP,SWITCH_FOR_CAL
L,SWITCH_TIME,SWITCH_IO_MEGABYTES,SWITCH_IO_REQS,SWITCH_ESTIMATE,MAX_EST_EXEC
_TIME,UNDO_POOL,MAX_IDLE_TIME,MAX_IDLE_BLOCKER_TIME,SWITCH_TIME_IN_CALL,COMME
NTS,STATUS,MANDATORY
from DBA_RSRC_PLAN_DIRECTIVES;
-- display the current top level plan and all of its descendent subplans
SELECT NAME, IS_TOP_PLAN FROM V$RSRC_PLAN;
-- for each consumer group in the plan showing the cumulative statistics for
the consumer group.
-- sequence# as as in V$RSRC_PLAN_HISTORY
select
SEQUENCE#,ID,NAME,REQUESTS,CPU_WAIT_TIME,CPU_WAITS,CONSUMED_CPU_TIME,YIELDS,A
CTIVE_SESS_LIMIT_HIT,UNDO_LIMIT_HIT,SWITCHES_IN_CPU_TIME,SWITCHES_OUT_CPU_TIM
E,SWITCHES_IN_IO_MEGABYTES,SWITCHES_OUT_IO_MEGABYTES,SWITCHES_IN_IO_REQUESTS,
SWITCHES_OUT_IO_REQUESTS,SQL_CANCELED,ACTIVE_SESS_KILLED,IDLE_SESS_KILLED,IDL
E_BLKR_SESS_KILLED,QUEUED_TIME,QUEUE_TIME_OUTS,IO_SERVICE_TIME,IO_SERVICE_WAI
TS,SMALL_READ_MEGABYTES,SMALL_WRITE_MEGABYTES,LARGE_READ_MEGABYTES,LARGE_WRIT
E_MEGABYTES,SMALL_READ_REQUESTS,SMALL_WRITE_REQUESTS,LARGE_READ_REQUESTS,LARG
E_WRITE_REQUESTS
from V$RSRC_CONS_GROUP_HISTORY;
select
SEQUENCE#,ID,NAME,REQUESTS,CPU_WAIT_TIME,CPU_WAITS,CONSUMED_CPU_TIME,YIELDS,A
CTIVE_SESS_LIMIT_HIT,UNDO_LIMIT_HIT,SWITCHES_IN_CPU_TIME,SWITCHES_OUT_CPU_TIM
E,SWITCHES_IN_IO_MEGABYTES,SWITCHES_OUT_IO_MEGABYTES,SWITCHES_IN_IO_REQUESTS,
SWITCHES_OUT_IO_REQUESTS,SQL_CANCELED,ACTIVE_SESS_KILLED,IDLE_SESS_KILLED,IDL
E_BLKR_SESS_KILLED,QUEUED_TIME,QUEUE_TIME_OUTS,IO_SERVICE_TIME,IO_SERVICE_WAI
TS,SMALL_READ_MEGABYTES,SMALL_WRITE_MEGABYTES,LARGE_READ_MEGABYTES,LARGE_WRIT
E_MEGABYTES,SMALL_READ_REQUESTS,SMALL_WRITE_REQUESTS,LARGE_READ_REQUESTS,LARG
E_WRITE_REQUESTS
from V$RSRC_CONS_GROUP_HISTORY;
-- resource usage and stats data on currently active resource consumer groups
select
ID,NAME,ACTIVE_SESSIONS,EXECUTION_WAITERS,REQUESTS,CPU_WAIT_TIME,CPU_WAITS,CO
NSUMED_CPU_TIME,YIELDS,QUEUE_LENGTH,CURRENT_UNDO_CONSUMPTION,ACTIVE_SESSION_L
IMIT_HIT,UNDO_LIMIT_HIT,SWITCHES_IN_CPU_TIME,SWITCHES_OUT_CPU_TIME,SWITCHES_I
N_IO_MEGABYTES,SWITCHES_OUT_IO_MEGABYTES,SWITCHES_IN_IO_REQUESTS,SWITCHES_OUT
_IO_REQUESTS,SQL_CANCELED,ACTIVE_SESSIONS_KILLED,IDLE_SESSIONS_KILLED,IDLE_BL
KR_SESSIONS_KILLED,QUEUED_TIME,QUEUE_TIME_OUTS,IO_SERVICE_TIME,IO_SERVICE_WAI
TS,SMALL_READ_MEGABYTES,SMALL_WRITE_MEGABYTES,LARGE_READ_MEGABYTES,LARGE_WRIT
E_MEGABYTES,SMALL_READ_REQUESTS,SMALL_WRITE_REQUESTS,LARGE_READ_REQUESTS,LARG
E_WRITE_REQUESTS,V$RSRC_CONSUMER_GROUP
FROM v$rsrc_consumer_group;
-- resource usage and stats data on currently active resource consumer groups
select
ID,NAME,ACTIVE_SESSIONS,EXECUTION_WAITERS,REQUESTS,CPU_WAIT_TIME,CPU_WAITS,CO
NSUMED_CPU_TIME,YIELDS,QUEUE_LENGTH,CURRENT_UNDO_CONSUMPTION,ACTIVE_SESSION_L
IMIT_HIT,UNDO_LIMIT_HIT,SWITCHES_IN_CPU_TIME,SWITCHES_OUT_CPU_TIME,SWITCHES_I
N_IO_MEGABYTES,SWITCHES_OUT_IO_MEGABYTES,SWITCHES_IN_IO_REQUESTS,SWITCHES_OUT
_IO_REQUESTS,SQL_CANCELED,ACTIVE_SESSIONS_KILLED,IDLE_SESSIONS_KILLED,IDLE_BL
KR_SESSIONS_KILLED,QUEUED_TIME,QUEUE_TIME_OUTS,IO_SERVICE_TIME,IO_SERVICE_WAI
TS,SMALL_READ_MEGABYTES,SMALL_WRITE_MEGABYTES,LARGE_READ_MEGABYTES,LARGE_WRIT
E_MEGABYTES,SMALL_READ_REQUESTS,SMALL_WRITE_REQUESTS,LARGE_READ_REQUESTS,LARG
E_WRITE_REQUESTS,V$RSRC_CONSUMER_GROUP
FROM v$rsrc_consumer_group;
-- how resources were shared among the consumer groups over time
select sequence# seq, name, cpu_wait_time, cpu_waits,
consumed_cpu_time from V$RSRC_CONS_GROUP_HISTORY;
-- sequence# as as in V$RSRC_PLAN_HISTORY
select
SEQUENCE#,ID,NAME,REQUESTS,CPU_WAIT_TIME,CPU_WAITS,CONSUMED_CPU_TIME,YIELDS,A
CTIVE_SESS_LIMIT_HIT,UNDO_LIMIT_HIT,SWITCHES_IN_CPU_TIME,SWITCHES_OUT_CPU_TIM
E,SWITCHES_IN_IO_MEGABYTES,SWITCHES_OUT_IO_MEGABYTES,SWITCHES_IN_IO_REQUESTS,
SWITCHES_OUT_IO_REQUESTS,SQL_CANCELED,ACTIVE_SESS_KILLED,IDLE_SESS_KILLED,IDL
E_BLKR_SESS_KILLED,QUEUED_TIME,QUEUE_TIME_OUTS,IO_SERVICE_TIME,IO_SERVICE_WAI
TS,SMALL_READ_MEGABYTES,SMALL_WRITE_MEGABYTES,LARGE_READ_MEGABYTES,LARGE_WRIT
E_MEGABYTES,SMALL_READ_REQUESTS,SMALL_WRITE_REQUESTS,LARGE_READ_REQUESTS,LARG
E_WRITE_REQUESTS
from V$RSRC_CONS_GROUP_HISTORY;
Using Jobs
• For Batch Files in Windows:
o The OracleJobscheduler service must exist in a running state
o The user who runs this service should have the Logon as batch job privilege
o .bat file cannot be run directly, but should be called as an argument of cmd.exe
-- creating a job
begin
dbms_scheduler.create_job (
job_name => 'Calc_Job',
job_type => 'stored_procedure', -- stored_procedure, plsql_block,
executable, chain
job_action => 'POPULATE_DEPT_SALS',
start_date => SYSDATE, -- or to_date('01-08-2006 17:46','dd-mm-yyyy
hh24:mi'),
repeat_interval => 'FREQ=MINUTELY; INTERVAL=2',
comments => 'Annual Department Salaries');
end;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'update_sales',
job_type => 'STORED_PROCEDURE',
job_action => 'OPS.SALES_PKG.UPDATE_SALES_SUMMARY',
start_date => '28-APR-03 07.00.00 PM Australia/Sydney',
repeat_interval => 'FREQ=DAILY;INTERVAL=2', /* every other day */
end_date => '20-NOV-04 07.00.00 PM Australia/Sydney',
job_class => 'batch_update_jobs',
comments => 'My new job');
END;
/
DECLARE
-- Copying Jobs
-- the new job is created disabled
begin
DBMS_SCHEDULER.COPY_JOB (
old_job =>'MY_OLD_JOB',
new_job =>'MY_NEW_JOB');
end;
-- altering jobs
-- value paramter may be {VARCHAR2|TIMESTAMP WITH TIMEZONE|
-- PLS_INTEGER|BOOLEAN|INTERVAL DAY TO SECOND}
begin
DBMS_SCHEDULER.SET_ATTRIBUTE (
name =>'FULL_BAKCUP',
attribute =>'auto_drop', -- see possible values below
value =>TRUE);
end;
/
-- attribute possible values for JOBS
auto_drop
comments
credential_name credential to use when running an external job
database_role Oracle Data Guard 'PRIMARY' or 'LOGICAL STANDBY'
destination host and port on which to run a remote external job
end_date if no value, the job repeats forever
event_spec
follow_default_timezone
-- stopping a job
-- stop job job1 and all jobs in the job class dw_jobs.
BEGIN
DBMS_SCHEDULER.STOP_JOB('job1, sys.dw_jobs');
END;
/
-- Dropping Jobs
BEGIN
DBMS_SCHEDULER.DROP_JOB ('job1, job3, sys.jobclass1, sys.jobclass2');
END;
/
-- Disabling Jobs
BEGIN
DBMS_SCHEDULER.DISABLE('job1, job2, job3, sys.jobclass1');
END;
/
-- Enabling Jobs
BEGIN
DBMS_SCHEDULER.ENABLE ('job1, job2, job3,sys.jobclass1');
END;
/
Using Programs
176B
-- Creating Programs
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'oe.my_program1',
program_type => 'PLSQL_BLOCK',
program_action => 'BEGIN DBMS_STATS.GATHER_TABLE_STATS(''oe'', ''sales'');
END;',
number_of_arguments => 0,
enabled => TRUE,
comments => 'My comments here');
END;
/
SELECT PROGRAM_NAME FROM DBA_SCHEDULER_PROGRAMS
WHERE PROGRAM_NAME = 'MY_PROGRAM1';
-- Dropping Programs
BEGIN
DBMS_SCHEDULER.DROP_PROGRAM('program1, program2, program3');
END;
/
-- Disabling Programs
BEGIN
DBMS_SCHEDULER.DISABLE (
name => 'ops_reports',
force =>FALSE, -- the default
commit_semantics => 'STOP_ON_FIRST_ERROR'); -- TRANSACTIONAL or
ABSORB_ERRORS
END;
/
-- Enabling Programs
BEGIN
DBMS_SCHEDULER.ENABLE('program1, program2, program3');
END;
/
Using Schedules
-- Creating Schedules
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'my_stats_schedule',
start_date => SYSTIMESTAMP,
end_date => SYSTIMESTAMP + INTERVAL '30' day,
repeat_interval => 'FREQ=HOURLY; INTERVAL=4',
comments => 'Every 4 hours');
END;
/
-- altering schedules
BEGIN
dbms_scheduler.set_attribute(
name => 'my_stats_schedule',
attribute => 'REPEAT_INTERVAL',
value => 'FREQ=HOURLY; INTERVAL=2');
END;
/
attribute:
-- Dropping Schedules
BEGIN
DBMS_SCHEDULER.DROP_SCHEDULE (
schedule_name => 'my_stats_schedule',
force => FALSE); -- DEFAULT
END;
/
Using Windows
179B
-- Creating Windows
begin
dbms_scheduler.create_window (
window_name => 'WORK_HOURS_WINDOW',
resource_plan => 'DAY_PLAN',
start_date => SYSTIMESTAMP, -- also schedule_name can be used
BEGIN
DBMS_SCHEDULER.CREATE_WINDOW (
window_name => 'my_window1',
resource_plan => 'my_res_plan1',
start_date => '15-JUL-03 1.00.00AM US/Pacific',
repeat_interval => 'FREQ=DAILY',
end_date => '15-SEP-03 1.00.00AM US/Pacific',
duration => interval '80' MINUTE,
comments => 'This is my first window');
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_WINDOW (
window_name => 'my_window2',
schedule_name => 'my_stats_schedule',
resource_plan => 'my_resourceplan1',
duration => interval '60' minute,
comments => 'My window');
END;
/
SELECT WINDOW_NAME FROM DBA_SCHEDULER_WINDOWS WHERE WINDOW_NAME =
'MY_WINDOW1';
-- Altering Windows
BEGIN
dbms_scheduler.set_attribute(
name => 'MYWINDOW',
attribute => 'window_priority',
value => 'LOW');
END;
/
ATTRIBUTE:
comments
duration
end_date
repeat_interval
resource_plan
schedule_name
start_date
window_priority
-- openinng a window
begin
dbms_scheduler.open_window (
window_name => 'WORK_HOURS_WINDOW',
duration => INTERVAL '20' MINUTE);
end;
/
-- closing a window
-- dropping a window
BEGIN
DBMS_SCHEDULER.DROP_WINDOW ('window1, window2,
window3, windowgroup1, windowgroup2');
END;
/
-- Disabling Windows
BEGIN
DBMS_SCHEDULER.DISABLE ('sys.window1, sys.window2,
sys.window3, sys.windowgroup1, sys.windowgroup2');
END;
/
-- Enabling Windows
BEGIN
DBMS_SCHEDULER.ENABLE ('sys.window1, sys.window2, sys.window3');
END;
/
-- Window Logging
column log_id format a3
column window_name format a20
column operation format a8
select trim(log_id) log_id, trunc(log_date) log_date,
window_name, operation
from dba_scheduler_window_log
/
begin
DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('LOG_HISTORY','60');
end;
/
declare
n number := 48*60*60;
begin
DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE(
attribute =>'EVENT_EXPIRY_TIME',
begin
DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE('ENQUEUE_ANY','USER1',FALSE);
DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE('DEQUEUE_ANY','USER1',FALSE);
DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE('MANAGE_ANY','USER1',FALSE);
end;
/
-- enable Job
BEGIN
DBMS_SCHEDULER.ENABLE( '"USER1"."U1JOB"' );
END;
/
-- Events are dequeued from the scheduler event queue using the DBMS_AQ
SET SERVEROUTPUT ON
DECLARE
l_dequeue_options DBMS_AQ.dequeue_options_t;
l_message_properties DBMS_AQ.message_properties_t;
l_message_handle RAW(16);
l_queue_msg sys.scheduler$_event_info;
BEGIN
l_dequeue_options.consumer_name := 'USER1';
DBMS_AQ.dequeue(queue_name => 'SYS.SCHEDULER$_EVENT_QUEUE',
dequeue_options => l_dequeue_options,
message_properties => l_message_properties,
payload => l_queue_msg,
msgid => l_message_handle);
COMMIT;
-- remove the job and unsubscribes the user from the scheduler event queue
EXEC DBMS_SCHEDULER.drop_job('"USER1"."U1JOB"')
EXEC DBMS_SCHEDULER.remove_event_queue_subscriber
-- CONNECT AS test_user
-- create type for the message to receive
connect marvin/panic
create or replace type MY_MSGT as object ( msg varchar2(20) )
/
begin
DBMS_AQADM.CREATE_QUEUE_TABLE
( QUEUQ_TABLE=>'MY_QT',
QUEUQ_PAYLOAD_TYPE => 'MY_MSGT',
MULTIPLE_CONSUMERS => TRUE );
DBMS_AQADM.CREATE_QUEUE(
QUEUE_NAME => 'MY_Q',
QUEUE_TABLE => 'MY_QT' );
DBMS_AQADM.START_QUEUE(QUEUE_NAME=>'MY_Q');
end;
/
-- enable Job
BEGIN
DBMS_SCHEDULER.ENABLE( '"TEST_USER"."BCKUP_01"' );
END;
/
DECLARE
my_msgid RAW(16);
props dbms_aq.message_properties_t;
enqopts dbms_aq.enqueue_options_t;
BEGIN
sys.dbms_aq.enqueue('marvin.bckup_q', enqopts, props,
marvin.bckup_msgt('GO'), my_msgid);
end;
/
COMMIT;
BEGIN
DBMS_SCHEDULER.SET_ATTRIBUTE ('entry_events_schedule', 'event_spec',
'tab.user_data.event_type = ''BAD_BADGE''', 'entry_events_q, entry_agent1');
END;
/
Using Chains
183B
-- Creating Chains
BEGIN
DBMS_SCHEDULER.CREATE_CHAIN (
chain_name => 'my_chain1',
rule_set_name => NULL,
evaluation_interval => NULL,
comments => 'My first chain');
END;
/
-- Example: 2
BEGIN
DBMS_SCHEDULER.CREATE_CHAIN (
chain_name => 'my_chain1',
rule_set_name => NULL,
-- Example 3:
BEGIN
DBMS_SCHEDULER.CREATE_CHAIN (
chain_name => 'my_chain2',
rule_set_name => NULL,
evaluation_interval => NULL,
comments => NULL);
END;
/
--- define three steps for this chain.
BEGIN
DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain2', 'step1', 'my_program1');
DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain2', 'step2', 'my_program2');
DBMS_SCHEDULER.DEFINE_CHAIN_STEP('my_chain2', 'step3', 'my_program3');
END;
/
--- define corresponding rules for the chain.
BEGIN
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('my_chain2', 'TRUE', 'START step1');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ( 'my_chain2', 'step1 SUCCEEDED', 'Start
step2');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('my_chain2', 'step1 COMPLETED AND step1
NOT SUCCEEDED', 'Start step3');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('my_chain2', 'step2 COMPLETED OR step3
COMPLETED', 'END');
END;
/
-- Enabling Chains
BEGIN
DBMS_SCHEDULER.ENABLE ('my_chain1');
END;
/
-- Dropping Chains
BEGIN
DBMS_SCHEDULER.DROP_CHAIN (
chain_name => 'my_chain1',
force => TRUE);
END;
/
-- Running Chains
BEGIN
DBMS_SCHEDULER.RUN_CHAIN (
chain_name => 'my_chain1',
job_name => 'quick_chain_job',
start_steps => 'my_step1, my_step2');
END;
/
-- Disabling Chains
BEGIN
DBMS_SCHEDULER.DISABLE ('my_chain1');
END;
/
Repeat the previous step for each database that is to run remote external
jobs on the agent's host.
-- Grant privileges
grant execute on system.hrcrdential to someuser;
Scheduler Privileges
• System Privileges:
o CREATE JOB
o CREATE ANY JOB
o CREATE EXTERNAL JOB
o EXECUTE ANY PROGRAM
o EXECUTE ANY CLASS
o MANAGE SCHEDULER
• Object Privileges: on jobs, programs, chains, schedules and job classes.
o EXECUTE
o ALTER
o ALL
DECLARE
fHandle UTL_FILE.FILE_TYPE;
v_username dba_users.username%TYPE;
CURSOR users IS SELECT username FROM dba_users order by username;
n number := 0;
BEGIN
-- options: r w a
fHandle := UTL_FILE.FOPEN('MYDIR','utlfile.txt','w');
UTL_FILE.PUT_LINE(fHandle,'SN'||CHR(9) || 'User NAME');
UTL_FILE.FCLOSE(fHandle);
/* re-Open the utlfile.txt for append, and get its file handle */
fHandle := UTL_FILE.FOPEN('MYDIR','utlfile.txt','a');
OPEN users;
LOOP
FETCH users INTO v_username;
EXIT when users%NOTFOUND;
n := n + 1;
/* Write a line of text to the file utlfile.txt */
UTL_FILE.PUT_LINE(fHandle,n || chr(9) || v_username);
/* Read a line from the file utltext.txt */
-- UTL_FILE.GET_LINE(fHandle,v_username||v_failed||v_life||v_lock);
END LOOP;
CLOSE users;
UTL_FILE.FCLOSE(fHandle);
EXCEPTION
WHEN UTL_FILE.INVALID_PATH THEN
RAISE_APPLICATION_ERROR(-20100,'Invalid Path');
WHEN UTL_FILE.INVALID_MODE THEN
RAISE_APPLICATION_ERROR(-20101,'Invalid Mode');
WHEN UTL_FILE.INVALID_OPERATION then
RAISE_APPLICATION_ERROR(-20102,'Invalid Operation');
WHEN UTL_FILE.INVALID_FILEHANDLE then
RAISE_APPLICATION_ERROR(-20103,'Invalid Filehandle');
WHEN UTL_FILE.WRITE_ERROR then
RAISE_APPLICATION_ERROR(-20104,'Write Error');
WHEN UTL_FILE.READ_ERROR then
/* Privs */
grant CREATE DATABASE LINK to hr;
/* Private */
CONNECT system/system_passwd@mydb
/* Public */
CREATE PUBLIC DATABASE LINK MONITOR
CONNECT TO hr IDENTIFIED BY hr USING 'monitor';
adrci –help
adrci>help
adrci>show base
adrci>show homes
adrci>show homepath
adrci>set homepath diag\rdbms\ora11g\ora11g
-- spooling
adrci>spool /u01/myfiles/myadrci.txt
adrci> ...
adrci>spool off
-- View Incidents
show incident
show incident –mode detail –p "incident_id=112564"
2. Add diagnostic data to the logical package: this is done by ips add incident command as shown
below:
adrci>ips add incident 112564 package 1
Actually, there are formats of the ips create package command which enables you to perform the
steps 1 and 2 in one command. Following are those command formats:
o ips create package problem
o ips create package problem key
o ips create package incident
o ips create package time
3. Generate the physical package. The files related to the incident will be collected in a ZIP file. The
following example shows the command to perform this task:
adrci>ips generate package 1 in /u01/myfiles/incidents
If you decide to add or change any diagnostic data later, you can do so by generating an incremental
ZIP file. Modify the command as follows to achieve that:
adrci>ips generate package 1 in /u01/myfiles/incidents incremental
You will notice that the generated file has the phase INC in its name indicating that it is an
incremental ZIP file.
ips commands behavior is controlled by various configuration options. To display those configuration
options, use the command ips show configuration.
Use the procedure RUN_CHECK to perform a database health check. Its first parameter CHECKNAME is
mandatory and it takes one of the returned names by the query above.
Most health checks accept input parameters. You can view parameter names and descriptions with the
V$HM_CHECK_PARAM view. Some parameters are mandatory while others are optional. The following query
displays parameter information for all health checks:
select C.NAME CHECK_NAME, P.NAME PARAMETER_NAME, P.TYPE,
P.DEFAULT_VALUE, P.DESCRIPTION
from V$HM_CHECK_PARAM P, V$HM_CHECK C
where P.CHECK_ID = C.ID and C.INTERNAL_CHECK = 'N'
order by C.NAME;
Input parameters are passed to the INPUT_PARAMS argument of the RUN_CHECK procedure as name/value
pairs separated by semicolons (;). The following example illustrates how to pass the transaction ID as a
parameter to the Transaction Integrity Check:
begin
DBMS_HM.RUN_CHECK (
CHECK_NAME => ' Transaction Integrity Check', -- passed value is case
sensitive
RUN_NAME => 'MY_RUN', INPUT_PARAMS => 'TXN_ID=7.33.2');
end;
Database Health checks executions are stored in ADR and can be viewed by either querying the
V$HM_RUN:
SELECT * FROM V$HM_RUN;
You can view a report of a particular Health check by using the following adrci command:
adrci>show report hm_run HM01
Alternatively, you can DBMS_HM package as shown in the following code example:
declare
v_rpt clob;
begin
v_rpt := DBMS_HM.GET_RUN_REPORT('HM01');
end;
Findings, if any, detected by the checks can be obtained from V$HM_FINDING and recommendations from
V$HM_RECOMMENDATION.
RMAN>LIST FAILURE;
RMAN>LIST OPEN;
RMAN>LIST CLOSED;
2. Optionally, execute LIST FAILURE ... DETAIL to list details of an individual failure.
RMAN>LIST FAILURE 105 DETAIL;
3. If you suspect that failures exist that have not been automatically diagnosed by the database, then
run VALIDATE DATABASE to check for corrupt blocks and missing files. If a failure is detected, then
RMAN logs it into the ADR, where it can be accessed by the Data Recovery Advisor.
5. Choose a repair option. You can repair the failures manually or run the REPAIR FAILURE command to
fix them automatically. By default, the REPAIR FAILURE command prompts the user to confirm the
repair, but this can be prevented using the NOPROMPT keyword. Be aware that the previous command
must be issued before using REPAIR FAILURE command.
The following form of the command informs you how RMAN plans to repair the failure:
RMAN>REPAIR FAILURE PREVIEW
6. You may wish to change the priority of a failure (to HIGH or LOW), if it does not represent a problem to
you, or even manually close it. This can be done by the CHANGE FAILURE command:
RMAN> CHANGE FAILURE 202 PRIORITY LOW;
Note Data Recovery Advisor may detect or handle some logical corruptions. But in general,
corruptions of this type require help from Oracle Support Services.
2. Execute the proper form of EXPORT_SQL_TESTCASE procedure. Following is an example using a passed
SQL statement.
DECLARE
V_SQL CLOB := 'SELECT * FROM HR.NAMES WHERE ID BETWEEN 100 AND 1000';
V_TESTCASE CLOB;
BEGIN
DBMS_SQLDIAG.EXPORT_SQL_TESTCASE (
DIRECTORY =>'SQL_TES_DIR',
SQL_TEXT =>V_SQL,
USER_NAME =>'HR',
BIND_LIST =>NULL,
EXPORTENVIRONMENT =>TRUE,
EXPORTMETADATA =>TRUE,
EXPORTDATA =>TRUE,
SAMPLINGPERCENT =>100,
CTRLOPTIONS =>NULL,
TIMELIMIT =>0,
TESTCASE_NAME =>'RETURN_NAMES', -- generated scripts prefix
TESTCASE =>V_TESTCASE);
END;
How to Download It
On metalink, search Patch 6880880.
At document writing, it is on:
https://updates.oracle.com/ARULink/PatchDetails/process_form?patch_num=6880880
Backup Recommendations
It is highly recommended that you back up the ORACLE_HOME before any patch operation. You can use
any method, such as zip, cp -r, tar, and cpio.
lsinventory
It is used to check what is currently installed on the system.
NApply
It is used to apply a set of patches under a directory.
opatch napply <patch_location> -id 1,2,3 -skip_subset -skip_duplicate
This will apply patches 1, 2, and 3 which are under < the patch_location> directory. OPatch will skip
duplicate patches and subset patches (patches under <patch_location> that are subsets of patches
installed in the ORACLE_HOME)
NRollback
It is used to rollback a set of patches installed in an ORACLE_HOME. You can invoke the command using
"opatch nrollback" or "opatch util nrollback".
UpdateRemoteNodes (RAC)
It is used to propagate/remove files/directories to/from remote nodes using files under
ORACLE_HOME/.patch_storage/<ID>/rac/*.
Cleanup
It is used to clean up 'restore.sh, make.txt' files and 'rac, scratch, backup' directories in the
ORACLE_HOME/.patch_storage directory. If -ps option is used, then it cleans the above specified areas
only for that patch, else for all patches under ORACLE_HOME/.patch_storage. You will be still able to
rollback patches after this cleanup.
CopyListedFiles (RAC)
It is used to copy all files listed in ORACLE_HOME/.patch_storage/<ID>/rac/copy_files.txt to remote
nodes. If -fp option is used, then one can specify the path of the file containing the list of files to be
copied. The files mentioned in this file will be copied to the remote nodes.
CopyListedFilesTest (RAC)
It is used to copy a single file to remote nodes. The usage remains the same as CopyListedFiles.
CopyListedDirs (RAC)
It is used to recursively copy all directories listed in
ORACLE_HOME/.patch_storage/<ID>/rac/copy_dirs.txt to remote nodes. If -dp option is used, then one
can specify the path of the file containing the list of directories to be copied. The directories mentioned in
this file will be copied to the remote nodes.
CopyListedDirsTest (RAC)
It is used to copy a single file to remote nodes. The usage remains the same as CopyListedDirs.
RemoveListedFiles (RAC)
It is used to remove files listed in ORACLE_HOME/.patch_storage/<ID>/rac/remove_files.txt on remote
nodes. If -fr option is used, then one can specify the path of the file containing the list of files to be
removed. The files mentioned in this file will be removed from the remote nodes.
RemoveListedFilesTest (RAC)
It is used to remove a single file from remote nodes. The usage remains the same as RemoveListedFiles.
RemoveListedDirs (RAC)
It is used to recursively remove directories listed in
ORACLE_HOME/.patch_storage/<ID>/rac/remove_dirs.txt from remote nodes. If -dr option is used, then
one can specify the path of the file containing the list of directories to be removed. The directories
mentioned in this file will be removed from the remote nodes.
RemoveListedDirsTest (RAC)
It is used to remove a single directory from remote nodes. The usage remains the same as
RemoveListedDirs.
RunLocalMake
It is used to invoke re-link on the local node. The make commands are stored in
ORACLE_HOME/.patch_storage/<ID>/make.txt. You need to use the -ps option to specify the Patch ID
with timestamp. A directory by this name will be present under ORACLE_HOME/.patch_storage. The
make.txt file present under ORACLE_HOME/.patch_storage/Patch ID with timestamp/ will be used to
perform the local make operation. This command cannot be run if you have already run Cleanup as it
would have removed these make.txt files.
RunRemoteMake (RAC)
It is used to invoke re-link on remote nodes. The make commands are stored in
ORACLE_HOME/.patch_storage/<ID>/rac/makes_cmd.txt. The usage remains the same as RunLocalMake.
RunAnyCommand (RAC)
It is used to run any command on remote nodes. The command should be specified using the -cmd option.
Verify
It is used to run the patch verification process to ensure that the patch was applied to the ORACLE_HOME.
It uses the defined ORACLE_HOME and the given patch location via -ph, to run the check.
MAX_USE_SESSION maximum number of times a connection can be taken and released to the
pool.
MAX_SIZE and MIN_SZIE the maximum and minimum number of pooled servers in the connections
pool.
INCRSIZE pool would increment by this number of pooled server when pooled server
are unavailable at application request time.
MAX_THINK_TIME maximum time of inactivity by the client after getting a server from the
pool. If the client does not issue a database call after grabbing a server
from the pool, the client will be forced to relinquish control of the pooled
server and will get an error. The freed up server may or may not be
returned to the pool.
/* Monitor DRCP */
SELECT
STATUS,MINSIZE,MAXSIZE,INCRSIZE,SESSION_CACHED_CURSORS,INACTIVITY_TIMEOUT
FROM DBA_CPOOL_INFO;
-- Handling Queries
string first_name,last_name;
number salary;
resultSet rs = stmt.executeQuery("SELECT * FROM Employees");
while (rs.next()) {
first_name = rs.getString("first_name");
last_name = rs.getString("last_name");
salary = rs.getNumber("salary");
system.out.println(first_name + last_name +" with salary of:" + salary);
}
-- transaction control
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
-- Error Handling
/* Password */
-- ask for a password before executing any admin command
LSNRCTL> set password
LSNRCTL> change_password
#
# HOSTS file
#
win2k3r2 172.16.10.10
Note the IP address – this is the address of a Loopback Adapter installed on the guest machine. As
outlined by the Oracle Installer, a Loopback Adapter is required on systems that do not have a static IP
address (as do virtual machines using NAT, etc.)
Note, before executing this command, ensure that the Oracle instance is running – it has to be in order for
Enterprise Manager Configuration Assistance to drop the repository and de-configure the Console.
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = win2k3r2)(PORT = 1521))
)
)
DEVBOX =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = win2k3r2)(PORT = 1521))
(CONNECT_DATA =
SLA Sample
Standard Processing Services. The Provider shall furnish and allow access to the processing
environments
listed below:
a. Mid-tier processing.
(1) Applications to be processed:
Financial Information Systems (FIS) to include:
LIST OF FIS APPLICATIONS
Other Departmental Applications
(2) Hours of Availability.
Interactive: Monday-Friday* 07:00-17:00*
Saturday, Sunday and Holidays Not Applicable
*Application will be a web-based 24×7×365 system WITH the exception of the
scheduled
maintenance periods (see below)
Batch: Not applicable
Maintenance: Monthly, Fourth Weekend of Every Month
(3) Standard Processing/Service Requirements.
All of the systems/applications listed in paragraph (1) above are required to be
operational 98% of the total time listed in paragraph (2) above. The Information Systems
Department will provide a method for the Department of Finance to monitor operational
percentages.
(4) Processing of data will be limited to the functionality/processing that was being conducted
at the time of handing over the operations to the Information Services Department.
…
List Database failure possible reasons or scenarios and the time required to recover for each
reason.
/* Example 1 */
# you'll have: image copy of the database (L0),
# incremental backup L1
# Archived redo logs between current time and L0
RUN {
# apply L1 to the specified datafile images
RECOVER COPY OF DATABASE WITH TAG 'incr_update';
# create L0 datafile images (first time) then L1
BACKUP INCREMENTAL LEVEL 1 FOR RECOVER OF COPY WITH TAG 'incr_update'
DATABASE;
}
/* Example 2 */
# you'll have image copy of db L0, 3 L1s,
# archived log between current time and L0
# assumption: Size the flash recovery area so it holds three days’ worth of
incremental backups.
RUN
{
RECOVER COPY OF DATABASE TAG "whole_db_copy" UNTIL TIME 'SYSDATE-3';
BACKUP INCREMENTAL LEVEL 1
FOR RECOVER OF COPY WITH TAG "whole_db_copy" DATABASE;
}
#!/bin/ksh
ORACLE_SID=$1
export ORACLE_SID
export ORAENV_ASK=NO
BACKUP_DIR=/u02/app/oracle
. oraenv
sqlplus -s system/mypsswrd << EOF
SET HEAD OFF FEED OFF ECHO OFF TRIMSPOOL ON LINESIZE 200
SPOOL /u01/app/oracle/dba/cold_backup.ksh
SELECT 'cp ' ||file_name|| ' ${BACKUP_DIR}' from sys.dba_data_files;
SELECT 'cp ' ||name || ' ${BACKUP_DIR}' from V$controlfile;
SELECT 'cp ' ||member|| ' ${BACKUP_DIR}' from V$logfile;
SPOOL OFF;
EXIT;
EOF
# 3) open the db
# online
ALTER TABLESPACE sysaux BEGIN BACKUP;
copy datafiles
ALTER TABLESPACE sysaux END BACKUP;
#2)
ALTER DATABASE END BACKUP;
#3)
SELECT * FROM v$backup;
#4)
ALTER DATABASE OPEN;
#(2
copy datafiles, control files and redo log files from backup location into the
original destinations
#(3
STARTUP
#(2
Restore the most recent whole database backup with operating system commands.
#4)
SQL> ALTER DATABASE OPEN RESETLOGS;
#4) if archive redo log file are stored in location different from
log_archive_dest_n:
#4.1) Specifying the location and name at the recover prompt:
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
#4.2)Using the ALTER SYSTEM ARCHIVE command:
SQL> ALTER SYSTEM ARCHIVE LOG START TO <new location>;
#4.3)Using the RECOVER FROM <LOCATION> command:
SQL> RECOVER FROM '<new location>' DATABASE
#4.4)
SQL>SET LOGSOURCE /new_directory
#4.5)
ALTER DATABASE RECOVER FROM '/new_directory';
#7) if required:
ALTER DATABASE OPEN;
3. Place the database in mount mode and insure that the datafiles are online.
SELECT file_id f#, file_name,
tablespace_name tablespace, status
FROM dba_data_files;
5. Open the database by using the RESETLOGS option and verify the recovery.
alter database open resetlogs;
Note: If log files need to be re-created on another disk due to media failure,
use the ALTER DATABASE DROP LOG GROUP and ALTER DATABASE ADD LOG GROUP
commands to create the log files manually.
-- space usage
select NAME, round(SPACE_LIMIT/1024/1024/1024,4) SPACE_LIMIT_GB,
round(SPACE_USED/1024/1024/1024,4) SPACE_USED_GB,
round(SPACE_RECLAIMABLE/1024/1024/1024,4) SPACE_RECLAIMABLE_GB,
NUMBER_OF_FILES
from V$RECOVERY_FILE_DEST;
-- related parameters
DB_CREATE_FILE_DEST = /u02/test/oradata/dbfiles/
LOG_ARCHIVE_DEST_1 = 'LOCATION=/u03/test/arc_dest1'
LOG_ARCHIVE_DEST_2 = 'LOCATION=USE_DB_RECOVERY_FILE_DEST'
-- disable FRA
ALTER SYSTEM SET DB_RECOVERY_FILE_DEST = ''
/* Backup Sets */
select
RECID,
STAMP,
SET_STAMP,
SET_COUNT,
BACKUP_TYPE,
CONTROLFILE_INCLUDED,
INCREMENTAL_LEVEL,
PIECES,
START_TIME,
COMPLETION_TIME,
ELAPSED_SECONDS,
/* Backup Pieces*/
SELECT RECID,
STAMP,
SET_STAMP, -- link to V$BACKUP_SET
SET_COUNT,
PIECE#,
COPY#,
DEVICE_TYPE,
HANDLE,
COMMENTS,
MEDIA,
MEDIA_POOL,
CONCUR,
TAG,
STATUS,
START_TIME,
COMPLETION_TIME,
ELAPSED_SECONDS,
DELETED,
BYTES,
IS_RECOVERY_DEST_FILE,
RMAN_STATUS_RECID,
RMAN_STATUS_STAMP,
COMPRESSED,
BACKED_BY_VSS,
ENCRYPTED,
BACKED_BY_OSB,
FROM V$BACKUP_PIECE
ORDER BY SET_STAMP;
/* Corruption */
-- blocks have been found corrupt during a backup of a backup set
select * from V$BACKUP_CORRUPTION;
Starting RMAN
export ORACLE_SID=mydb
rman target /
#
echo "alias rman2='rlwrap rman'" >> /home/oracle/.bashrc
/* Encryption */
-- Transparent or Dual mode
CONFIGURE ENCRYPTION FOR DATABASE ON
/* Compression */
CONFIGURE DEVICE TYPE DISK BACKUP TYPE TO COMPRESSED BACKUPSET
/* Defining Parallelism */
CONFIGURE DEVICE TYPE DISK PARALLELISM 4;
/* Backup Optimization */
-- datafile of a version identical to its backup won't be backuped up
CONFIGURE BACKUP OPTIMIZATION ON;
/* Backup examples */
-- make a whole database backup
BACKUP DATABASE FORMAT '/tmp/%U' TAG='weekly_bak'
SQL 'ALTER SYSTEM ARCHIVE LOG CURRENT';
-- Backing Up Tablespaces
BACKUP TABLESPACE system, users, tools;
RUN
{
ALLOCATE CHANNEL c1 DEVICE TYPE sbt PARMS="ENV=
(BACKUP_SERVER=tape_server1)";
ALLOCATE CHANNEL c2 DEVICE TYPE sbt PARMS="ENV=
(BACKUP_SERVER=tape_server2)";
BACKUP
(DATAFILE 1,2,3 CHANNEL c1)
(DATAFILECOPY '/tmp/system01.dbf',
'/tmp/tools01.dbf' FILESPERSET = 2 CHANNEL c2)
}
-- to check
list backupset of tablespace tbs1;
Validating Backup
• When you run BACKUP VALIDATE, RMAN checks datafiles for physical and logical block
corruption but it does not actually produce any backup sets or image copies.
# only database level
BACKUP VALIDATE DATABASE ARCHIVELOG ALL;
Incremental Backup
• Level 0 or Level 1.
• Differential: since last 1 or 0, Cumulative: since last 0 (faster recovery).
BACKUP INCREMENTAL LEVEL N [CUMULATIVE]
backup of: DATAFILE, DATAFILECOPY, TABLESPACE, or DATABASE.
BACKUP INCREMENTAL LEVEL 0 ...
BACKUP .. TAG='tag_name'
• The BACKUP ... KEEP command can be used to create a backup that is both all-inclusive
(every file needed including archived redo logs) and exempt from the backup retention
policy.
• In Oracle 11g, some modifications made on the RMAN BACKUP ... KEEP command. In the
new version of the command, the KEEP, NOKEEP, FOREVER, and UNTIL TIME options are
retained. However, the LOGS and NOLOGS options are not there any longer. Instead, you
have a new option, RESTORE POINT. The RESTORE POINT option lets RMAN automatically
create a normal restore point.
Note: You can’t use the KEEP clause for backup files in the flash recovery area. Also, you
cannot use the CHANGE ... KEEP command for backup files stored in the flash recovery area.
RUN
{
ALLOCATE CHANNEL c1 DEVICE TYPE sbt PARMS
'ENV=(OB_MEDIA_FAMILY=archival_backup)';
-- with forever option (recovery catalog is required)
BACKUP DATABASE TAG BAKQ108 KEEP FOREVER RESTORE POINT FY08Q1;
-- backup will be kept for 365 days (long-term)
BACKUP DATABASE TAG BAKQ108 KEEP UNTIL TIME 'SYSDATE+365' RESTORE POINT
FY08Q1;
-- After one day, the backup becomes obsolete,
-- regardless the configured retention policy
• If you want to change the status of a regular backup to an archival backup, use the CHANGE command
as follows:
3. Query the V$SESSION_LONGOPS view to get the status of the backup or copy
VALIDATE BACKUPSET 1;
-- Recover a Tablespace
run{
sql "alter tablespace users offline immediate";
restore tablespace users;
recover tablespace users;
sql "alter tablespace users online"; }
-- Relocate a Tablespace
RUN{
SQL "alter tablespace users offline immediate";
SET NEWNAME FOR DATAFILE '/ORADATA/u03/users01.dbf'
TO '/ORADATA/u04/users01.dbf';
RESTORE TABLESPACE users;
SWITCH datafile 3; # Update the control file and recovery catalog
RECOVER TABLESPACE users; #Recover the tablespace
SQL "alter tablespace tbs1 online";}
3. If using a recovery catalog, register the new incarnation of the database using the command: RESET
DATABASE
Note: Insure that NLS_LANG and NLS_DATE_FORMAT environment variables are set appropriately.
Note: If you need to restore archived redo log files to a new location use the SE SET ARCHIVELOG
DESTINATION TO <location> command.
RMAN>startup nomount
RECOVER DATABASE;
Trial Recovery
• Target: to estimate size of corruption in a recovery process.
• It lets you know whether there is corruption and, if there is, the extent of the corruption.
-- You can use the TEST option for any RECOVER command
RECOVER DATABASE TEST
RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL TEST
RECOVER TABLESPACE users TEST
RECOVER DATABASE UNTIL CANCEL TEST
-- You can limit the number of data blocks trial recovery can corrupt in
memory:
RECOVER DATABASE TEST ALLOW 10 CORRUPTION;
SQL> startup
ORACLE instance started.
..
Database mounted.
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SQL> alter database open noresetlogs;
alter database open noresetlogs
*
ERROR at line 1:
ORA-01588: must use RESETLOGS option for database open
SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01194: file 1 needs more recovery to be consistent
ORA-01110: data file 1: 'C:\ORACLE\ORADATA\MANAGER\SYSTEM01.DBF'
ORA-01152 Error:
----------------
-- resolution: provide the online redo log file to recover
ORA-00289: suggestion :
/u01/app/oracle/admin/finance/arch/finance/_0000012976.arc
ORA-00280: change 962725326 for thread 1 is in sequence #12976
ORA-00278:
logfile'/u01/app/oracle/admin/finance/arch/finance/_0000012975.arc'
no longer needed for this recovery
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01152: file 1 was not restored from a sufficiently old backup
ORA-01110: data file 1: '/pase16/oradata/finance/system_01.dbf'ORA-01112:
media recovery not started
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
/pase04/oradata/finance/redo01a.rdo
ORA-00376 Error:
----------------
reason: might be datafile or tablespace being offline
resolution: bringing the tablespace or datafile online
-- in seconds
ALTER DATABASE SET FAST_START_MTTR_TARGET=60;
advise failure;
repair failure preview;
repair failure;
The V$IR_REPAIR view shows the results of the REPAIR FAILURE command:
select REPAIR_ID,ADVISE_ID,SUMMARY,RANK from V$IR_REPAIR;
RMAN Catalog
3. Grant privileges
GRANT connect, resource, recovery_catalog_owner to rman;
4. Create catalog
rman catalog rman_db1/rman_db1@catdb
RMAN> create catalog tablespace rman_ts;
• Alternatively you can use SQL commands to query the RMAN data dictionary views. Examples of those
view are the following:
RC_DATABASE
RC_DATAFILE
RC_STORED_SCRIPT
RC_STORED_SCRIPT_LINE
RC_TABLESPACE
/* report command */
REPORT SCHEMA
REPORT OBSOLETE;
REPORT NEED BACKUP;
# datafile containing undergone a nologging data (must be backed up)
REPORT UNRECOVERABLE
/* list command */
LIST BACKUP;
LIST BACKUP RECOVERABLE;
LIST COPY;
LIST ARCHIVELOG ALL;
LIST SCRIPT NAMES;
LIST GLOBAL SCRIPT NAMES;
LIST INCARNATION;
-- upgrade steps
1) If the recovery catalog owner that you created is from a release before
10.1, execute the following
GRANT command (assuming that rman is the catalog owner):
SQL> GRANT CREATE TYPE TO rman;
2) Start RMAN and connect to the recovery catalog database.
RMAN> connect catalog rman/rman;
3) Execute the UPGRADE CATALOG command.
RMAN> UPGRADE CATALOG;
In Oracle Database 11g, you can restrict access to the recovery catalog by granting access to only a
subset of the metadata in the recovery catalog. The subset that a user has read/write access to is termed
as virtual private catalog, or just virtual catalog. The central or source recovery catalog is now called the
base recovery catalog.
Following are the steps to create a new private catalog for the database user SCOTT:
# grant the role RECOVERY_CATALOG_OWNER to the user
SQL>GRANT RECOVERY_CATALOG_OWNER TO scott;
# in RMAN session, connect as the base catalog owner
RMAN>CONNECT CATALOG rman/rman@mydb
RMAN>GRANT CATALOG FOR DATABASE db1, db2 TO SCOTT;
# connect as the granted user (virtual catalog onwer) and create the virtual catalog
RMAN>CONNECT CATALOG scott/lion@mydb
RMAN>CREATE VIRTUAL CATALOG;
# make sure only granted dbs are seen
RMAN>LIST INCARNATION;
If the catalog is to be used for releases pre-Oracle 11g clients, in the SQL*Plus log on as the virtual
private catalog owner and run the following procedure, where "rman" is the name of the base catalog
owner:
SQL> CONN scott/lion@mydb
SQL> EXEC rman.DBMS_RCVCAT.CREATE_VIRTUAL_CATALOG;
The virtual catalog owner must have the SYSDBA and SYSOPER privileges on the traget database, to
perform most of the RMAN operations on it.
Following are examples of removing the privileges from a virtual catalog owner:
# To remove recovery catalog access to a database from a user:
RMAN>CONNECT CATALOG RMAN/RMAN@MYDB;
RMAN>REVOKE CATALOG FOR DATABASE db1 FROM scott;
# To revoke the ability to register new databases from a virtual private catalog owner:
RMAN>REVOKE REGISTER DATABASE FROM scott;
# To revoke both the catalog and register privileges from a user:
RMAN>REVOKE ALL PRIVILEGES FROM scott;
Caution When the DROP CATALOG command is issued by the virtual catalog owner, all the metadata
pertaining to it is deleted from the base recovery catalog.
# create script
CREATE SCRIPT nightly_backup {
ALLOCATE CHANNEL c1 TYPE DISK;
BACKUP DATABASE FORMAT '/u01/app/oracle/%u';
SQL 'ALTER DATABASE BACKUP CONTROLFILE TO TRACE';
}
# run it
RUN {EXECUTE SCRIPT nightly_backup;}
# update a script
REPLACE SCRIPT full_backup { ..
# delete a script
DELETE SCRIPT 'my-script';
• A duplicate database is a copy of your target database with a new, unique database
identifier (DBID).
-Add the auxiliary database service to the listener configuration file in the
source server:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = ora11g)
(ORACLE_HOME = C:\app\Administrator\product\11.1.0\db_1)
(SID_NAME = ora11g)
)
(SID_DESC =
(GLOBAL_DBNAME = ora11g2)
(ORACLE_HOME = C:\app\Administrator\product\11.1.0\db_1)
(SID_NAME = ora11g2)
)
)
-- You may want to increase the parallelism setting of your source database
disk channels
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 ;
in source
RUN {
ALLOCATE CHANNEL c1 DEVICE TYPE DISK FORMAT 'C:\oracle\stagingbackups\%U';
BACKUP AS COPY DATABASE;
BACKUP AS COPY CURRENT CONTROLFILE FORMAT
'C:\oracle\stagingbackups\control01.ctl';
}
OR
RUN {
ALLOCATE CHANNEL c1 DEVICE TYPE DISK FORMAT 'C:\oracle\stagingbackups\%U';
BACKUP COPY OF DATABASE ;
BACKUP AS COPY CURRENT CONTROLFILE FORMAT
'C:\oracle\stagingbackups\control01.ctl';
}
- Manually transfer the backups in the new directory on the source host to the
identically named directory on the destination host.
- in source:
-- check parameters containing folder info:
col value format a35
col name format a30
select NAME, VALUE FROM v$parameter where upper(value) like '%C:\%';
OR
select NAME, VALUE FROM v$parameter
where name in
- in destination:
-Create a password file in the destination server:
orapwd FILE=C:\oracle\oracledb11g\database\PWDora11g2.ora PASSWORD=ora11g
ENTRIES=10 ignorecase=n
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = ora11g2.pc02)
(ORACLE_HOME = C:\oracle\oracledb11g)
(SID_NAME = ora11g2)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = PC02)(PORT = 1521))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
-- You may want to increase the parallelism setting of your source database
disk channels
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 ;
Change DB name:
db_domain
db_name
2. Prepare a text file for the creation of a control file for the new database
as follows:
- in prod
SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
Modify as required the parameters below, include them in the parameter file
and create their folders:
Note: if you define diagnostic_dest, you don't have to create its sub-
directories
audit_file_dest='C:\ORACLE\ADMIN\ORA11G2\ADUMP'
audit_trail='DB'
compatible='11.1.0.0.0'
control_files='C:\ORACLE\ORADATA\ORA11G2\CONTROL01.CTL'
control_files='C:\ORACLE\ORADATA\ORA11G2\CONTROL02.CTL'
control_files='C:\ORACLE\ORADATA\ORA11G2\CONTROL03.CTL'
db_block_size=8192
db_domain='pc02'
db_name='ora11g2'
db_recovery_file_dest='C:\oracle\flash_recovery_area'
db_recovery_file_dest_size=4048M
diagnostic_dest='C:\ORACLE'
dispatchers='(PROTOCOL=TCP) (SERVICE=ora11gXDB)'
log_buffer=5654016 # log buffer update
memory_target=620M
open_cursors=400
optimizer_dynamic_sampling=2
optimizer_mode='ALL_ROWS'
plsql_warnings='DISABLE:ALL' # PL/SQL warnings at init.ora
processes=400
query_rewrite_enabled='TRUE'
remote_login_passwordfile='EXCLUSIVE'
result_cache_max_size=2112K
sessions=390
skip_unusable_indexes=TRUE
undo_tablespace='UNDOTBS1'
LOG_ARCHIVE_FORMAT=ARC%S_%R.%T
DB_UNIQUE_NAME="ora11g2"
LOG_ARCHIVE_DEST_10='LOCATION=USE_DB_RECOVERY_FILE_DEST'
8. Execute:
ALTER DATABASE OPEN RESETLOGS;
9. Execute:
ALTER DATABASE RENAME GLOBAL_NAME TO ora11g2.pc02;
ALTER SYSTEM REGISTER;
• Row Level:
o Flashback Query
o Flashback Versions Query
o Flashback Transaction Query
o Flashback Transaction Backout
• Table level:
o Flashback Table
o Flashback Drop
o Flashback Data Archive (FDA)
• Database level:
o Flashback Database
-- must be AUTO
show parameter UNDO_MANAGEMENT
Flashback Query
-- if the user isn't the owner
GRANT FLASHBACK ON employees TO scott;
GRANT FLASHBACK ANY TABLE TO scott;
/* using DBMS_FLASHBACK */
-- set the specified point in time in the past
select ... -- the output will be as of current time
EXECUTE DBMS_FLASHBACK.ENABLE_AT_TIME (TO_TIMESTAMP '11-DEC-2008 10:00:00',
'DD-MON-YYYY hh24:MI:SS');
select ... -- the output will be as of the set time
EXECUTE DBMS_FLASHBACK.DISABLE ();
/* using it */
SELECT to_char(start_timestamp,'dd-Mon hh24:mi'), operation, undo_sql
FROM flashback_transaction_query
WHERE start_timestamp >= TO_TIMESTAMP ('2009-11-09 05:00:00', 'YYYY-MM-DD
HH:MI:SS')
AND table_owner='HR' AND table_name='EMPLOYEES'
order by start_timestamp desc;
-- required privs
grant EXECUTE on DBMS_FLASHBACK to hr;
grant SELECT ANY TRANSACTION to hr;
Flashback Table
• ROW MOVEMENT must be enabled in advance and before flashback recovery time.
• Generates undo and redo data
• Syntax:
FLASHBACK TABLE [schema.]table [,[schema.]table] ... TO {SCN|TIMESTAMP} expr
• By default, Oracle disables all relevant triggers and reenables them upon completing the
table recovery.
• Several restrictions apply:
o You can’t flash back a table to a time preceding any DDL operation involving a change
in table structure.
o If the flashback operation involves multiple tables, all of the tables must be flashed
back or none.
-- required privs
grant FLASHBACK ANY TABLE to hr;
grant FLASHBACK on hr.employees to hr;
-- SELECT, INSERT, DELETE, and ALTER privileges on the table to be flashed
back are required
Flashback Drop
• When table is dropped, its dependents' names will also renamed by system generated
names.
• If a table is undropped, the cryptic system-generated names of the dependents remain.
-- user level
SELECT * FROM RECYCLEBIN;
SHOW RECYCLEBIN
-- purge a table(s)
DROP TABLE table_name PURGE;
PURGE TABLE int_admin_emp;
PURGE TABLE BIN$jsleilx392mk2=293$0;
PURGE TABLESPACE users;
PURGE TABLESPACE users USER scott;
PURGE RECYCLEBIN;
-- purge all objects in the db
PURGE DBA_RECYCLEBIN;
-- dropping FDA:
DROP FLASHBACK ARCHIVE myflash;
-- in mount level
ALTER DATABASE FLASHBACK ON;
ALTER DATABASE OPEN;
-- to switch it on again:
ALTER TABLESPACE users FLASHBACK ON;
/* Flashback db in action */
-- flashback db to a past time
STARTUP MOUNT;
FLASHBACK DATABASE TO SCN 5964663;
FLASHBACK DATABASE TO SEQUENCE 12345;
FLASHBACK DATABASE TO TIMESTAMP(SYSDATE -1/24);
-- You can flash back to just before the last RESETLOGS operation by :
FLASHBACK DATABASE TO SCN 5964663 TO BEFORE RESETLOGS;
-- you can check the data before open resetlogs
ALTER DATABASE OPEN READ ONLY;
-- open resetlogs
ALTER DATABASE OPEN RESETLOGS;
/* Assissted commands */
-- current scn
SELECT current_scn FROM V$DATABASE;
Restore Points
• Guaranteed restore points use a separate logging mechanism from the Flashback logging
used for a Flashback Database operation.
• However, if you use a guaranteed restore point and Flashback Database is enabled, Oracle
won’t delete any Flashback logs and thus FRA will eventually become full.
• Turning off Flashback Database if you’re using guaranteed restore points.
• Set the UMASK variable to 022 to the Oracle software OS user owner.
• Remove the SETUID on all Oracle files.
• Unless needed, remove mentions to EXTPROC in both the listener.ora file on the server
and the tnsnames.ora file on the client. Then remove all EXTPROC executables from your
$ORACLE_HOME/bin directory ( usually extproc and xtproc0). If needed, refere to
Document ID 175429.1 in metalink.
• Set a password to the listener. Secure the linstener.ora file.
ADMIN_RESTRICTIONS=ON
• You may use Server-side Access Controls in the sqlnet.ora file as follows:
REMOTE_OS_AUTHENT=FALSE
-- disable
INSERT INTO SYSTEM.PRODUCT_USER_PROFILE(PRODUCT,userid,attribute,char_value)
VALUES('SQL*Plus','TESTER','ROLES','TEST123');
-- enable
DELETE FROM product_user_profile WHERE userid='TESTER'
AND char_value = 'TEST123';
-- creating user
CREATE USER user1 IDENTIFIED BY urs1754
TEMPORARY TABLESPACE TEMPTBS01
DEFAULT TABLESPACE user1ts
QUOTA 500M ON user1ts
PROFILE 'SALES_RPOF';
-- dropping user
DROP USER user1;
DROP USER user1 cascade;
REVOKE CREATE SESSION FROM user1;
Managin Passwords
select value from v$parameter where name='sec_case_sensitive_logon';
-- dynamic
alter system set sec_case_sensitive_logon=false ;
/* password file */
select value from v$parameter where upper(name)='REMOTE_LOGIN_PASSWORDFILE';
SELECT * FROM v$pwfile_users;
sqlplus /
Proxy Authentication
-- to authorize connections by a database user logging on from
-- a middle-tier node, using password authentication.
ALTER USER user1
GRANT CONNECT THROUGH appserv
AUTHENTICATED USING PASSWORD;
-- on Windows
-- 1. obain thread #
SELECT sid, spid as thread, osuser, s.program
FROM v$process p, v$session s
WHERE p.addr = s.paddr;
-- kill the process using orakill utiliy
orakill 2948
/* object privs */
GRANT DELETE ON bonuses TO hr WITH GRANT OPTION;
GRANT UPDATE (product_id) ON sales01 TO hr;
GRANT SELECT, UPDATE ON emp_view TO PUBLIC;
GRANT SELECT ON oe.customers_seq TO hr;
GRANT ALL ON EMPLOYEES TO hr;
GRANT EXECUTE ON employee_pkg TO hr;
GRANT QUERY REWRITE TO hr;
GRANT READ ON DIRECTORY bfile_dir TO hr;
-- incorrect
REVOKE UPDATE (hostname) ON ods_process FROM hr;
-- correct
REVOKE UPDATE ON ods_process FROM hr;
Roles
• Predefined roles:
-- create role
CREATE ROLE new_dba;
/* Role Authorization */
-- (1) Database authorization
CREATE ROLE clerk IDENTIFIED BY password;
-- (2) Database authorization with a PL/SQL package
-- the role is enabled by a hr.admin package:
CREATE ROLE admin_role IDENTIFIED USING hr.admin;
-- (3) Externally
CREATE ROLE accts_rec IDENTIFIED EXTERNALLY;
-- (4) Globally: enabled by an enterprise directory service
CREATE ROLE supervisor IDENTIFIED GLOBALLY;
-- Dropping a Role
DROP ROLE admin_user;
-- Column-Level VPD
-- You can apply column-level VPD to a table or a view
Standard Auditing
• Set AUDIT_TRAIL to: NONE (default), OS, DB (SYS.AUD$), DB_EXTENDED (SYS.AUD$ +
the columns SQLBIND and SQLTEXT CLOB), XML (in OS), 'XML, EXTENDED'.
• If you set AUDIT_TRAIL to DB, change the tablespace of SYS.AUD$ from SYSTEM.
• Audited info:
o Operating system login
o Database username
o Terminal and session identifiers
o Operation performed or attempted
o Date and time stamp
o SQL text that triggered the auditing
select value from v$parameter where name='audit_trail';
-- if not defined: $ORACLE_HOME/rdbms/audit/
select value from v$parameter where name='audit_file_dest';
-- AUDIT focused by
-- DB/user
-- success/failure and
-- grouped by session or access
audit session ;
AUDIT SESSION BY hr;
AUDIT select table BY hr BY SESSION;
AUDIT DELETE ANY TABLE BY hr WHENEVER NOT SUCCESSFUL;
AUDIT UPDATE ANY TABLE;
AUDIT SELECT,INSERT,UPDATE,DELETE ON employees BY ACCESS WHENEVER SUCCESSFUL;
AUDIT ALL PRIVILEGES;
/* flushing db audit */
CONN / AS SYSDBA
DELETE FROM SYS.AUD$;
BEGIN
-- ** generate the target Audit Table
-- create sequence
INSERT_VW('CREATE SEQUENCE SEQ_'|| P_TABLE || '_AUDIT ;');
INSERT_VW('CREATE TABLE '|| P_TABLE || '_AUDIT (');
INSERT_VW('ID NUMBER CONSTRAINT '|| P_TABLE || '_AUDIT_ID PRIMARY KEY,');
-- N Columns
FOR R IN ( SELECT
TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH,DATA_PRECISION,DATA_SCALE FROM
USER_TAB_COLUMNS WHERE TABLE_NAME = UPPER(P_TABLE) ) LOOP
IF R.DATA_TYPE = 'NUMBER' AND R.DATA_PRECISION IS NULL THEN
INSERT_VW( 'N' || R.COLUMN_NAME || ' NUMBER ,');
V_NCOL_LIST := V_NCOL_LIST || 'N' || R.COLUMN_NAME || ',';
V_NCOL_LIST2 := V_NCOL_LIST2 || ' :NEW.' || R.COLUMN_NAME || ',';
ELSIF R.DATA_TYPE = 'NUMBER' AND R.DATA_PRECISION IS NOT NULL AND
R.DATA_SCALE = 0 THEN
INSERT_VW( 'N' || R.COLUMN_NAME || ' NUMBER('|| R.DATA_PRECISION ||'),');
V_NCOL_LIST := V_NCOL_LIST || 'N' || R.COLUMN_NAME || ',';
V_NCOL_LIST2 := V_NCOL_LIST2 || ' :NEW.' || R.COLUMN_NAME || ',';
/* Examples */
-- DDL triggers
/* BEFORE / AFTER ALTER
BEFORE / AFTER ANALYZE
BEFORE / AFTER ASSOCIATE STATISTICS
BEFORE / AFTER AUDIT
BEFORE / AFTER COMMENT
BEFORE / AFTER CREATE
BEFORE / AFTER DDL
BEFORE / AFTER DISASSOCIATE STATISTICS
BEFORE / AFTER DROP
BEFORE / AFTER GRANT
BEFORE / AFTER NOAUDIT
BEFORE / AFTER RENAME
BEFORE / AFTER REVOKE
BEFORE / AFTER TRUNCATE
AFTER SUSPEND */
CREATE OR REPLACE TRIGGER ddl_log_trig
AFTER DDL ON DATABASE
BEGIN
INSERT INTO ddl_log
(username, change_date, object_type, object_owner, database, event_name )
VALUES
(ORA_LOGIN_USER, sysdate, ora_dict_obj_type, ora_dict_obj_owner,
ora_database_name, ora_sysevent)
END;
/
-- Disable granting privileges to PUBLIC
CREATE OR REPLACE TRIGGER ddl_trig
BEFORE GRANT
ON DATABASE
DECLARE
g_list DBMS_STANDARD.ORA_NAME_LIST_T;
n PLS_INTEGER;
BEGIN
n := ORA_GRANTEE(g_list);
FOR i IN 1..n LOOP
IF g_list(i) = 'PUBLIC' THEN
RAISE_APPLICATION_ERROR(-20997,'Public Grants Not Allowed');
END IF;
END LOOP;
END;
/
-- System Errors
CREATE TABLE servererror_log (
error_datetime TIMESTAMP,
error_user VARCHAR2(30),
db_name VARCHAR2(9),
error_stack VARCHAR2(2000),
captured_sql VARCHAR2(1000));
-- required priv
grant execute on DBMS_FGA to hr;
-----
-- Show Fine-Grained Auditing results so far
-- the view is based on SYS.FGA_LOG$
-----
TTITLE 'Current Fine-Grained Auditing (FGA) Results'
COL audit_date FORMAT A10 HEADING 'Audit|Date'
COL policy_name FORMAT A16 HEADING 'Policy Name' WRAP
COL object_schema FORMAT A10 HEADING 'Object|Schema'
COL object_name FORMAT A20 HEADING 'Object Name' WRAP
COL db_user FORMAT A10 HEADING 'DBUser'
COL sql_text FORMAT A36 HEADING 'SQL Text' WRAP
SELECT
TO_CHAR(timestamp,'dd/mm/yyyy hh24:mi:ss') audit_date
,db_user
,object_schema
,object_name
-----
-- Use the new combined audit trail view (DBA_COMMON_AUDIT_TRAIL)
-- to see results of both Standard (i.e. AUDIT) and Fine-Grained
-- Auditing (i.e. via DBMS_FGA)
-----
COL audtype FORMAT A03 HEADING 'Aud|Typ'
COL db_user FORMAT A10 HEADING 'DBUser'
COL object_schema FORMAT A06 HEADING 'Object|Schema'
COL object_name FORMAT A20 HEADING 'Object Name' WRAP
COL policy_name FORMAT A16 HEADING 'Policy Name' WRAP
COL audit_date FORMAT A10 HEADING 'Audit|Date'
COL sql_text FORMAT A32 HEADING 'SQL Text' WRAP
SELECT
DECODE(audit_type,
'Fine Grained Audit', 'FGA'
,'Standard Audit', 'STD'
,'UNK') audtype
,db_user
,object_schema
,object_name
,policy_name
,TO_CHAR(extended_timestamp,'mm/dd/yyyy hh24:mi:ss') audit_date
,sql_text
FROM dba_common_audit_trail
WHERE db_user NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN')
ORDER BY extended_timestamp, db_user, object_schema, object_name;
-----
BEGIN
DBMS_FGA.ADD_POLICY(
object_schema => 'AP' -- if null, logon user schema
,object_name => 'VENDORS'
,policy_name => 'VENDORS_LO'
,audit_condition => 'ACTIVE_IND <> ''Y''' -- if NULL=TRUE
,audit_column => 'ACTIVE_IND,CREDIT_CARD,CREDIT_LIMIT'
,handler_schema => NULL
,handler_module => NULL -- the procedure will fire on audit
,enable => TRUE -- default is TRUE
,statement_types => 'SELECT'
,audit_trail => DBMS_FGA.DB_EXTENDED
,audit_column_opts => DBMS_FGA.ANY_COLUMNS -- or DBMS_FGA.ALL_COLUMNS
);
END;
/
BEGIN
DBMS_FGA.ADD_POLICY(
object_schema => 'AP'
,object_name => 'RV_INVOICE_DETAILS'
,policy_name => 'RV_INVOICE_LO'
,audit_condition => NULL
,audit_column =>
'VENDOR_NAME,INVOICE_ID,EXTENDED_AMT,VENDOR_CREDIT_LIMIT'
,handler_schema => NULL
,handler_module => NULL
,enable => FALSE
,statement_types => 'SELECT'
/*
|| Listing 1.5: FGA Policy Maintenance
*/
BEGIN
-----
-- Disabling an enabled, existing FGA policY
-----
DBMS_FGA.DISABLE_POLICY(
object_schema => 'AP'
,object_name => 'INVOICES'
,policy_name => 'INVOICES_HI'
);
-----
-- Dropping an enabled, existing FGA policY
-----
DBMS_FGA.DROP_POLICY(
,policy_name => 'RV_INVOICE_LOW'
,object_name => ' RV_INVOICE_DETAILS'
,policy_name => 'RV_INVOICE_LO'
);
END;
/
/* Setting up TDE */
-- 1. Create the Wallet file:
-- add the following to the sqlnet.ora
ENCRYPTION_WALLET_LOCATION =
(SOURCE=
(METHOD=file)
(METHOD_DATA=
(DIRECTORY=C:\oracle\OraDb10g\admin\ora10g\wallet)))
-- To Test TDE
SELECT
DBMS_ROWID.ROWID_TO_ABSOLUTE_FNO (ROWID,USER,'EMP'),
DBMS_ROWID.ROWID_BLOCK_NUMBER (ROWID)
Tablespace Encryption
In Oracle Database 11g, you can encrypt an entire tablespace.
Caution Losing the master key or the wallet file will lead to losing the data in the encrypted
tablespace.
Encrypting a Tablespace
Create and open a wallet file, as explained in the previous section.
The tablespace creation statement for an encrypted tablespace has the following syntax:
CREATE TABLESPACE <tbsp_name> ...
[ENCRYPTION [USING <ALGORITHM>]] -- specify encryption algorithm
DEFAULT STORAGE(ENCRYPT) -- encrypt objects in the tablespace
To know whether an existing tablespace is encrypted or not, issue the following query:
select vt.NAME, vet.ENCRYPTIONALG, vet.ENCRYPTEDTS
from V$ENCRYPTED_TABLESPACES vet, V$TABLESPACE vt
where vet.TS#=vt.TS#
Oracle Database 11g provides a mechanism to refine the level of access to the network
access packages UTL_TCP, UTL_SMTP, UTL_MAIL, UTL_HTTP, and UTL_INADDR.
Creating ACL
You can use the DBMS_NETWORK_ACL_ADMIN package to facilitate management of the UTL_*
network access packages as in the following steps:
1) Create an Access Control List (ACL): All ACL definitions are stored in XML DB in the form of
XML documents. The ACL XML files reside in the /sys/acls directory of the XML DB
repository. Following is an example of using the CREATE_ACL procedure to create an XML
file called dba.xml:
begin
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
ACL => 'dba.xml', -- case sensitive
DESCRIPTION=> 'Network Access Control for the DBAs',
PRINCIPAL => 'SCOTT', -- user or role the privilege is granted or denied
(upper case)
IS_GRANT => TRUE, -- privilege is granted or denied
PRIVILEGE => 'connect', -- or 'resolve' (case sensitive)
START_DATE => null, -- when the access control entity ACE will be valid
END_DATE => null); -- ACE expiration date (TIMESTAMP WITH TIMEZONE format)
end;
Regarding the PRIVILEGE parameter, the database user needs the connect privilege to an
external network host computer if he or she is connecting using the UTL_TCP, UTL_HTTP,
UTL_SMTP, and UTL_MAIL utility packages. To resolve a host name that was given as a host IP
address, or the IP address that was given as a host name, with the UTL_INADDR package,
grant the database user the resolve privilege.
You can then query the RESOURCE_VIEW view to find the dba.xml ACL in the /sys/acls
directory:
select ANY_PATH
from RESOURCE_VIEW
where ANY_PATH LIKE '/sys/acls/dba%'
Too may entries in the ACL may lead to significant XML DB performance drop because ACL
are checked for each access to Oracle XML DB repository. As general rule of thumb, ACL
check operations perform best when the number of ACEs in the ACL is at 16 entries or less.
2) Add Access Control Entries: Once you create the initial ACL, you can continue to add more
privileges to the XML file. The following example will add the user RAMI to the dba.xml file
and grant him network access:
begin
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE (
ACL => 'dba.xml',
PRINCIPAL => 'RAMI',
IS_GRANT => TRUE,
In ACL, the security entries are evaluating in order precedence. If you have two contradicting
entries in the list, the first one in the order will take effect. You can control the order number
of an added entry as follows:
begin
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE (
POSITION => 1, -- on the top
ACL => 'dba.xml', PRINCIPAL => 'SAMI',
IS_GRANT => FALSE, PRIVILEGE => 'connect',
START_DATE => null, END_DATE => null);
end;
3) Assign Hosts: The ASSIGN_ACL procedure is used to authorize access to one or more
network hosts as follows:
begin
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL (
ACL => 'dba.xml', HOST => 'dbaexpert.com',
LOWER_PORT => 80, UPPER_PORT => 443);
end;
COMMIT;
The lower port and the upper port define the lower and the upper boundaries of the allowable
port range. They should be set for connect privileges not resolve privileges.
4) Validate that the ACL permissions worked accordingly. Following is an example to test the
code in the previous step.
If the sufficient ACL privileges or ACL assignments are not provided, you will receive the ORA-
24247 error.
Use the DROP_ACL procedure to remove the XML file from the /sys/acls directory as follows:
exec DBMS_NETWORK_ACL_ADMIN.DROP_ACL ( ACL=>'dba.xml' );
You can query the DBA_NETWORK_ACL_PRIVILEGES view to query network privileges granted or
denied for the access control list as follows:
select PRINCIPAL, PRIVILEGE, IS_GRANT
from DBA_NETWORK_ACL_PRIVILEGES
where ACL like '%dba.xml'
Logged on users can use the following query to see their access entries in the dba.xml file:
Managing OS Statistics
• CPU Statistics:
o doesn't exceed 95% in total.
o check DB share on CPU
• Virtual Memory Statistics:
o validate that memory usage does not increase after the system has reached a
steady state after startup.
• Disk I/O Statistics:
o current response time should be between 5 to 20 ms for a single block IO
o the length of the disk queues shouldn't exceed two.
• Network Statistics:
o Look at the network round-trip ping time and the number of collisions. Investigate
it, if the network is causing large delays in response time.
-- all stats
select STAT_NAME, VALUE, OSSTAT_ID, COMMENTS, CUMULATIVE
from V$OSSTAT;
/* CPU */
-- one-hour history of the Host CPU Utilization
select BEGIN_TIME, END_TIME, GROUP_ID, METRIC_ID, METRIC_NAME, VALUE, METRIC_UNIT
from V$SYSMETRIC_HISTORY
where METRIC_NAME LIKE '%Host CPU%'
/* io tuning */
-- IO related waits
select
EVENT,
TOTAL_WAITS_FG,
TOTAL_TIMEOUTS_FG,
TIME_WAITED_FG,
AVERAGE_WAIT_FG,
WAIT_CLASS,
TOTAL_WAITS,
TOTAL_TIMEOUTS,
TIME_WAITED,
AVERAGE_WAIT
from
V$SYSTEM_EVENT
WHERE WAIT_CLASS = 'User I/O'
order by WAIT_CLASS;
-- io stats
select
FILE_NO,
FILETYPE_NAME,
SMALL_READ_MEGABYTES "Single-block MegaBytes Reads",
SMALL_WRITE_MEGABYTES "Single-block MegaBytes Writes",
SMALL_READ_REQS "Single-block Read Requests",
SMALL_WRITE_REQS "Single-block Write Requests",
SMALL_READ_SERVICETIME "Total S-Block Read Time",
SMALL_WRITE_SERVICETIME "Total S-Block Write Time",
-- decode(SMALL_READ_REQS,0,0,SMALL_READ_SERVICETIME/SMALL_READ_REQS) "Per S-
Block Read Response T",
SMALL_SYNC_READ_REQS,
SMALL_SYNC_READ_LATENCY "S-Block Sync Read Latency (ms)",
LARGE_READ_MEGABYTES "Multi-block MegaBytes Reads",
LARGE_WRITE_MEGABYTES "Multi-block MegaBytes Writes",
LARGE_READ_REQS "Multi-block Read Requests",
LARGE_WRITE_REQS "Multi-block Write Requests",
LARGE_READ_SERVICETIME "Total M-Block Read Time",
LARGE_WRITE_SERVICETIME "Total M-Block Write Time",
ASYNCH_IO,
RETRIES_ON_ERROR
from V$IOSTAT_FILE
order by FILE_NO
/
-- Datafiles IO History
SELECT
f.snap_id,
f.filename,
f.phyrds reads,
f.phywrts wrts,
(f.readtim / decode(f.phyrds,0,-1,f.phyrds))/10 ReadRespoinseTime_ms,
(f.writetim / decode(f.phywrts,0,-1,phywrts))/10 WriteRespoinseTime_ms,
SINGLEBLKRDTIM/10 Single_Block_ReadTime_ms,
wait_count, time waittime
FROM DBA_HIST_FILESTATXS f
ORDER BY f.snap_id desc, filename
/* on Windows */
--Performance Monitor tool
/* on Unix */
/* CPU */
# process per second
sar -c 2 10 -- for all CPUs without interval, since last reboot
sar -c –P 0 -- for first CPU
# CPU% utilization
sar -u 4 5
# alternatively
vmstat -s | grep "cpu ticks"
# CPU% utilization
iostat –c
iostat 4 5 –c -- 5 times every 4 seconds
sar –r
sar -W
-- Active and inactive pages: you shouldn't have too few inactive memory pages:
vmstat -S M
# alternatively:
vmstat -s -S M | grep "memory"
sar –r
sar –R
# rtps wtps read/write requests per second issued to the physical disk
# bread/s bwrtn/s data read/write from the drive in blocks per second
sar –b 5 10
# bloc device usage
# number of sectors (512 byte) read/written per second
# if avque is greater larger than 1, disk contention is there
sar -d
/* Network Statistics */
# ping and check the latency
ping ...
/* Session stats */
select
T.SID,S.USERNAME, S.MACHINE, S.MODULE, S.ACTION,
N.NAME,
decode(N.CLASS,
'1','User','2','Redo','4','Enqueue','8','Cache','16','OS','32','RAC','64','SQL','1
28','Debug', N.CLASS) STAT_CLASS,
VALUE
from V$SESSTAT T, V$STATNAME N, V$SESSION S
WHERE T.STATISTIC#=N.STATISTIC# and T.SID=S.SID
and S.USERNAME NOT IN ('SYSTEM','SYS','DBSNMP','SYSMAN')
/* SQL Stats */
high buffer gets = using the wrong index, the wrong driving table in a join, or a
similar SQL-related error
buffer gets and disk reads are at identical levels = a missing index
-- top io consumers
SELECT executions, buffer_gets, disk_reads, rows_processed,SORTS, sql_text
FROM V$SQL
WHERE buffer_gets > 100000 OR disk_reads > 100000
ORDER BY buffer_gets + 100*disk_reads DESC;
Wait Events
• The wait events are only the symptoms of problems, most likely within the application
code.
• After defining the troubled waiting event, you can get further info by tracing the suspected
session.
-- TIMED_STATISTICS must be true (default)
/* WAIT EVENTS */
-- waite events in the instance:
-- Top Wait Classes By Instance Total
-- AWR reports could also assist you
select
WAIT_CLASS,
TIME_WAITED, round(TIME_WAITED/TOT_WAIT*100,2) TIME_WAITED_PCT, TIME_WAITED_FG,
round(TIME_WAITED_FG/TOT_WAIT*100,2) TIME_WAITED_FG_PCT
from V$SYSTEM_WAIT_CLASS, (select sum(TIME_WAITED) TOT_WAIT from
V$SYSTEM_WAIT_CLASS where WAIT_CLASS <>'Idle'),
(select sum(TIME_WAITED_FG) TOT_WAIT_FG from V$SYSTEM_WAIT_CLASS where WAIT_CLASS
<>'Idle')
where WAIT_CLASS <>'Idle'
order by TIME_WAITED_FG_PCT DESC
-- if buffer busy was on the top waits, get more info about
-- block contention statistics
select CLASS, TIME, COUNT
from V$WAITSTAT
order by TIME desc
-- ASH report
-- info about the SQL that ran during the time you specify
$ORACLE_HOME/rdbms/admin/ashrpt.sql
The ashrpti.sql lets you specify the db instance
-- Top Waits
SELECT a.event,
SUM(a.wait_time + a.time_waited) total_wait_time
FROM v$active_session_history a
WHERE a.sample_time between
sysdate - 30/2880 and sysdate
GROUP BY a.event
ORDER BY total_wait_time DESC;
Segment Statistics
• You drill down into segment stats from the instance, sessions or ASM wait stats.
select OWNER, OBJECT_TYPE, OBJECT_NAME, TABLESPACE_NAME, STATISTIC_NAME, VALUE
from V$SEGMENT_STATISTICS
-- WHERE statistic_name='buffer busy waits'
order by value desc;
select *
FROM V$DB_OBJECT_CACHE
order by loads desc;
-- statement reloads
SELECT namespace, pins, pinhits, reloads
FROM V$LIBRARYCACHE
ORDER BY namespace;
/* Setting CURSOR_SPACE_FOR_TIME */
If CURSOR_SPACE_FOR_TIME=TRUE, you ensure that the cursors for the application
cannot be deallocated while the application cursors are still open. It will then
eliminate the Oracle’s overhead to check whether the cursor is flushed from the
library cache.
It will result in increase in the shared pool memory.
/* Setting SESSION_CACHED_CURSORS */
It ensures that for any cursor for which more than three parse requests are made,
the parse requests are automatically cached in the session cursor cache. It avoids
high soft parse.
Good to use in Forms-based apps.
ALTER SESSION SET SESSION_CACHED_CURSORS = value;
If the value of session cursor cache hits is low compared to the total parse count
for a session, then the SESSION_CACHED_CURSORS parameter value should be increased
(also good to make it larger than OPEN_CURSORS):
Tuning PGA
-- PGA stats
SELECT NAME, VALUE, UNIT FROM V$PGASTAT
-- Package specification
CREATE OR REPLACE PACKAGE department_pks IS
-- Function declaration
FUNCTION get_dept_info (dept_id NUMBER) RETURN dept_info_record RESULT_CACHE;
END department_pks;
exec DBMS_RESULT_CACHE.BYPASS(FALSE);
-- using DBMS_RESULT_CACHE
-- check the status of the Result Cache
-- Note: this is the reliable method to know whether result cache is enabled or
not
SQL>select DBMS_RESULT_CACHE.STATUS from dual;
-- blocking session
select ADDR, KADDR, l.SID, s.USERNAME, S.MACHINE, S.TERMINAL, S.PROGRAM,
decode(l.TYPE, 'TM','DML enqueue','TX','Transaction enqueue','UL','User supplied')
Block_Type,
ID1, ID2, LMODE, REQUEST, CTIME, BLOCK
from v$lock l, v$session s
where s.sid = l.sid
and l.block=1;
• The AWR and ADDM are Oracle products that need special licensing through the purchase
of the Diagnostic Pack.
-- To manually creating a snapshot:
dbms_workload_repository.create_snapshot()
/* Monitoring AMT */
SELECT client_name, status,
attributes, window_group,service_name
FROM dba_autotask_client;
begin
dbms_auto_task_admin.disable
(client_name => 'sql tuning advisor',
operation => 'automatic sql tuning task',
window_name => 'monday_window');
end;
/
-- recommendations
select * from DBA_ADVISOR_RECOMMENDATIONS where task_name='ADDM 01012009';
DBA_ADVISOR_SQLPLANS
-- in a specific window
begin
dbms_auto_task_admin.enable (
client_name => 'sql tuning advisor',
operation => 'NULL',
window_name='monday_night_window');
end;
/
When you configure the database to use MEMORY_TARGET, you should take into consideration
the following:
• The parameter STATISTICS_LEVEL must be set to TYPICAL
• If you set the parameters SGA_TARGET and PGA_TARGET, Oracle will consider the values
as the minimum values for SGA and PGA.
• If you do not set the parameters SGA_TARGET and PGA_TARGET (or set them to zero), no
minimum value is considered by Oracle for the SGA and PGA. When the instance starts, it
assigns 60 percent to SGA and 40 percent to the PGA.
• When MEMORY_TARGET is configured, the following components are auto tuned: DB
BUFFER CACHE, SHARED POOL, JAVA POOL, LARGE POOL and STREAMS POOL.
Note On Linux systems, if you receive the following error after setting the MEMORY_TARGET parameter,
most likely the reason is that the /dev/shm is allocated a size (can be known by issuing the
command df -k) less than SGA_MAX_SIZE:
ORA-00845: MEMORY_TARGET not supported on this system.
-- dynamic parameter
ALTER SYSTEM SET MEMORY_TARGET = 410M ;
-- To know how Oracle has modified the memory area sizes by time, issue the
following query:
select START_TIME, END_TIME, STATUS, COMPONENT, OPER_TYPE, OPER_MODE,
PARAMETER, INITIAL_SIZE/1024/1024 INITIAL_SIZE_MB,
TARGET_SIZE/1024/1024 TARGET_SIZE_MB, FINAL_SIZE/1024/1024 FINAL_SIZE_MB
from V$MEMORY_RESIZE_OPS
order by START_TIME, END_TIME
-- instance level:
ALTER SYSTEM SET optimizer_mode = first_rows_10;
-- statement level
select /*+ first_rows(10) */ ..
SELECT /*+ ALL_ROWS */ ...
Joins:
• Nested Loop Join (USE_NL, No_USE_NL): for every row in the outer table, Oracle accesses
all the rows in the inner table.
• Hash Join (USE_HASH, NO_USE_HASH): used when joining one large table with a small
one. The smaller data source is built into memory as hash table. It then scans the larger
table, probing the hash table to find the joined rows. Euality condition is a must.
• Sort Merge (USER_MERGE, NO_USE_MERGE): It performs well when no order is required
on the data source (or already sorted) and the join condition is NOT equality.
• Outer Joins: extends the result of a simple join:
o Nested Loop Outer Joins: The outer table will be the one with rows that are
being preserved.
o Hash Join Outer Joins
o Sot Merge Outer Joins
o Full Outer Join
• Cartesian: two or more tables with no joins.
/* Access Path Hinst */
-- Full Table Scans
select /* FULL(table_alias) */
-- Bitmap Index
-- bitmap indexes should be there
SELECT /*+ INDEX_COMBINE(e emp_manager_ix emp_department_ix) */ *
FROM employees e
WHERE (manager_id = 108) OR (department_id = 110);
-- Cluster
CREATE CLUSTER sc_srvr_id (
srvr_id NUMBER(10)) SIZE 1024;
-- Hash
CREATE CLUSTER sthc_si (srvr_id NUMBER(10))
SIZE 1024 SINGLE TABLE HASHKEYS 11
TABLESPACE uwdata;
-- Sample data
-- SAMPLE (1) : read 1% of rows
-- SAMPLE BLOCK (1) : read 1% of blocks
SELECT * FROM employees SAMPLE BLOCK (1);
-- Nested Loops
select /*+ use_nl(e d) use_nl(e j) */ -- or No_use_nl
employee_id , department_name, salary, j.job_title
from employees e , departments d, jobs j
where e.department_id = d.department_id
and e.job_id = j.job_id
and d.department_id>10
/
-- Hash Join
SELECT /*+ USE_HASH(o l) */
o.customer_id, l.unit_price * l.quantity
FROM orders o ,order_items l
WHERE l.order_id = o.order_id;
-- col stats
select OWNER, TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, LOW_VALUE, HIGH_VALUE,
DENSITY, NUM_NULLS, NUM_BUCKETS, LAST_ANALYZED, SAMPLE_SIZE, GLOBAL_STATS,
USER_STATS, AVG_COL_LEN, HISTOGRAM
from DBA_TAB_COL_STATISTICS
where owner not in
('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN','TSMSYS','WMSYS','EXFSYS','CTXSYS','
XDB','ORDSYS','MDSYS','OLAPSYS','WKSYS','WK_TEST','IX')
and owner NOT LIKE 'FLOWS_%'
order by OWNER, LAST_ANALYZED DESC;
SET SERVEROUTPUT ON
declare
v_value varchar2(100);
begin
v_value := DBMS_STATS.GET_PREFS (
PNAME =>'STALE_PERCENT',
• If the OWNNAME and TABNAME are provided and a preference has been entered for the table, the
function returns the preference as specified for the table. In all other cases it returns the global
preference if it has been specified, otherwise the default value is returned.
Similarly, the procedures DELETE_*_PREFS are used to delete current statistics preferences.
EXPORT_*_PREFS and IMPORT_*_PREFS procedures are used to export and import statistics preferences.
Following is an example:
begin
DBMS_STATS.EXPORT_DATABASE_PREFS(
STATTAB =>'mytable', -- table name to where statistics should be exported
STATID =>'prod_prefs', -- identifier to associate with these statistics
STATOWN =>'HR'); -- Schema containing stattab (if other than ownname)
end;
You can check whether or not the statistics will be automatically published checking the value of the
PUBLISH attribute using the DBMS_STATS package as in the following example:
SELECT DBMS_STATS.GET_PREFS('PUBLISH') PUBLISH FROM DUAL;
You can change the PUBLISH setting at either the schema or table level. Following are examples to do so:
-- setting PUBLISH at schema level
exec DBMS_STATS.SET_SCHEMA_PREFS('HR', 'PUBLISH', 'FALSE');
-- setting PUBLISH at table level
exec DBMS_STATS.SET_TABLE_PREFS('HR','EMPLOYEES', 'PUBLISH', 'FALSE');
Published statistics are stored in data dictionary views, such as DBA_TAB_STATISTICS and USER_IND_
STATISTICS. Pending statistics are stored in views such as DBA_TAB_PENDING_STATISTICS and
DBA_IND_PENDING_STATISTICS.
select NUM_ROWS, BLOCKS, AVG_ROW_LEN, SAMPLE_SIZE, LAST_ANALYZED
from DBA_TAB_PENDING_STATISTICS where OWNER='HR' AND TABLE_NAME ='EMPLOYEES';
By default, the optimizer uses the published statistics stored in the data dictionary views. If you want the
optimizer to use the newly collected pending statistics, set the initialization parameter
The optimizer will use the pending statistics (if available) instead of the published statistics when
compiling SQL statements. If the pending statistics are valid, they can be made public by executing the
following statement:
-- for the whole database
exec DBMS_STATS.PUBLISH_PENDING_STATS(null, null);
-- publishing specific database object pending statistics
exec DBMS_STATS.PUBLISH_PENDING_STATS('HR','EMPLOYEES');
If you do not want to publish the pending statistics, delete them by executing the following statement:
exec DBMS_STATS.DELETE_PENDING_STATS('HR','EMPLOYEES');
MultiColumn Statistics
When multiple columns from a single table are used together in the where clause of a query (multiple
single column predicates), Oracle optimizer in previous versions (before 11g) does not understand the
relationship between the columns. In Oracle 11g, statistics on these columns as a group (column group)
can be gathered and thus resulting in high enhancement in CBO cardinality estimation.
You can also create column groups manually by using the CREATE_EXTENDED_STATS function in the
DBMS_STATS package. This function creates a column statistics entry in the system for a user specified
column group or an expression in a table. This function returns a system-generated name of this newly
created entry for the extension.
Note: The optimizer will only use MultiColumn statistics with equality predicates.
Following is an example:
declare
V_NAME VARCHAR2(30);
begin
-- stats of the combined columns will be collected next time the stats is gathered
V_NAME := DBMS_STATS.CREATE_EXTENDED_STATS(
OWNNAME => NULL,
TABNAME => 'EMPLOYEES',
EXTENSION => '(STATE_ID,COUNTRY_ID)');
-- you can then issue the gathering process
DBMS_STATS.GATHER_TABLE_STATS (NULL, 'EMPLOYEES', METHOD_OPT='for all columns size
skewonly' );
end;
The DBMS_STATS.GATHER_TABLE_STATS procedure can also be used to create column group and gather its
statistics all in one step. The keyword FOR COLUMNS is used in this case as shown in the following
example:
begin
DBMS_STATS.GATHER_TABLE_STATS ('HR', 'EMPLOYEES',
METHOD_OPT=>'for all columns size skewonly for columns (STATE_ID,COUNTRY_ID)' );
end;
You can use the methods in the following code examples to retrieve information on column groups that
have been created:
-- you can query the data dictionary USER_STAT_EXTENSIONS
select EXTENSION_NAME, EXTENSION from USER_STAT_EXTENSIONS where TABLE_NAME='EMPLOYEES';
-- you can query USER_TAB_COL_STATISTICS (extension name appears as COLUMN_NAME)
select COLUMN_NAME, NUM_DISTINCT, HISTOGRAM
from USER_TAB_COL_STATISTICS where TABLE_NAME = 'EMPLOYEES';
-- you can use DBMS_STATS.SHOW_EXTENDED_STATS_NAME function
select DBMS_STATS.SHOW_EXTENDED_STATS_NAME(OWNNAME => 'HR',
TABNAME => 'EMPLOYEES',
EXTENSION => 'STATE_ID,COUNTRY_ID') AS E_NAME
from dual;
After gathering the multi-column statistics as show in the example, when you check the explain plan for a
query of a where condition like "STATE_ID = 'CA' AND COUNTRY_ID = 'US'", you will notice that the
optimizer has retrieved the correct number of expected retrieved rows. Practically, this will lead to a
significant improvement in the statement execution.
Following is how to drop a column group that you have previously defined:
exec DBMS_STATS.DROP_EXTENDED_STATS('HR', 'EMPLOYEES', '(STATE_ID,COUNTRY_ID)');
Expression Statistics
In Oracle 11g, you can create statistics on an expression. Following are examples to do that:
declare
V_NAME VARCHAR2(30);
begin
-- to create expression extended stats (not statistics are yet gathered)
V_NAME := DBMS_STATS.CREATE_EXTENDED_STATS(
OWNNAME => NULL,
TABNAME => 'EMPLOYEES',
EXTENSION => '(lower(last_name))');
end;
begin
-- to create expression extended stats and gather the statistics in one step
DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>NULL,TABLE_NAME=>'EMPLOYEES',
METHOD_OPT=>'for all columns size skewonly for columns (lower(last_name))');
end;
After executing the code above, if you issue a query from EMPLOYEES table with a condition like
LOWER(LAST_NAME)='ABC', the optimizer has statistics about the retrieved rows and thus will be able to
estimate the correct number of returned rows. Consequently, the optimizer will most likely create a more
efficient plan than if those statistics were not present.
Use the DBA_STAT_EXTENSIONS data dictionary view to retrieve information on expression statistics that
have been created in the database.
select EXTENSION_NAME, EXTENSION from USER_STAT_EXTENSIONS where TABLE_NAME='EMPLOYEES';
Note that you will not be able to drop an extended expression statistics, if a function-based index is
dependent on that statistic (ORA-20000 error will be returned).
begin
sys.dbms_session.set_sql_trace(true);
end;
/
-- specific session
exec DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(SID=>123, SERIAL#=>567, SQL_TRACE=>
true);
exec DBMS_MONITOR.SESSION_TRACE_ENABLE(session_id => 27, serial_num => 60,
waits => TRUE, binds => FALSE);
3. Run TKPROF to translate the trace file into a readable output file and
optionally create a SQL script that can be used to store the statistics in a
database.
tkprof finance_ora_16340.trc test.txt sys=no explain=y AGGREGATE =yes|no WAITS
=yes|no
-- not recommended
-- Setting the 10046 Event For a Session Other than Your Own
-- Method 1
-- SPID known (OR next)
oradebug setospid 1864;
-- PID known
oradebug setpid 21;
-- then
oradebug event 10046 trace name context forever, level 12
oradebug event 10046 trace name context off
-- Method 2
Dbms_system.set_ev (
si binary_integer, -- SID
se binary_integer, -- Serial#
ev binary_integer, -- Event code or number to set.
le binary_integer, -- Usually level to trace
cm binary_integer -- When to trigger (NULL = context forever.)
To disable tracing:
DBMS_MONITOR.CLIENT_ID_STAT_DISABLE(<Client_id>)
DBMS_MONITOR.SERV_MOD_ACT_TRACE_DISABLE('APPS1')
DBMS_MONITOR.DATABASE_TRACE_DISABLE(INSTANCE_NAME=>'RAC1')
You can then run TKPROF against the consolidated trace file to generate a
report:
tkprof hr_report.trc output=hr_trc_report sys=np SORT=(EXEELA, PRSELA, FCHELA)
-- it can be rewritten as
..
WHERE ...
AND somecolumn BETWEEN :loval AND :hival
AND (:hival != 'ALL' AND :loval != 'ALL')
UNION ALL
..
WHERE ...
AND (:hival = 'ALL' OR :loval = 'ALL');
• If possible, define the Join Order using ORDERED or STAR hints. Table with the lowest
percentage of retireved compared to its tolad it candidate to be the driving table.
-- in this example, a is the driving table.
SELECT info
FROM taba a, tabb b, tabc c
WHERE a.acol BETWEEN 100 AND 200
AND b.bcol BETWEEN 10000 AND 20000
AND c.ccol BETWEEN 10000 AND 20000
AND a.key1 = b.key1
AND a.key2 = c.key2;
UPDATE employees
SET job_id ='SA_MAN', salary = salary + 1000,
department_id = 140
WHERE last_name = 'Jones'
RETURNING salary*0.25, last_name, department_id
INTO :bnd1, :bnd2, :bnd3;
• Consider using Test Case Builder.
• Consider using Bitmap Join Indexes on a star model query.
• Selecting the Best Join Order: If you’re joining three tables, the one with the more
restrictive filter (driving table) should be joined first (after the FROM keyword) to one of the
other two tables.
-- this statement is less efficient than the following one
select /*+ ordered */
order_date, order_total, line_item_id id, product_name ,quantity,
quantity*unit_price item_tprice
from order_items i, PRODUCT_INFORMATION p, orders o
where
order_date between to_date('01-01-2010','dd-mm-yyyy') and to_date('31-03-
2010','dd-mm-yyyy') and
o.order_id=i.order_id and
i.product_id=p.product_id;
-- more efficient
select /*+ ordered */
order_date, order_total, line_item_id id, product_name ,quantity,
quantity*unit_price item_tprice
from orders o, order_items i, PRODUCT_INFORMATION p
where
order_date between to_date('01-01-2010','dd-mm-yyyy') and to_date('31-03-
2010','dd-mm-yyyy') and
o.order_id=i.order_id and
i.product_id=p.product_id;
Following are the tips to improve SQL processing, even if you cannot change the code:
• Using Partitioned Tables
• Using Compression Techniques
CREATE INDEX item_product_x
ON order_items(product_id)
TABLESPACE order_items_indx_01
COMPRESS;
CREATE INDEX item_product_x
ON order_items(product_id)
TABLESPACE order_items_indx_01 COMPRESS;
• Using Materialized Views
• Using Stored Outlines to Stabilize the CBO (and SQL Plan Management in Oracle 11g).
• Using Parallel Execution
BEGIN
DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'my_sql_tuning_task' );
END;
/
-- asm files
select * from V$ASM_FILE;
LSNRCTL STATUS
in the pfile:
ASM_DISKGROUPS=dgroup1
restart
-- rebalancing speed
show parameter ASM_POWER_LIMIT
ALTER DISKGROUP dgroup1 REBALANCE POWER 5;
SQL>
ALTER DISKGROUP dgroup1 ADD
FAILGROUP controller1 DISK 'c:\asmdisks\asmdiska3'
FAILGROUP controller2 DISK 'c:\asmdisks\asmdiskb3'
/
/* Checking Diskgroup */
-- 11g: you can validate the internal consistency of ASM diskgroup metadata.
Summary of errors is logged in the ASM alert log file.
-- check specific diskgroup with automatic repair
SQL>ALTER DISKGROUP data CHECK;
-- disable automatic repair
SQL>ALTER DISKGROUP data CHECK NOREPAIR;
SQL>ALTER DISKGROUP data CHECK REPAIR;
• disk_repair_time in units of minute (M) or hour (H) and is set by the ALTER DISKGROUP command
Variable AU Sizes
The default size of Allocation Unit (AU) is 1 MB which is sufficient for most regular databases. However,
when you have databases with TB sizes, you will have enormous number of AUs. With Oracle 11g, AU
size can be specified at diskgroup creation time to 1, 2, 4, 8, 16, 32, or 64MB in size. You can check the
AU size through the following query:
COMPATIBLE The compatible initialization parameter can be set for either ASM or the database
initialization instance. It takes one of the following values: 10.1, 10.2, or 11.1.
parameter
Setting the initialization parameter to a lesser value than the software release will
exclude availability of the new features introduced in the new release.
If you assign any of the compatibility setting to a higher value, you cannot later reverse it to a lower
value.
Following are some queries to obtain information about the compatibility settings:
The ALTER DISKGROUP DROP, RESIZE, and REBALANCE commands return before the operation is
complete. To monitor progress of these long-running operations, you can query the V$ASM_OPERATION
fixed view.
GROUP_NUMBERDisk group
OPERATION Type of operation: REBAL
STATE State of operation: QUEUED or RUNNING
POWER Power requested for this operation
ACTUAL Power allocated to this operation
SOFAR Number of allocation units moved so far
EST_WORK Estimated number of remaining allocation units
EST_RATE Estimated number of allocation units moved per minute
EST_MINUTES Estimated amount of time (in minutes) for operation termination
set oracle_sid=ora11g
/* Method 2 */
- Edit your listener.ora and add an entry for the ASM instance in the SID_LIST
(SID_DESC =
(GLOBAL_DBNAME = My_DB_SID)
(ORACLE_HOME=d:\oracle\product\10.2.0\db_2)
(SID_NAME = +ASM)
)
- Fill in the required fields and press continue (it won´t do anything yet.
It´s just the first step, to get ASM listen as a new OEM target).
- If it ever complains about ORA-1017, you need to recreate the ASM instance
paswordfile. Take a backup of it first if you feel better so.
The syntax for recreating the passwordfile can be, for example:
orapwd file=D:\oracle\product\10.2.0\db_2\database\PWD+ASM.ora
password=my_password force=y
(of course, you must replace the password and the path with the one that
serves your needs)
Now, you only need to: click on the "Database" link on the right top of the DB
Console window, or access the DB Console page again. You should see the ASM
target link below the listener target. You only need to click the link and
you´ll get the ASM home administration page, from DBConsole.
If ASM hyperlink is not directly shown in the main DBconsole page, you can
still click on the Host name link in the left of the DBConsole main page (just
over the listener name link), and once there, again click in the "Targets"
You also have the option of directly typing the following URL, after the ASM
target is created:
http://your_DB_hostname:your_DBConsole_port/em/console/database/osm/osmSitemap
?type=osm_instance&target=%2BASM_your_DB_hostname&event=doLoad
If the backup file already exists, you should remove it before issuing the command.
If you issue the md_backup command without any option, it creates a file named as
ambr_backup_intermediate_file which contains the metadata information of all the mounted
diskgroups.
newdg create disk group with a different name and restore metadata; -o is required. This tag is
used to allow the user to change diskgroup name.
-f write SQL commands to <sql_script_file> instead of executing them.
-o override option is used only with the newdg option to remap the diskgroup name, disk name,
paths, and failure groups.
-i ignore errors. By default, the command aborts when it encounters an error.
-l log all messages to a log file.
# To just restore the metadata for the dg1 diskgroup (the diskgroup already
exists).
md_restore –b /tmp/backupfile –t nodg –g dg1 –i
# To apply the override options as specified in the dg_over.txt file and restore
# from the backup file:
md_restore –b /tmp/backupfile –t newdg –of /tmp/dg_override.txt –i
/* Scenario Example */
1. Back up a tablespace exising in a disk group:
RMAN> BACKUP TABLESPACE users;
2. Create a directory named test in the disk group DGROUPA. Also create an alias
called
+DGROUPA/test/users.f that points to the ASM datafile that contains the users
tablespace:
ASMCMD> mkdir +DGROUPA/test
ASMCMD> mkalias TBSSRA.123.123456789 +DGROUPA/test/users.f
3. Back up the metadata for the disk group DGROUPA using the md_backup command:
ASMCMD> md_backup –g dgroupA
The md_backup command stores the backup metadata in the text file named
ambr_backup_
intermediate in the current directory.
4. Simulate a disk failure by dropping the disk group DGROUPA:
SQL> ALTER DISKGROUP dgroup1 DISMOUNT FORCE;
SQL> DROP DIKSGROUP dgroup1 FORCE INCLUDING CONTENTS;
Note that md_backup is a backup of the metadata of the ASM instance. The data is being backed up by
RMAN. After the diskgroup is created, along with all the directories, you can restore the RMAN backup to
the diskgroup.
This feature introduces a new SYSASM privilege that is specifically intended for performing ASM
administration tasks. Using the SYSASM privilege instead of the SYSDBA privilege provides a clearer division
of responsibility between ASM administration and database administration.
Following are code examples illustrating how to use this privilege:
-- grant the privilege
GRANT SYSASM TO firas;
Be aware that users with SYSOPER privilege have some ASM privileges. Following table shows available
and restricted ASM privilege for users with SYSOPER privilege:
Avaiable ASM Privilege Restricted ASM Privilege
STARTUP AND SHUTDOWN CREATE DISKGROUP / DISK
ALTER DISKGROUP MOUNT DROP DISKGROUPS / DISKS
ALTER DISKGROUP DISMOUNT ALTER DISKGROUP / DISK RESIZE
ALTER DISKGROUP ONLINE DISK
ALTER DISKGROUP OFFLINE DISK
ALTER DISKGROUP REBALANCE
ALTER DISKGROUP CHECK
OSASM is a new operating system group that is used exclusively for ASM. Members of the OSASM group
can connect as SYSASM using operating system authentication and have full access to ASM.
6. If you are upgrading a ASM instance in a RAC environments, you can modify the new ASM home
within the OCR using the srvctl utility as follows:
srvctl modify asm -n racnode1 -i +ASM1 -o /apps/oracle/product/11.1.0/asm -p
init+ASM1.ora
8. If you have obsolete initialization parameters, you can address them now. To get a listing of all the
obsolete initialization parameters, refer to the ASM alert log file.
Installation Environment
• Emulation software: VMWare Workstation ACE Edition 6.0.5 or VMWare Server 2.
• RAC Nodes: 2 nodes with 2 GB RAM each , 2 ethernet cards.
• OS: Oracle Linux Enterprise 4.5 for x86: kernel 2.6.9
Required Software
• Oracle 10g R2 Clusterware for Linux x86 32-bit
• Oracle Database 10g Release 2 for Linux x86 32-bit
Used Hardware
• In the VMWare: create one virtual machine (rac1) with the following specs:
o 2 GB RAM
o two ethernet cards: both can be configured as bridged or host-only in VMware.
o one local hardisk with 20 GB
o CPU Count: 2
o create a folder in the same directory structure level as the parent folder containing the
created virtual machine. Give it a meaningful name like 'shared_disks'. Create in that
folder three disks of 10 GB and two of 512 MB. All of them are of LSI Logic type and
SCISI Persistent.
Installation Plan
1. Preinstallation tasks:
o Hardware requirements
o Software requirements
o Environment configuration
2. Oracle Clusterware installation
3. Oracle Database 10g Software Installation
4. Apply Patchset 3 (10.2.0.4) for Clusterware and Database Software
5. Install EM Agent in cluster nodes (if required)
6. Configure Listeners
7. Perform ASM installation
8. Perform cluster database creation
9. Complete postinstallation tasks
# from CD 3
rpm -Uvh libaio*
rpm -Uvh openmotif21-2.1.30-11.RHEL4.6.i386.rpm
rpm -Uvh openmotif-2.2.3-10.1.el4.i386.rpm
Note: To prevent network hangs with failovers from public to virtual IP addresses with
RAC databases using NAS devices or NFS mounts, enter the following command as root to
enable the Name Service Cache Daemon: /sbin/service nscd start
• Create and configure the required OS users and groups
Note: userid and groupid must be the same in all nodes. You can check them by id
oracle command.
# all group and user ids on all the nodes must have identical id
# inventory and OSDBA groups (if needed, use -g <number> to specify the id)
# inventory group
• Create the required directories for the Oracle clusterware and database software
# to know if there is an existing oracle inventory
# from its output, ORACLE_BASE will be parent of oraInventory
more /etc/oraInst.loc
# to identify existing Oracle home directories
more /etc/oratab
• Start rac1
• Configure ASM drivers:
# as root ( on ALL NODES )
service oracleasm configure
vi /etc/hosts.equiv
# add node names to /etc/hosts.equiv (all nodes)
rac1
rac2
# as oracle in node1
# whenever prompted for a passphrase leave it empty and press return
mkdir ~/.ssh
chmod 700 ~/.ssh
/usr/bin/ssh-keygen -t rsa
# as oracle in node2
mkdir ~/.ssh
chmod 700 ~/.ssh
/usr/bin/ssh-keygen -t rsa
# as oracle on node1
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
ssh rac2 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
scp ~/.ssh/authorized_keys rac2:/home/oracle/.ssh/
# Perform the following as the oracle user on node1 and then node2
# copy paste the following command in both nodes twice:
ssh rac1 date;ssh rac2 date;ssh rac1.mydomain.com date;ssh rac2.mydomain.com
date;ssh rac1-priv date;ssh rac2-priv date;ssh rac1-priv.mydomain.com date;ssh
rac2-priv.mydomain.com date;ssh localhost.localdomain date;ssh localhost date
# Note: the keys are session dependent. it's gone from memory on log off
# Execute (to load the keys in the memory):
exec /usr/bin/ssh-agent $SHELL
/usr/bin/ssh-add
# unzip the Oracle 10g R2 Clusterware for Linux in the stage folder (rac1)
>Home Details
/u01/crs
>Configuration Scripts
as the root user on each node, run the scripts. Do not run the scripts
simultaneously on both nodes.
if there is an error in scripts execution, it's reported in /u01/
/crs/log/<hostname>
# you MUST run vipca in the LAST NODE (NODE2) before clicking OK in OUI
# from $ORA_CRS_HOME/bin
cd /u01/crs/bin
./vipca
# in vipca, click on vip address to auto fill
rac1 rac1-vip.mydomain.com 192.168.4.13
rac2 rac2-vip.mydomain.com 192.168.4.14
When the configuration is complete, the final result report will be:
Configuration ResultsThe VIP Configuration Assistant has successfully created
resource aplications for each cluster node
Click 'Exit'
-- start OUI
cd /u01/stage10g/database
./runInstaller
Install Location
Keep the default Oracle Base location /u01/app/oracle and
default Oracle Home location /u01/app/oracle/product/10.2.0/db_1
'Next' to continue.
Summary
Review the summary and select 'Install' to start the installation.
Configuration Script
Once the installation is complete you will be prompted to run a script as the
root user. Open a
terminal window and execute the script as the root user on each node.
Select 'Ok' to continue after the script has been run successfully on both
nodes.
End of Installation
Once the installation is complete select 'Exit' to complete the installation
and exit the OUI.
# you apply the patch on (1) clusterware then on (2) database software
6. Configure Listeners
# Run netca (not netmanager which is not clusteraware) from any node.
# as oracle
cd $ORACLE_HOME/bin
./netca &
Select Cluster configuration and select both nodes.
Configure Listener
Then Configure Naming Methods: Local and Easy Connect
After installing listener check with below commands whether listener working
properly.
# as root
/u01/crs/bin/crs_stat -t
Welcome
Keep the default selection Oracle RAC database. 'Next' to continue.
Node Selection
Select ALL the nodes and 'Next' to continue.
Operations
Select Create a Database.
'Next' to continue.
Node
Select all the nodes
'Next' to continue.
Database Templates
Select the required template
Database Identification
Enter rac as the global database name.
'Next' to continue.
Management Options
Keep the default settings Configure Enterprise Manager and Configure Database
Control for local management selected,
but Enable Alert Notifications and Enable Daily Disk Backup to Recovery Area
deselected.
'Next' to continue.
Database Credentials
Select Use the same Administrative Password for All Accounts and enter a
password.
'Next' to continue.
Storage Options
Select ASM for storage.
'Next' to continue.
Recovery Configuration:
Select Specify Flash Recovery Area and enter +DG2 as the Flash Recovery Area.
Set its size.
Select Enable archiving and click on the Edit Archive Mode Parameters button
and make sure the Flash Recovery area is pointing to +DG2.
'OK' and then
'Next' to continue.
Database Content
Select Sample Schemas if you want to install them.
Click 'Next'
Database Services:
Click Add button and enter Service Name such as: hrserv then click 'OK'
Make sure it's set to 'Preferred' in both nodes and select Basic for TAF.
Click 'Next'
Initialization Parameters:
Memory Size to 70%. You can leave all other settings as is.
'Next' to continue
Creation Options
Select Generate database creation scripts if you want to review these at a
later stage.
'Finish' to review the installation.
9. Postinstallation tasks
• After implementing the mandatory tasks below, consider implementing some useful
posinstallation tasks.
As the oracle user edit the /etc/oratab file on both nodes.
Replace the database name with the instance name for the rac database
i.e. replace the rac keyword with rac1 or rac2 depending on the node.
Furthermore add details for your clusterware home to this file.
This will enable you to set the Clusterware home using the oraenv script.
Once edited the /etc/oratab file should contain the following:
vi /etc/oratab
On node RAC1:
+ASM1:/u01/app/oracle/products/10.2.0/db_1:N
rac1:/u01/app/oracle/products/10.2.0/db_1:N
crs:/u01/crs:N
On node RAC2
+ASM2:/u01/app/oracle/products/10.2.0/db_1:N
rac2:/u01/app/oracle/products/10.2.0/db_1:N
crs:/u01/crs:N
• Following are tips to consider after the successful installation to make managing RAC
easier.
• Consider using rlwrap utility with SQL*Plus and RMAN:
o Using rlwrap Utility with RMAN in Unix-Based Systems
o Using rlwrap Utility with SQL*Plus in Unix-Based Systems
/* Make crs_stat -t more readable */
/* copy the following script into ~/scripts/crstat.sh */
#!/usr/bin/ksh
#
# Sample 10g CRS resource status query script
#
# Description:
# - Returns formatted version of crs_stat -t, in tabular
# format, with the complete rsc names and filtering keywords
# - The argument, $RSC_KEY, is optional and if passed to the script, will
# limit the output to HA resources whose names match $RSC_KEY.
# Requirements:
# - $ORA_CRS_HOME should be set in your environment
# suggested scrip name: crstat.sh
RSC_KEY=$1
QSTAT=-u
AWK=/usr/bin/awk # if not available use /usr/bin/awk
# Table body:
$ORA_CRS_HOME/bin/crs_stat $QSTAT | $AWK \
'BEGIN { FS="="; state = 0; }
$1~/NAME/ && $2~/'$RSC_KEY'/ {appname = $2; state=1};
state == 0 {next;}
$1~/TARGET/ && state == 1 {apptarget = $2; state=2;}
$1~/STATE/ && state == 2 {appstate = $2; state=3;}
state == 3 {printf "%-45s %-10s %-18s\n", appname, apptarget, appstate;
state=0;}'
Installation Environment
• Emulation software: VMWare Server 2 for Windows.
• RAC Nodes: 2 nodes
• OS: Windows 2003 Server Standard Edition 32-bit SP2
Required Software
• Oracle 10g R2 Clusterware for Windows 32-bit
• Oracle Database 10g Release 2 for Windows 32-bit
Used Hardware
• In the VMWare: create one virtual machine (rac1) with the following specs:
o 2 GB RAM
o two ethernet cards: both can be configured as bridged or host-only in VMware.
o one local hardisk with 20 GB
o CPU Count: 2
o create a folder in the same directory structure level as the parent folder containing the
created virtual machine. Give it a meaningful name like 'shared_disks'. Create in that
folder two disks of 10 GB and two of 512 MB. All of them are of LSI Logic type and
SCISI Persistent.
1. Preinstallation tasks
• The local admin username and password must be the same on both nodes.
• Give the first ethernet card IP 192.168.4.11 and the second 192.168.0.11. Define a
gateway. If it does not exist, make it same as the host IP address.
right click on the partition and select the "New Logical Drive" -> Next->
Accept the default partition size Next->
select the "Do not assign a drive letter or drive path" option->
Next->
select the "Do not format this partition" option-> Next-> Finish
/* Time Sync */
-- make sure the time is synched
>Summary
>Install
>Welcome
>Next
>Enter the vitual IP alias and address for each node: rac1-vip.mydomain.com
Once you enter the first alias, the remaining values should default
automatically
>Next
>Summary
>Finish
-- 4
# check status of crs daemon processes (ALL NODES)
crs_stat -t
Name Type Target State Host
------------------------------------------------------
ora.rac1.gsd application ONLINE ONLINE rac1
ora.rac1.ons application ONLINE ONLINE rac1
ora.rac1.vip application ONLINE ONLINE rac1
ora.rac2.gsd application ONLINE ONLINE rac2
ora.rac2.ons application ONLINE ONLINE rac2
ora.rac2.vip application ONLINE ONLINE rac2
# if State of any of them is UNKNOWN, try restarting the deamons
./crsctl stop crs
# then start again
./crsctl start crs
-- start OUI
cd C:\temp\OracleDB10gR2
setup.exe
Welcome
>Next
Install Location
>Oracle Home name: OraDb10g
>Oracle Home location: C:\oracle\product\10.2.0\db_1
>Next
Summary
>Finish
End of Installation
>Exit
>Summary
>Install
>Exit
>Summary
>Install
>Exit
6. Configure Listeners
# Run netca (not netmanager which is not clusteraware) from any node
# as oracle
cd C:\oracle\product\10.2.0\db_1\bin
netca.bat
After installing listener check with below commands whether listener working
properly
C:\oracle\product\10.2.0\crs\bin\crs_stat -t
Welcome
Keep the default selection Oracle RAC database
>Next
Operations Select
>Configure ASM >Next
Node Selection
>Select ALL the nodes >Next
# start crs
crsctl start crs
# start crs
crsctl stop crs
CSS Parameters
• MISSCOUNT: Represents network heartbeat timeouts (600 s)
• DISKTIMEOUT: Represents disk I/O timeouts outside reconfiguration (200 s). Should
always be less than I/O latency otherwise crs may trigger node eviction.
# to set disktimeout:
1. Shut down Oracle Clusterware on all nodes but one.
2. As root on available node, use (where M is the I/O latency):
crsctl get css disktimeout
crsctl set css disktimeout M+1
3. Reboot available node.
4. Restart all other nodes.
# to set misscount
# same as above except:
crsctl set css misscount 300
# in Windows
# 1. Identify the OCR backups using the
ocrconfig -showbackup
ocrdump -backupfile <file_name>
# 2. On all of the remaining nodes, disable the following OCR clients:
OracleClusterVolumeService, OracleCSService, OracleCRService, and the
OracleEVMService
# 3. Apply the OCR backup file from Step 1
ocrconfig -restore c:\oracle\crs\cdata\crs\backup00.ocr
# 4. Start all of the services that were stopped in step 2. Restart all of the
nodes and resume operations in cluster mode.
# 5. Verify the OCR integrity where the -n all
cluvfy comp ocr -n all [-verbose]
# Import in Windows
1. Identify the OCR export file
2. Stop the following OCR clients on each node:
OracleClusterVolumeService, OracleCMService, OracleEVMService,
OracleCSService, and the OracleCRService.
3. Import the OCR export file
ocrconfig -import ocrexport.dat
4. Restart all of the affected services on all nodes.
5. Verify the OCR integrity where node_list is a list of all of the nodes:
cluvfy comp ocr -n all [-verbose]
/* to drop a group */
-- make sure its inactive
select thread#, group#, members, bytes/1024/1024 MB, status from v$log order
by thread#, group#;
-- switch log if required
alter system switch loglife;
-- start archiving, if required: specific instance
alter system archive log instance 'rac1' next ;
-- drop the group
ALTER DATABASE DROP LOGFILE GROUP 5;
ALTER DATABASE DROP LOGFILE GROUP 6;
-- or
CONNECT /@db1 AS SYSDBA
..
# 2. update the OCR with the right attribute values for your resources
crs_register ora.….inst -update -o as=2,ra=1,ut=7d
crs_register ora.….asm -update -o as=2,ra=1,ut=7d
crs_register ora.….db -update -o as=2,ra=1,ut=7d
crs_register ora.….cs -update -o as=2,ra=0
crs_register ora.….svr -update -o as=2,ra=0
Setting Server Parameter File Parameter Values for Real Application Clusters
• Practically, each instance uses its own PFILE file that contains only one parameter called
SPFILE. The SPFILE parameter points to the shared SPFILE on your shared storage.
/* about the parameters in spfile in RAC */
# to know wheather spfile or pfile was used when startup
SELECT DECODE(value, NULL, 'PFILE', 'SPFILE:'|| value) "Init File Type"
FROM sys.v_$parameter WHERE name = 'spfile';
-- example
ALTER SYSTEM SET OPEN_CURSORS=500
COMMENT='Changed by Ahmed for testing on 16-dec-09'
SCOPE=BOTH
SID='*';
ALTER SYSTEM SET OPEN_CURSORS=1000 SPFILE=BOTH SID='rac1';
sqlplus /nolog
conn / as sysdba
-- setting the default connection load balancing goal for the service hrserv
-- to LONG (long-lived apps like forms)(default), SHORT (short-lived apps)
execute dbms_service.modify_service (service_name => 'hrserv' , clb_goal =>
dbms_service.clb_goal_long);
execute dbms_service.modify_service (service_name => 'hrserv' , clb_goal =>
dbms_service.clb_goal_short);
AWK=/usr/bin/awk
MY_CRS_HOME=/private/oracle/crs
# ###################################################
# [1] Notification Method 1: On-cluster file logging
# ###################################################
# This section simply writes one-line entries for each event published by RAC,
# and the log is written to standard RAC log directory. It will blindly
# record all RAC events, regardless of state (UP, DOWN or NOT_RESTARTING):
RACEVT_LOGFILE=$MY_CRS_HOME/racg/log/rac_${NOTIFY_SERVICE}_uptime.log
# ########################################################
# [2] Notification Method 2: On-cluster program execution
# ########################################################
# Let's assume you have a custom client program in /tmp (say logTicket)
# to which you can pass certain arguments. This program connects to a
# customer-service application that processes incident tickets for your
# IT department:
# % /tmp/logTicket {serverside_timestamp} \
# {databasename} {servicename} \
# {instancename} {hostname}#
# Let us also assume that a ticket would be logged only for NOT_RESTARTING
# events, as they are the ones that exceeded RAC-monitored timeouts and
# seriously need human intervention for full resolution.#
# -------------------
# ONE SOLUTION TO [2]:
# -------------------
if [ $NOTIFY_STATUS = "NOT_RESTARTING" -o $NOTIFY_STATUS = "not_restarting"
]; then
/tmp/logTicket $NOTIFY_SVRLOGDATE $NOTIFY_DBNAME \
$NOTIFY_SERVICE \
$NOTIFY_INSTANCE $NOTIFY_HOST >> $RACEVT_LOGFILE
fi
# (2) in rac3:
racgons add_config rac1:6200 rac2:6200
racgons add_config rac3:6200
SELECT SERVICE_NAME,
to_char(BEGIN_TIME,'hh24:mi:ss') BEGIN_TIME,
to_char(END_TIME,'hh24:mi:ss') END_TIME,
INTSIZE_CSEC, GROUP_ID "Service Metric Group",
CPUPERCALL "CPU time per call",
DBTIMEPERCALL "Elapsed time per call",
CALLSPERSEC "User Calls/s",
DBTIMEPERSEC "DB Time/s"
from V$SERVICEMETRIC_HISTORY
order by SERVICE_NAME, BEGIN_TIME desc;
-- aggregated
SELECT
SERVICE_NAME,
GROUP_ID "Service Metric Group",
round(sum(CPUPERCALL),2) "CPU time per call",
round(sum(DBTIMEPERCALL),2) "Elapsed time per call",
round(sum(CALLSPERSEC),2) "User Calls/s",
round(sum(DBTIMEPERSEC),2) "DB Time/s"
from V$SERVICEMETRIC_HISTORY
group by SERVICE_NAME, GROUP_ID
order by SERVICE_NAME;
exec dbms_service.modify_service ( ,-
service_name => 'hrserv' ,-
aq_ha_notifications => true ,-
failover_method => dbms_service.failover_method_basic ,-
failover_type => dbms_service.failover_type_session ,-
failover_retries => 100, failover_delay => 5 ,-
clb_goal => dbms_service.clb_goal_long);
hrserv =
(DESCRIPTION =(FAILOVER=ON)(LOAD_BALANCE=ON)
(ADDRESS=(PROTOCOL=TCP)(HOST=rac1-VIP)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=rac2-VIP)(PORT=1521))
(CONNECT_DATA = (SERVICE_NAME = hrserv)))
HRSERV =
(DESCRIPTION =(FAILOVER=ON)(LOAD_BALANCE=ON)
HRSERV_PRECONNECT =
(DESCRIPTION =(FAILOVER=ON)(LOAD_BALANCE=ON)
(ADDRESS=(PROTOCOL=TCP)(HOST=rac1-vip)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=rac2-vip)(PORT=1521))
(CONNECT_DATA = (SERVICE_NAME = HRSERV_PRECONNECT)))
Service Attributes
• Global unique name
• Network name
• Load Balancing Advisory goal: best service quality (service response time), or best
throughput (how much work is completed in a unit of time).
• Distributed transactions flag
• Advance queuing notification characteristics for OCI and ODP.NET clients
• Failover characteristics
• Connection load-balancing algorithm: SHORT: Use Load Balancing Advisory, LONG: Using
session count by service
• Threshold: for response time and CPU consumption
• Priority: services to consumer groups mapping
• High-availability configuration: how the service is distributed across instances when the
system first starts
-- confirm
select value from v$parameter where upper(name)='SERVICE_NAMES'
/* Delete Service */
begin
DBMS_SERVICE.DELETE_SERVICE( service_name =>'olapserv');
end;
/
/* Start a service */
begin
DBMS_SERVICE.START_SERVICE(service_name=>'hrserv',
instance_name => DBMS_SERVICE.ALL_INSTANCES, -- if NULL current inst
);
end;
/
/* Stop Service */
begin
DBMS_SERVICE.STOP_SERVICE(service_name=>'hrserv',
instance_name => DBMS_SERVICE.ALL_INSTANCES, -- if NULL current inst
);
end;
/
/* Disconnect Sessions */
-- sessions connected to the service are terminated
begin
-- CAUTION: control doesn't return till all sessions are terminated
DBMS_SERVICE.DISCONNECT_SESSION('hrserv');
end;
/
/* Relocating Services */
srvctl relocate service -d rac -s hrserv -i rac2 -t rac3
/* Removing Services */
rvctl stop service -d rac -s hrserv
rvctl remove service -d rac -s hrserv
BEGIN
dbms_scheduler.set_attribute(
name => 'my_jobs_class',
attribute => 'service',
value => 'hrserv');
END;
/
begin
dbms_scheduler.create_job (
job_name => 'My_Job',
job_type => 'plsql_block', -- stored_procedure, plsql_block, executable,
chain
job_action => 'begin null; end;',
job_class => 'my_jobs_class',
start_date => SYSDATE+1,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=2');
end;
BEGIN
dbms_scheduler.set_attribute(
name => 'My_Job',
attribute => 'INSTANCE_STICKINESS',
value => TRUE);
END;
/
BEGIN
DBMS_SCHEDULER.DROP_JOB('My_Job');
END;
/
BEGIN
DBMS_SCHEDULER.DROP_JOB_CLASS('my_jobs_class');
END;
/
DBMS_SCHEDULER.CREATE_JOB_CLASS(
JOB_CLASS_NAME => 'HOT_BATCH_CLASS',
RESOURCE_CONSUMER_GROUP => NULL ,
SERVICE => 'HOT_BATCH_SERV' ,
LOGGING_LEVEL => DBMS_SCHEDULER.LOGGING_RUNS,
LOG_HISTORY => 30, COMMENTS => 'P1 batch');
DBMS_SCHEDULER.CREATE_JOB(
JOB_NAME => 'my_report_job',
JOB_TYPE => 'stored_procedure',
JOB_ACTION => 'my_name.my_proc();',
NUMBER_OF_ARGUMENTS => 4, START_DATE => SYSDATE+1,
REPEAT_INTERVAL => 5, END_DATE => SYSDATE+30,
JOB_CLASS => 'HOT_BATCH_CLASS',
ENABLED => TRUE,
AUTO_DROP => false, COMMENTS => 'daily status');
-- gather stats for PAYROLL module and ACTION whose name is null
begin
DBMS_MONITOR.SERV_MOD_ACT_STAT_ENABLE(SERVICE_NAME => 'hrserv',
-- most recent 60 s
SELECT service_name, elapsedpercall, cpupercall
FROM V$SERVICEMETRIC;
-- last hour
SELECT service_name, elapsedpercall, cpupercall
FROM V$SERVICEMETRIC_HISTORY;
# Auto control file and spfile backup must be configured in a shared location.
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT = '/u02/oradata/RAC/cf_%F';
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '+FRA';
# each node archives to a directory with the same name on all instances
sid1.LOG_ARCHIVE_DEST_1="LOCATION=/arc_dest"
sid2.LOG_ARCHIVE_DEST_1="LOCATION=/arc_dest"
sid3.LOG_ARCHIVE_DEST_1="LOCATION=/arc_dest"
CONN / AS SYSDBA
SHUTDOWN
Back up the database
set LOG_ARCHIVE_DEST_n
-- no instance in OPEN mode
STARTUP MOUNT
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
SHUTDOWN IMMEDIATE
Back up the database
SCHEDULE DESTINATION
-------- ----------------------------------------------
ACTIVE C:\app\Administrator\product\11.1.0\db_1\RDBMS
NAME VALUE
------------------------------ ------------------
log_archive_dest_1
SCHEDULE DESTINATION
-------- ---------------------------------
INACTIVE
SQL> startup
ORACLE instance started.
NAME VALUE
------------------------------ ------------------
log_archive_dest_1
SCHEDULE DESTINATION
-------- ----------------------------------------------
ACTIVE C:\app\Administrator\product\11.1.0\db_1\RDBMS
SCHEDULE DESTINATION
-------- ----------------------------------
ACTIVE USE_DB_RECOVERY_FILE_DEST
NAME VALUE
------------------------------ -------------------
log_archive_dest_10
oifcfg -help
oifcfg iflist
# deleting an interface
# CAUTION: when no option provided, all interfaces will be deleted:
oifcfg delif -global qfe0/204.152.65.16
# all global interfaces will be deleted
oifcfg delif -global
oifcfg getif
2. Stop First, the database instance, and then the ASM instance. When done,
stop nodeapps.
srvctl stop instance ..
srvctl stop asm ..
srvctl stop nodeapps
4. Make any changes necessary to all nodes' /etc/hosts files (on UNIX), or
\WINNT\System32\drivers\etc\hosts files on Windows, and make the necessary DNS
changes, to associate the new IP address with the old host name.
# (4) Perform Postinstallation Steps. Be aware to check the ASM instance name
before editing /etc/oractab file: ps -ef | grep asm
2. Follow: Real Application Cluster-> Instance Management-> Add Instanc-> Select RAC
database-> Next-> Enter the Instance Name, select node-> Enter service info->
$CRS_HOME/bin/crs_stat -t
# confirm
srvctl config service -d rac
2. From rac1, remove DB instance in rac2 using DBCA (OEM can also be used). Follow the
steps as in the sub-section "Using DBCA in Interactive Mode to Delete Database
Instances from Existing Nodes". To confirm:
crs_stat -t
3. Delete ASM instance as described in the sub-section "ASM Instance Clean-Up Procedures
for Node Deletion".
4. Use NETCA to remove the listener. To confirm:
crs_stat -t
6. On rac2, to make the OUI remove the software home only from rac2:
su - oracle
echo $ORACLE_HOME
export ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1
7. Run OUI from the home and deinstall this home. Make sure that you choose the home to
be removed and not just the products under that home.
./runInstaller &
2. If you ran the Oracle Interface Configuration Tool (OIFCFG) with the -global flag during
the installation, then skip this step. Otherwise, from a node that is going to remain in
your cluster, from the CRS_home/bin directory, run the following command:
./oifcfg delif –node rac2
3. Obtain the remote port number, which you will use in the next step, using the following
command from the CRS_HOME/opmn/conf directory:
echo $CRS_HOME
export CRS_HOME=/u01/crs
cd $CRS_HOME/opmn/conf
cat ons.config
5. On rac2 as root:
su -
export CRS_HOME=/u01/crs
$CRS_HOME/install/rootdelete.sh
$CRS_HOME/install/rootdeletenode.sh rac2,2
$CRS_HOME/bin/olsnodes -n
crs_stat -t
olsnodes -n
Using DBCA in Interactive Mode to Delete Database Instances from Existing Nodes
1. On rac1, open DBCA from Oracle home.
2. On the DBCA Welcome page select Oracle Real Application Clusters Database, click
Next
3. On the DBCA Operations page, select Instance Management, click Next
4. On the Instance Management page, Select Delete Instance, click Next
5. On the List of Cluster Databases page, select the Oracle RAC database. Enter a
SYSDBA user name and password. Click Next
6. On the List of Cluster Database Instances page, select an instance to delete and click
Finish.
7. If you have services assigned to this instance, then the DBCA Services Management
page appears. Use this feature to reassign services from this instance to other
instances in the cluster database.
8. On the Summary page and click OK.
9. DBCA removes the instance and the instance's Oracle Net configuration.
10. After completion, exit DBCA
5. Run OUI from the home and deinstall this home. Make sure that you choose the home to
be removed and not just the products under that home.
./runInstaller &
8. On rac2, disable the Oracle Clusterware applications that are on the node:
echo $CRS_HOME
export CRS_HOME=/u01/crs
cd $CRS_HOME/install
# If the ocr.loc file is on a local file system
rootdelete.sh remote nosharedvar
# If the ocr.loc file is on a shared file system
rootdelete.sh remote sharedvar
10. On rac2:
$CRS_HOME/oui/bin/runInstaller -updateNodeList ORACLE_HOME=$CRS_HOME
CLUSTER_NODES="" –local CRS=true
11. Run OUI from the home and deinstall this home. Make sure that you choose the home to
be removed and not just the products under that home.
$CRS_HOME/oui/bin/runInstaller &
crs_stat -t
3. On rac2:
rm -r $ORACLE_BASE/admin/+ASM
rm -f $ORACLE_HOME/dbs/*ASM
Using DBCA in Interactive Mode to Delete Database Instances from Existing Nodes
exec dbms_workload_repository.create_snapshot
Note: You can install the Oracle Clusterware high availability Application Programming
Interface (API) from the Oracle Database 10g release 10.2 client installation media.
Note: Your Listener.ora file should contain one entry for the virtual internet protocol (VIP)
address, using the VIP's name, and another entry for the physical host, by IP address not
name.
1. Create an application profile by editing an ASCII file or by running the crs_profile command.
# file name format resource_name.cap
save file in
$CRS_HOME\crs\profile for root user
$CRS_HOME\crs\public for non-root user
# Required Ones
# resource-specific script (start, stop or check will be passed by crs)
ACTION_SCRIPT
# application name
NAME
# resource type (must be APPLICATION)
TYPE
# ordered list of cluster nodes (use names as listed by olsnodes)
HOSTING_MEMBERS
# Optional Ones
# description of the resource
DESCRIPTION='myapplication'
# list of required resources (must be registered)
REQUIRED_RESOURCES
# placement policy: (balanced), favored, or restricted
PLACEMENT
# when 1 (0), crs re-evaluates the placement of a resource
# during addition or restart of a cluster node
ACTIVE_PLACEMENT=0
# when 1 (0), it atuo-restarts on system reboot
AUTO_START=1
# check intervals in seconds (60)
# in $CRS_HOME/crs/public
# will generate file postman.cap containing:
NAME=postman
TYPE=application
ACTION_SCRIPT=/oracle/crs/script/postman.scr
ACTIVE_PLACEMENT=0
AUTO_START=0
CHECK_INTERVAL=5
DESCRIPTION=email app
FAILOVER_DELAY=0
FAILURE_INTERVAL=12
FAILURE_THRESHOLD=2
HOSTING_MEMBERS=
OPTIONAL_RESOURCES=application2
PLACEMENT=balanced
REQUIRED_RESOURCES=network1
RESTART_ATTEMPTS=2
SCRIPT_TIMEOUT=60
...
# and script file postman.scr
3. Run the crs_start command to initiate the application profile and then the Oracle
Clusterware runs the action program command that you have included in the profile to start
your application.
crs_start postman
4. The Oracle Clusterware periodically runs the action program command to check an
application’s status.
5. In the event of a check or node failure, the Oracle Clusterware recovers the applications
either by restarting it on the current node or by relocating the application to another node. To
manually relocate the application and its resources to another node:
# the application and its required resources must be offline
crs_relocate postman -c rac2
6. If you run the crs_stop command to stop the application, then the Oracle Clusterware runs
the action program command to stop it.
crs_stop postman
#
# 1) create the action script file
# create following script in both nodes (in $CRS_HOME/crs/script)
# make the file executable
# you can then test it by passing start stop and check
#!/bin/bash
# start/stop/check script for xclock example
# the script assumes xclock is there
# and DISPLAY variable is set
APP=/usr/X11R6/bin/xclock
BIN_NAME=xclock
LOG_DIR=/tmp
export DISPLAY=:0.0
PID1=`ps -ef | grep $BIN_NAME | grep -v grep | grep -v xclock_app | awk '{
print $2 }'`
case $1 in
'start')
if [ "$PID1" != "" ]
then
status_p1="running"
else
if [ -x $APP ]
then
#umask 002
${APP} &
PID1=`ps -ef | grep $BIN_NAME | grep -v grep | grep -v xclock_app | awk
'{ print $2 }'`
echo `date +"%M:%S"` $* $PID1 $USER>>/tmp/mylog.log
status_p1="started"
else
echo `basename $0`": $APP: Executable not found"
fi
fi
echo "$APP: $status_p1"
;;
'stop')
if [ "${PID1}" != "" ]
then
kill -9 ${PID1} && echo "$APP killed"
else
echo "$BIN_NAME: no running Process!"
fi
;;
'check')
if [ "$PID1" != "" ]
then
echo "running"
exit 0
else
echo "not running"
echo `date +"%M:%S"` $0 $* "ERR">>/tmp/mylog.log
exit 1
#
# 2) create application resource profile named myClock
# if you copy paste, fix the hyphen issue
su -
$CRS_HOME/bin/crs_profile -create myClock -t application -a
crsclock_action.scr -p favored -h "rac1-vip rac2-vip" -o ci=5,ra=2
#
# 3) Register the resource (in ONE node only)
# must be done as root and then permission is granted to oracle
su -
$CRS_HOME/bin/crs_register myClock
$CRS_HOME/bin/crs_setperm myClock -u user:oracle:r-x
$CRS_HOME/bin/crs_stat myClock
$CRS_HOME/bin/crs_stat -t
#
# 4) Start the resource
# as oracle
su - oracle
$CRS_HOME/bin/crs_start myClock
$CRS_HOME/bin/crs_stat -t
# application profile
Debugging Recommnedation
• Always make sure that your nodes have exactly the same system time. Use NTP.
# crs alerts
$ORA_CRS_HOME/log/<hostname>/alert<nodename>.log
Dynamic Debugging
/* to Enable Debugging */
# as root
# for the Oracle Clusterware
crsctl debug log crs "CRSRTI:1,CRSCOMM:2"
# for EVM
crsctl debug log evm "EVMCOMM:1"
Resource Debugging
# method 1: where 1 in the following example is the debugging level
crsctl debug log res "ora.node1.vip:1"
# method 2:
export USER_ORA_DEBUG=1
# .. then issue crsctl start, stop, or check
Enabling Tracing for Java-Based Tools and Utilities in Real Application Clusters
#verify whether storage is shared among the nodes in your cluster database or
to identify all of the storage that is available on the system and can be
shared across the cluster nodes:
cluvfy comp ssa -n all -s /dev/sda1
#checks whether node1 and node2 can communicate through the eth0 network
interface (without i, all interfaces are checked):
cluvfy comp nodecon -n node1,node2 –i eth0 -verbose
#verify existence of node applications, namely VIP, ONS, and GSD, on all
the nodes:
cluvfy comp nodeapp -n all -verbose
sqlplus –help
-- no insert
INSERT INTO product_user_profile VALUES
('SQL*PLUS','OE','INSERT',NULL,NULL,NULL,NULL,NULL);
-- no OS command
INSERT INTO product_user_profile (product,userid,attribute) VALUES
('SQL*Plus','myuser','HOST');
-- no set Role to DBA
insert into product_user_profile(product, userid, attribute, char_value)
values('SQL*Plus', 'APPS', 'ROLES', 'DBA');
-- Preventing access using PL/SQL
insert into system.product_profile (product, userid, attribute, char_value)
values ('SQL*Plus', 'AMAR', 'DECLARE', 'DISABLED');
insert into system.product_profile (product, userid, attribute, char_value)
values ('SQL*Plus', 'AMAR', 'BEGIN', 'DISABLED');
sqlplus -RESTRICT 1
SAVE status.sql
-- set the search directory using env var ORACLE_PATH
@myscriptfile.sql
-- substitution vars
DEFINE owner = '&1'
SELECT segment_name,segment_type,extents
FROM dba_segments
WHERE owner = upper ('&owner');
SET AUTOTRACE
ON
ON STATISTICS
ON EXPLAIN
TRACEONLY
TRACEONLY STATISTICS
OFF
• rlwrap utility allows you to navigate history of commands in SQL*Plus and edit them.
/* Install */
# download rlwrap-0.30.tar.gz (search the net or from
http://www.ahmedbaraka.com/download/oracle/rlwrap-0.30.tar.gz )
# unzip the file and install
su -
/* Recommended */
vi /home/oracle/.bashrc
alias sqlpus='rlwrap sqlplus /nolog'
# or
echo "alias sqlplus='rlwrap sqlplus'" >> /home/oracle/.bashrc
Invoking SQL*Loader
SQLLDR keyword=value [,keyword=value,. . .]
Parameters can be specified in a parameter file:
sqlldr PARFILE=c:\...\myparfile.txt
You specify the command-line parameters (which also could be specified in the control file):
USERID = usrname/passwored
CONTROL = '/../mycontrol.ctl'
DATA = '/../mydata.dat'
LOG = '/.../mylog.log'
BAD = '/.../mybadfile.bad' if not specified, Oracle will create one
DISCARD='/../mydiscard.dat' discarded data do not meet the criteria
DISCARDMAX=100
SKIP = 235550
in conventional path mode, bind size in bytes OR number of rows
BINDSIZE = 512000
ROWS = 64000
DIRECT=true
UNRECOVERABLE=Y (see direct load options in the following sections)
ERRORS = 0 no errors tolerated
LOAD = 10000 maximum number of logical records to be loaded into the table
SILENT = ALL all generated message are NOT displayed
PARALLEL=true only when DIRECT=true
RESUMABLE=true default is false
RESUMABLE_NAME = finance1_load
RESUMABLE_TIMEOUT = 3660 in seconds
/* Example 1 */
-- tabe separated with nulls in the data
Data to Import:
1 Ahmed Baraka 1000 1.87 1-1-2000
2 John Rice 5000 2.4 10-5-1998
3 Emme Rak 2500 2.34
4 King Size 2700
5 Small Size 3000 31-3-2001
Table Structure
PERSONS
(ID NUMBER,
PNAME VARCHAR2(100),
BALANCE NUMBER,
RATE NUMBER,
JOIN_DATE DATE );
Control File:
OPTIONS ( ERRORS=0)
LOAD DATA
INFILE 'C:\temp\data\persons.dat'
BADFILE 'C:\temp\data\persons.bad'
DISCARDFILE 'C:\temp\data\persons.dsc'
/* Example 2 */
-- positional columns
load data
infile *
replace
into table departments
( dept position (02:05) char(4),
deptname position (08:27) char(20)
)
begindata
COSC COMPUTER SCIENCE
ENGL ENGLISH LITERATURE
MATH MATHEMATICS
POLY POLITICAL SCIENCE
/* Example 3 */
-- data transformation
LOAD DATA
INFILE *
INTO TABLE modified_data
( rec_no "my_db_sequence.nextval",
region CONSTANT '31',
time_loaded "to_char(SYSDATE, 'HH24:MI')",
data1 POSITION(1:5) ":data1/100",
data2 POSITION(6:15) "upper(:data2)",
data3 POSITION(16:22)"to_date(:data3, 'YYMMDD')"
)
BEGINDATA
11111AAAAAAAAAA991201
22222BBBBBBBBBB990112
LOAD DATA
INFILE 'mail_orders.txt'
BADFILE 'bad_orders.txt'
APPEND
INTO TABLE mailing_list
FIELDS TERMINATED BY ","
( addr,
city,
state,
zipcode,
mailing_addr "decode(:mailing_addr, null, :addr, :mailing_addr)",
mailing_city "decode(:mailing_city, null, :city, :mailing_city)",
mailing_state,
move_date "substr(:move_date, 3, 2) || substr(:move_date, 7, 2)"
)
/* Example 4 */
/* Example 5 */
-- loading into multiple tables
-- skipping columns (FILLER)
-- POSITION(1:4) in the example is a must to resent the pointer back
-- to the beginning of the row
-- In delimited formats, use "POSITION(1)" after the first
-- column to reset the pointer
LOAD DATA
INFILE *
INTO TABLE tab1 WHEN tab = 'tab1'
( tab FILLER CHAR(4),
col1 INTEGER
)
INTO TABLE tab2 WHEN tab = 'tab2'
( tab FILLER POSITION(1:4),
col1 INTEGER
)
BEGINDATA
tab1|1
tab1|2
tab2|2
tab3|3
-- another example
LOAD DATA
INFILE 'mydata.dat'
REPLACE
INTO TABLE emp
WHEN empno != ' '
( empno POSITION(1:4) INTEGER EXTERNAL,
ename POSITION(6:15) CHAR,
deptno POSITION(17:18) CHAR,
mgr POSITION(20:23) INTEGER EXTERNAL
)
INTO TABLE proj
WHEN projno != ' '
( projno POSITION(25:27) INTEGER EXTERNAL,
empno POSITION(1:4) INTEGER EXTERNAL
)
/* Example 6 */
-- work around on being unable to use OR in the WHEN condition
LOAD DATA
INFILE 'mydata.dat' BADFILE 'mydata.bad' DISCARDFILE 'mydata.dis'
/* Example 7 */
-- load records with multi-line fields
-- doesn't work with inline data
load data
infile "test.dat" "str '|\n'"
into test_table
fields terminated by ';' TRAILING NULLCOLS
(
desc, txt
)
test.dat:
one line;hello dear world;|
two lines;Dear world,
hello!;|
/* Example 8 */
-- loading binary files (word, images, video... etc)
CREATE TABLE image_table (
image_id NUMBER(5),
file_name VARCHAR2(30),
image_data BLOB);
Control File:
LOAD DATA
INFILE *
INTO TABLE image_table
REPLACE
FIELDS TERMINATED BY ','
(
image_id INTEGER(5),
file_name CHAR(30),
image_data LOBFILE (file_name) TERMINATED BY EOF
)
BEGINDATA
001,image1.gif
002,image2.jpg
/* Example 9 */
-- using specified characterset
LOAD DATA
CHARACTERSET WE8EBCDIC500
INFILE data.ebc "fix 86 buffers 1024"
BADFILE data.bad'
DISCARDFILE data.dsc'
REPLACE
INTO TABLE temp_data
(
...
/* Example 10 */
-- Loading a Sequence Number
LOAD DATA
INFILE '/u01/app/oracle/oradata/load/testload.txt'
INSERT INTO TABLE test123
(test_seq.nextval,. . .)
# tables mode
expdp baraka/password tables=employees DIRECTORY=dpump_dir1
dumpfile=testexp01.dmp
expdp system/password tables=hr.employees ..
/* QUERY */
QUERY=OE.ORDERS: "WHERE order_id > 100000 ORDER BY order_date desc"
REMAP_SCHEMA
REMAP_DATAFILE
Changes the name of the source datafile to the target datafile name in all SQL statements
where the source datafile is referenced: CREATE TABLESPACE, CREATE LIBRARY, and CREATE
DIRECTORY.
Remapping datafiles is useful when you move databases between platforms that have
different file naming conventions.
impdp hr/hr FULL=y DIRECTORY=dpump_dir1 DUMPFILE=db_full.dmp
REMAP_DATAFILE='DB1$:[HRDATA.PAYROLL]tbs6.f':'/db1/hrdata/payroll/tbs6.f'
REMAP_TABLESPACE
This parameter enables you to move objects from one tablespace into a different tablespace
during an import.
impdp hr/hr REMAP_TABLESPACE='example_tbs':'new_tbs' DIRECTORY=dpump_dir1
PARALLEL=2 JOB_NAME=cf1n02 DUMPFILE=employees.dmp NOLOGFILE=Y
Note: you must enable at least minimal supplemental logging prior to generating log files
which will be analyzed by LogMiner.
-- start LogMiner
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
begin
DBMS_LOGMNR.START_LOGMNR(
STARTTIME => '01-Jan-2003 08:30:00',
ENDTIME => '01-Jan-2003 08:45:00', -- future value can be set SYSDATE+5/24
OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG +
DBMS_LOGMNR.CONTINUOUS_MINE +
DBMS_LOGMNR.COMMITTED_DATA_ONLY +
DBMS_LOGMNR.PRINT_PRETTY_SQL );
end;
/
-- query V$LOGMNR_CONTENTS
SELECT USERNAME AS usr,(XIDUSN || '.' || XIDSLT || '.' || XIDSQN) as XID,
SQL_REDO FROM V$LOGMNR_CONTENTS
WHERE SEG_OWNER IS NULL OR SEG_OWNER NOT IN ('SYS', 'SYSTEM') AND
TIMESTAMP > '10-jan-2003 15:59:53';
- TO extract the data dictionary to the redo logs (must be done before the
redo to analyze)
EXECUTE sys.DBMS_LOGMNR_D.build( OPTIONS =>
sys.DBMS_LOGMNR_D.store_in_redo_logs);
- Find a redo log file that contains the end of the dictionary extract
SELECT NAME, SEQUENCE#, DICTIONARY_BEGIN d_beg, DICTIONARY_END d_end
FROM V$ARCHIVED_LOG
WHERE SEQUENCE# = (SELECT MAX (SEQUENCE#) FROM V$ARCHIVED_LOG
WHERE DICTIONARY_END = 'YES' and SEQUENCE# <= 210);
- Find the redo log file that contains the start of the data dictionary
extract that matches the end of the dictionary found in the previous step:
SELECT NAME, SEQUENCE#, DICTIONARY_BEGIN d_beg, DICTIONARY_END d_end
FROM V$ARCHIVED_LOG
WHERE SEQUENCE# = (SELECT MAX (SEQUENCE#) FROM V$ARCHIVED_LOG
WHERE DICTIONARY_BEGIN = 'YES' and SEQUENCE# <= 208);
- Specify the list of the redo log files of interest. Order doesn't matter:
EXECUTE DBMS_LOGMNR.ADD_LOGFILE(-
LOGFILENAME => '/usr/oracle/data/db1arch_1_210_482701534.dbf', -
OPTIONS => DBMS_LOGMNR.NEW);
EXECUTE DBMS_LOGMNR.ADD_LOGFILE(-
LOGFILENAME => '/usr/oracle/data/db1arch_1_208_482701534.dbf');
EXECUTE DBMS_LOGMNR.ADD_LOGFILE(-
LOGFILENAME => '/usr/oracle/data/db1arch_1_207_482701534.dbf');
- Start LogMiner:
EXECUTE DBMS_LOGMNR.START_LOGMNR(-
OPTIONS => DBMS_LOGMNR.DICT_FROM_REDO_LOGS + -
DBMS_LOGMNR.COMMITTED_DATA_ONLY + -
DBMS_LOGMNR.PRINT_PRETTY_SQL);
- to display all the DML statements that were executed as part of the CREATE
isqlplusctl start
#!/bin/bash
#
# oraemctl Starting and stopping Oracle Enterprise Manager Database Control.
# Script is valid for 10g and 11g versions.
#
# chkconfig: 35 80 30
# description: Enterprise Manager DB Control startup script
. /etc/rc.d/init.d/functions
ORACLE_OWNER="oracle"
ORACLE_HOME="/u01/app/oracle/product/10.2.0/db_1"
case "$1" in
start)
echo -n $"Starting Oracle EM DB Console:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/emctl start dbconsole"
echo "OK"
;;
stop)
echo -n $"Stopping Oracle EM DB Console:"
su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/emctl stop dbconsole"
echo "OK"
;;
*)
echo $"Usage: $0 {start|stop}"
esac
DECLARE
v_string VARCHAR2(10 CHAR);
...
/* number */
BINARY_DOUBLE
BINARY_FLOAT
BINARY_INTEGER
NUMBER
PLS_INTEGER –2147483647 to +2147483647
/* data time */
-- TIMESTAMP
select SYSTIMESTAMP from dual;
/* inerval */
INTERVAL YEAR TO MONTH
INTERVAL DAY TO SECOND
DECLARE
v_college_deadline TIMESTAMP;
BEGIN
/* REF CURSOR */
-- a pointer to a result set
CREATE OR REPLACE PROCEDURE cust_sel
( cv_results IN OUT SYS_REFCURSOR)
IS
BEGIN
OPEN cv_results FOR
SELECT customer_id, cust_last_name from customers;
END;
/
VARIABLE x REFCURSOR
EXEC cust_sel(:x)
PRINT x
/* REF */
REF value simply as a pointer to an object instance in an object table or
object view.
-- more examples:
PLSQL_WARNINGS = 'ENABLE:SEVERE', 'DISABLE:INFORMATIONAL';
PLSQL_WARNINGS = 'DISABLE:ALL';
PLSQL_WARNINGS = 'DISABLE:5000', 'ENABLE:5001',
'ERROR:5002';
PLSQL_WARNINGS = 'ENABLE:(5000,5001,5002)',
'DISABLE:(6000,6001)';
Hiding Code
wrap iname=input_file.sql oname=output_file.plb
/* CASE */
CASE expression
WHEN test1 THEN action;
WHEN test2 THEN action;
...
ELSE
...
END CASE;
CASE v_category
WHEN 'Oracle Basics'
THEN v_discount := .15;
WHEN 'Oracle Server'
THEN v_discount := .10;
ELSE v_discount := .5;
END CASE;
/* Searched CASE */
CASE
WHEN <exp> THEN
actions;
WHEN <exp> THEN
actions;
ELSE
actions;
END CASE;
/* Case Expressions */
appraisal :=
CASE
WHEN grade = 'A' THEN 'Excellent'
WHEN grade IN ('B','C') THEN 'Good'
ELSE 'No such grade'
END;
/* Loop */
LOOP
..
EXIT [WHEN condition]
END LOOP;
begin
for i in reverse 1..10 loop
dbms_output.put_line(i);
end loop;
end;
/
OPEN cur1;
OPEN cur1(50);
CLOSE cursor_name;
Cursor Attributes:
%BULK_ROWCOUNT number of rows changed during the operation
%ROWCOUNT number of rows fetched from the cursor at any given time
%FOUND
%ISOPEN
%NOTFOUND
-- example 1
SET SERVEROUTPUT ON
DECLARE
v_first_name AUTHORS.FIRST_NAME%TYPE;
v_last_name AUTHORS.LAST_NAME%TYPE;
v_row_count PLS_INTEGER := 0;
v_book_count PLS_INTEGER := 0;
CURSOR auth_cur IS
SELECT a.first_name, a.last_name, count(b.title)
FROM authors a, books b
WHERE a.id = b.author1
OR a.id = b.author2
OR a.id = b.author3
GROUP BY a.first_name, a.last_name
HAVING count(b.title) > 0
ORDER BY a.last_name;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
OPEN auth_cur;
LOOP
FETCH auth_cur INTO v_first_name, v_last_name, v_book_count;
EXIT WHEN auth_cur%NOTFOUND;
v_row_count := auth_cur%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE(v_row_count||' rows processed so far');
DBMS_OUTPUT.PUT_LINE(v_last_name ||', ' ||v_first_name ||' wrote '
||v_book_count ||' book(s).');
END LOOP;
CLOSE auth_cur;
IF auth_cur%ISOPEN = FALSE THEN
DBMS_OUTPUT.PUT_LINE('Cursor closed');
ELSE
DBMS_OUTPUT.PUT_LINE('The cursor is still open');
END IF;
EXCEPTION
-- example 2
..
WHILE auth_cur%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(v_author.last_name);
FETCH auth_cur INTO v_author;
END LOOP;
..
-- example 3
SET SERVEROUTPUT ON
DECLARE
CURSOR auth_cur IS
SELECT * FROM authors;
BEGIN
FOR v_author IN auth_cur LOOP
DBMS_OUTPUT.PUT_LINE(v_author.last_name);
END LOOP;
END;
/
/* Cursor Variables */
SET SERVEROUTPUT ON
DECLARE
TYPE book_typ IS REF CURSOR RETURN BOOKS%ROWTYPE;
cv_books book_typ;
v_books BOOKS%ROWTYPE;
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
OPEN cv_books FOR
SELECT * FROM books WHERE isbn = '78824389';
FETCH cv_books INTO v_books;
DBMS_OUTPUT.PUT_LINE(v_books.title||' is '||v_books.price);
CLOSE cv_books;
END;
/
/* Cursor Subqueries */
SET SERVEROUTPUT ON
DECLARE
cv_author SYS_REFCURSOR;
v_title BOOKS.TITLE%TYPE;
v_author AUTHORS%ROWTYPE;
v_counter PLS_INTEGER := 0;
CURSOR book_cur IS
SELECT b.title,
CURSOR (SELECT *
FROM authors a
WHERE a.id = b.author1
OR a.id = b.author2
OR a.id = b.author3)
FROM books b WHERE isbn = '78824389';
BEGIN
OPEN book_cur;
LOOP
FETCH book_cur INTO v_title, cv_author;
EXIT WHEN book_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Title from the main cursor: '||v_title);
LOOP
FETCH cv_author INTO v_author;
EXIT WHEN cv_author%NOTFOUND;
v_counter := v_counter + 1;
DBMS_OUTPUT.PUT_LINE('Author'||v_counter||': '
||v_author.first_name||' '||v_author.last_name);
END LOOP;
END LOOP;
CLOSE book_cur;
END;
/
DECLARE
TYPE individual_record IS RECORD
(individual_id INTEGER
,first_name VARCHAR2(30 CHAR)
,middle_initial individuals.middle_initial%TYPE
,last_name VARCHAR2(30 CHAR));
-- nested records
DECLARE
-- Define a record type.
TYPE individual_record IS RECORD
(individual_id INTEGER
,first_name VARCHAR2(30 CHAR)
,middle_initial VARCHAR2(1 CHAR)
,last_name VARCHAR2(30 CHAR));
BEGIN
-- Initialize the field values for the record.
individual_address.individual.individual_id := 3;
individual_address.individual.first_name := 'Ulysses';
...
BEGIN
FOR v_Rec IN c_SomeBooks LOOP
v_ResultSet.EXTEND;
v_ResultSet(v_ResultSet.LAST) := BookType(v_Rec.isbn, v_Rec.title);
END LOOP;
RETURN v_ResultSet;
END SomeBooks;
/
SELECT *
FROM TABLE (SomeBooks('Oracle Basics'));
-- Since SomeBooks will always return the same output given the same
-- input, we can use the DETERMINISTIC keyword.
-- its supposed positive impact is not proved though
CREATE OR REPLACE FUNCTION SomeBooks(p_Category IN books.category%TYPE)
RETURN BookTypes DETERMINISTIC AS
END;
/
-- (4) usage
SELECT *
FROM
TABLE(sales_package.modify_sales_data( CURSOR(select
store_name,sales_2001,sales_2002 FROM sales_data)));
Using VARRAYS
• Although VARRAYS can be stored as part of a table, it is best suited for PL/SQL
proccessing.
TYPE type_name IS {VARRAY | VARYING ARRAY} (size_limit)
OF element_type [ NOT NULL ];
-- initialized in the declaration section
DECLARE
TYPE integer_varray IS VARRAY(3) OF INTEGER;
–– Declare and initialize a varray that allows nulls.
varray_integer INTEGER_VARRAY := integer_varray(NULL,NULL,NULL);
BEGIN
–– Assign values to subscripted members of the varray.
varray_integer(1) := 11;
varray_integer(2) := 12;
varray_integer(3) := 13;
FOR i IN 1..3 LOOP
dbms_output.put_line('Integer Varray ['||i||'] '||
'['||varray_integer(i)||']');
END LOOP;
END;
/
UPDATE addresses
SET street_address =
address_varray('Your Address' ,'2400 E. Arizona Biltmore Cir.'
,'Suite 1150')
WHERE address_id = 11;
-- index by string
..
-- Loop through all the associative array elements.
FOR i IN 1..calendar.COUNT LOOP
-- Check if the first element in the loop.
IF i = 1 THEN
-- Assign the first character index to a variable.
current := calendar.FIRST;
-- Use the derived index to find the next index.
element := calendar(current);
ELSE
-- Check if next index value exists.
IF calendar.NEXT(current) IS NOT NULL THEN
-- Assign the character index to a variable.
current := calendar.NEXT(current);
-- Use the derived index to find the next index.
element := calendar(current);
ELSE
-- Exit loop since last index value is read.
EXIT;
END IF;
END IF;
END LOOP;
..
-- using FORALL
CREATE TABLE bulk_numbers
(number_id NUMBER
,CONSTRAINT number_id_pk PRIMARY KEY (number_id));
DECLARE
COMMIT;
END;
/
-- using EXTEND
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
-- Define a nested table type of INTEGER.
TYPE number_table IS TABLE OF INTEGER;
-- Define a variable of the nested table type.
number_list NUMBER_TABLE := number_table(1,2);
-- Define a local procedure to check and print elements.
PROCEDURE print_list
(list_in NUMBER_TABLE) IS
BEGIN
-- Loop through the possible index values of the list.
FOR i IN list_in.FIRST..list_in.LAST LOOP
-- Check if the subscripted element is there.
IF list_in.EXISTS(i) THEN
-- Print the element.
DBMS_OUTPUT.PUT_LINE('List ['||list_in(i)||']');
END IF;
END LOOP;
END print_list;
BEGIN
-- Print a title.
DBMS_OUTPUT.PUT_LINE('Nested table before extension');
DBMS_OUTPUT.PUT_LINE('-----------------------------');
-- Print the list.
print_list(number_list);
-- Allocate two null elements.
number_list.EXTEND(2);
-- Allocate three elements and copy element two
number_list.EXTEND(3,2);
-- Print a title.
DBMS_OUTPUT.PUT_LINE(CHR(10)||
'Nested table after extension');
DBMS_OUTPUT.PUT_LINE('----------------------------');
-- Print the list.
print_list(number_list);
END;
/
Predefined Exceptions
Oracle Error Equivalent Exception Description
ORA-0001 DUP_VAL_ON_INDEX Unique constraint violated.
ORA-0051 TIMEOUT_ON_RESOURCE Time-out occurred while waiting for resource.
ORA-1001 INVALID_CURSOR Illegal cursor operation.
ORA-1012 NOT_LOGGED_ON Not connected to Oracle.
ORA-1017 LOGIN_DENIED Invalid user name/password.
ORA-1403 NO_DATA_FOUND No data found.
ORA-1410 SYS_INVALID_ROWID Conversion to a universal rowid failed.
ORA-1422 TOO_MANY_ROWS A SELECT.INTO statement matches more than
one row.
ORA-1476 ZERO_DIVIDE Division by zero.
ORA-1722 INVALID_NUMBER Conversion to a number failed; for example,
'1A' is not valid.
ORA-1725 USERENV_COMMITSCN_ERROR Incorrect usage of the USERENV('COMMITSCN')
1 function.
ORA-6500 STORAGE_ERROR Internal PL/SQL error raised if PL/SQL runs out
of memory.
ORA-6501 PROGRAM_ERROR Internal PL/SQL error.
ORA-6502 VALUE_ERROR Truncation, arithmetic, or conversion error.
ORA-6504 ROWTYPE_MISMATCH Host cursor variable and PL/SQL cursor variable
have incompatible row types.
ORA-6511 CURSOR_ALREADY_OPEN Attempt to open a cursor that is already open.
ORA-6530 ACCESS_INTO_NULL Attempt to assign values to the attributes of a
NULL object.
ORA-6531 COLLECTION_IS_NULL Attempt to apply collection methods other than
EXISTS to a NULL PL/SQL table or varray.
ORA-6532 SUBSCRIPT_OUTSIDE_LIMIT Reference to a nested table or varray index
outside the declared range (such as –1).
ORA-6533 SUBSCRIPT_BEYOND_COUNT Reference to a nested table or varray index
higher than the number of elements in the
collection.
ORA-6548 NO_DATA_NEEDED1 Caller of a pipelined function does not need
more rows.
ORA-6592 CASE_NOT_FOUND2 No matching WHEN clause in a CASE statement
is found.
ORA-30625 SELF_IS_NULL Attempt to call a method on a null object
instance.
BEGIN
/* Find the IDs for the 3 authors of 'Oracle9i DBA 101' */
SELECT author1, author2, author3
INTO v_Author1, v_Author2, v_Author3
FROM books
WHERE title = 'Oracle9i DBA 101';
Using RAISE_APPLICATION_ERROR
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors]);
• error_number is a value between –20,000 and –20,999
• The error_message must be fewer than 512 characters
• If keep_errors is TRUE, the new error is added to the list of errors already raised (if one
exists). If it is FALSE, which is the default, the new error will replace the current list of
errors.
..
END;
/
GRANT R1 TO USER1;
CONN USER1/U
• To echo the contents of the shared pool of objects greater than minisize to the screen:
DBMS_SHARED_POOL.SIZES(minsize NUMBER)
Restrictions on Triggers
• A trigger may not issue any transaction control statements—COMMIT, ROLLBACK,
SAVEPOINT, or SET TRANSACTION.
• The trigger body cannot declare any LONG or LONG RAW variables.
• Code in a trigger body may reference and use LOB (Large OBject) columns, but it may not
modify the values of the columns. This is also true for object columns.
• Database Events:
Attribute
Event When Trigger Fires Conditions Restrictions Transaction Functions
STARTUP When the database is None No database Starts a ora_sysevent
opened. allowed operations separate ora_login_user
allowed in the transaction ora_instance_num
trigger. and commits it ora_database_name
after firing the
triggers.
Return status
ignored.
SHUTDOWN Just before the server None No database Starts a ora_sysevent
starts the shutdown of allowed operations separate ora_login_user
an instance. allowed in the transaction ora_instance_num
trigger. and commits it ora_database_name
after firing the
This lets the cartridge
triggers.
shutdown completely. Return status
For abnormal instance ignored.
shutdown, this triiger
To workaround: create two triggers: one statement level and the other row
level. The statement trigger store the SELECT result into a PL/SQL table in a
package. The row-level trigger will read that data from the package.
v_StudentMajors t_Majors;
v_StudentIDs t_IDs;
v_NumEntries BINARY_INTEGER := 0;
END StudentData;
/
-- Reset the counter so the next execution will use new data.
StudentData.v_NumEntries := 0;
END SLimitMajors;
-- DDL
statement := 'CREATE SEQUENCE '||sequence_name||CHR(10)
|| ' INCREMENT BY 1' ||CHR(10)
|| ' START WITH 1' ||CHR(10)
|| ' CACHE 20' ||CHR(10)
|| ' ORDER';
PROCEDURE multiple_row_return IS
-- Define local variables.
statement VARCHAR2(2000);
value_out VARCHAR2_TABLE1;
BEGIN
-- using an anonymous block is mandatory, otherwise ORA-03001
statement := 'BEGIN '
|| 'SELECT ''A'' '
|| 'BULK COLLECT INTO :col_val '
|| 'FROM DUAL;'
|| 'END;';
PROCEDURE multiple_row_return
( table_name VARCHAR2
Using DBMS_SQL
• DBMS_SQL still has a major feature that is not delivered in NDS. It does not need to know
beforehand the number and types of arguments it will receive and process.
To use dbms_sql:
GRANT EXECUTE ON dbms_sys_sql TO SYSTEM WITH GRANT OPTION;
GRANT EXECUTE ON dbms_sql TO SYSTEM WITH GRANT OPTION;
PROCEDURE create_sequence
( sequence_name IN VARCHAR2) IS
c INTEGER := dbms_sql.open_cursor;
fdbk INTEGER;
statement VARCHAR2(2000);
BEGIN
BEGIN
/*
|| Debugging Tip:
|| =============
|| When you are using a SELECT-INTO-FROM within DBMS_SQL, which is a
|| reserved PLSQL syntax not directly supported by DBMS_SQL. You
|| need to encapsulate it in a PLSQL wrapper. When you use a PLSQL
|| wrapper, the semicolons must be used in the statement and the
|| PLSQL block because DBMS_SQL adds a single semicolon to execute
|| the PLSQL block. If you forget to encapsulate the SQL in a
|| PLSQL wrapper, you will raise the following error message.
|| -------------------------------------------------------------------
|| ORA-01006: bind variable does not exist
*/
/*
|| Technical Note:
|| ==============
|| The BIND_VARIABLE procedure is returning a NUMBER
|| and does not require parameter four.
*/
dbms_sql.close_cursor(c);
dbms_output.put_line('Value <'||sequence_value||'>');
END increment_sequence;
fdbk := dbms_sql.execute(c);
dbms_sql.close_cursor(c);
commit;
dbms_output.put_line('Value inserted <'||table_column_value1||'>');
dbms_output.put_line('Value inserted <'||table_column_value2||'>');
dbms_output.put_line('Value inserted <'||table_column_value3||'>');
END insert_into_table;
BEGIN
-- Build dynamic SQL statement.
statement := 'INSERT '
|| 'INTO '||table_name||' '
|| '( card_number '
|| ', card_name '
fdbk := dbms_sql.execute(c);
dbms_sql.close_cursor(c);
commit;
dbms_sql.parse(c,statement,dbms_sql.native);
fdbk := dbms_sql.execute(c);
LOOP
-- Exit when no more rows to fetch.
EXIT WHEN dbms_sql.fetch_rows(c) = 0;
-- Copy the contents of column #1 to the value_out variable.
dbms_sql.column_value(c,1,value_out);
dbms_output.put_line('Value from COLUMN_VALUE <'||value_out||'>');
END LOOP;
-- Close the open cursor.
dbms_sql.close_cursor(c);
BEGIN
/*
|| Debugging Tip:
|| =============
|| Define the column values and DO NOT forget to assign a size
|| parameter for a string datatype, like VARCHAR2; however, if you
|| forget, the error message is:
|| -------------------------------------------------------------------
|| PLS-00307: too many declarations of 'DEFINE_COLUMN' match this call
*/
BEGIN
/*
|| Debugging Tip:
|| =============
|| Define the column values and DO NOT forget to assign a size
|| parameter for a string datatype, like VARCHAR2; however, if you
|| forget, the error message is:
|| -------------------------------------------------------------------
|| PLS-00307: too many declarations of 'DEFINE_COLUMN' match this call
||
|| This is the message returned because the DEFINE_COLUMN procedure
|| is overloaded and it doesn't know how to implicitly cast without
|| the OUT_VALUE_SIZE argument. Only CHAR, RAW and VARCHAR2 support
|| a fourth argument.
*/
fdbk := dbms_sql.execute_and_fetch(c);
dbms_output.put_line(
'Value from COLUMN_VALUE <'||value_out||'>');
END single_row_return;
BEGIN
/*
|| Debugging Tip:
|| =============
|| Define the column values and DO NOT forget to assign a size
|| parameter for a string datatype, like VARCHAR2; however, if you
|| forget, the error message is:
|| -------------------------------------------------------------------
|| PLS-00307: too many declarations of 'DEFINE_COLUMN' match this call
||
|| This is the message returned because the DEFINE_COLUMN procedure
|| is overloaded and it doesn't know how to implicitly cast without
|| the OUT_VALUE_SIZE argument. Only CHAR, RAW and VARCHAR2 support
|| a fourth argument.
*/
dbms_sql.close_cursor(c);
END single_row_return;
• Pre-requisits:
o set CLASSPATH should contain:
. current directory
Oracle 11g: %ORACLE_HOME%/jdbc/lib/ojdbc5.jar (or 6 but not both)
ORACLE_HOME/jlib/orai18n.jar
Oracle 10g: %ORACLE_HOME%/jdbc/lib/classes12.zip
Java JDK or J2SE 5.n or 6.n
In Oracle 11g, the oracle.jdbc.driver.* classes, the ojdbc4.jar file, and the
OracleConnectionCacheImpl class are no longer supported or available.
o Make sure PATH points to JDK home.
/* to create a Thick Java client program to Oracle 11g */
-- JDBCExample.java
import java.sql.*;
import oracle.jdbc.pool.OracleDataSource;
/* Pass a query to SQL and store the results in the result set rs */
ResultSet rs = stmt.executeQuery("select employee_id, last_name from
employees");
/* Close the JDBC result set and close the database connection */
rs.close();
conn.close();
}
}
o For further details refer to the documentation or Oracle Database 10g PL/SQL
Programming by Ron Hardman, Michael McLaughlin and Scott Urman, Oracle Press.
Configure one listener for the database and one for the the extproc agent
#(1) In listener.ora
# remove the IPC protocol from the standard settings
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(HOST = srv01)
(PORT = 1521)
)
)
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = ora11g)
(ORACLE_HOME = E:\oracle\OraDB11g)
)
)
#(3) rebuild the original listener service and create new one
# In Windows
lsnrctl stop
# use NETCA to delete the original service and then re-create it.
# build a new service for the second listener CALLOUT_LISTENER. A new
linstener.ora will
# be created so paste again the code above in the file.
# In Unix
lsnrctl stop LISTENER
# backup the original linstener.ora and tnsnames files
# copy the new ones
lsnrctl start LISTENER
lsnrctl start CALLOUT_LISTENER
# verify
ps –ef | grep –v grep | grep tnslsnr
Creating LOB
• To specify different storage options, use the following syntax in your create table
statement:
CREATE TABLE table_name ( .. lob_column lob_datatype )
LOB (lob_column,..) STORE AS [lob_segment_name]
[(TABLESPACE tablespace
{ENABLE|DISABLE} STORAGE IN ROW
STORAGE storage_clause
CHUNK int
PCTVERSION int
CACHE
CACHE READS [[NO]LOGGING]
NOCACHE [[NO]LOGGING])
• PCTVERSION defaults to 10
• NOCACHE is the default
• ENABLE STORAGE IN ROW, which is the default setting, says that if the LOB value is less
than 4K (including control information), store it inline.
CREATE TABLE book_samples (
book_sample_id NUMBER (10) PRIMARY KEY,
isbn CHAR(10 CHAR),
description CLOB,
nls_description NCLOB,
book_cover BLOB,
chapter_title VARCHAR2(30 CHAR),
chapter BFILE
)
LOB (book_cover)
STORE AS blob_seg ( TABLESPACE blob_ts
CHUNK 8192
PCTVERSION 0
NOCACHE
NOLOGGING
DISABLE STORAGE IN ROW)
LOB (description, nls_description)
STORE AS ( TABLESPACE clob_ts
CHUNK 8192
PCTVERSION 10
NOCACHE
LOGGING
ENABLE STORAGE IN ROW);
DBMS_LOB.APPEND(io_lob_destination, io_lob_source);
SET SERVEROUTPUT ON
DECLARE
v_source_lob_loc NCLOB;
v_destination_lob_loc NCLOB;
v_combined_lob NCLOB;
BEGIN
-- for update is a must here
SELECT nls_description
INTO v_source_lob_loc
FROM book_samples_nls
FOR UPDATE;
LOBAPPEND(v_source_lob_loc, v_destination_lob_loc);
SELECT nls_description
INTO v_combined_lob
from book_samples;
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_combined_lob, 1, 150));
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_combined_lob, 151, 300));
END;
/
/* COMPARE */
If 0 is returned, then the LOBs are the same. If 1 is returned, then they are
different.
FUNCTION COMPARE RETURNS NUMBER(38)
Argument Name Type In/Out Default?
––––––––––––––– –––––––––––- ––– ––––
LOB_1 CLOB IN
LOB_2 CLOB IN
AMOUNT NUMBER(38) IN DEFAULT
OFFSET_1 NUMBER(38) IN DEFAULT
OFFSET_2 NUMBER(38) IN DEFAULT
DBMS_LOB.CLOSE(v_lob1);
DBMS_LOB.CLOSE(v_lob2);
END;
/
DECLARE
v_lob1 CLOB;
v_lob2 CLOB;
v_lob3 CLOB;
BEGIN
SELECT description
INTO v_lob1
FROM book_samples
WHERE book_sample_id = 1;
SELECT description
INTO v_lob3
FROM book_samples
WHERE book_sample_id = 3;
CLOB_COMPARE(v_lob1, v_lob2);
CLOB_COMPARE(v_lob1, v_lob3);
END;
/
/* CONVERTTO..LOB */
PROCEDURE CONVERTTOBLOB
DEST_LOB BLOB IN/OUT
# in CONVERTTOCLOB the following is SRC_BLOB
SRC_CLOB CLOB IN
AMOUNT NUMBER(38) IN
DEST_OFFSET NUMBER(38) IN/OUT
SRC_OFFSET NUMBER(38) IN/OUT
BLOB_CSID NUMBER IN
LANG_CONTEXT NUMBER(38) IN/OUT
WARNING NUMBER(38) OUT
DBMS_LOB.OPEN(v_blob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.OPEN(v_clob, DBMS_LOB.LOB_READWRITE);
IF v_blob_or_clob = 0
THEN
DBMS_LOB.CONVERTTOBLOB(v_blob,
v_clob,
v_amount,
v_blob_offset,
v_clob_offset,
1,
v_lang_context,
v_warning);
ELSE
DBMS_LOB.CLOSE(v_blob);
DBMS_LOB.CLOSE(v_clob);
END;
/
DECLARE
v_clob_or_blob NUMBER;
v_blob_locator BLOB;
v_clob_locator CLOB;
v_blob_offset NUMBER;
v_clob_offset NUMBER;
v_lang_context NUMBER := DBMS_LOB.DEFAULT_LANG_CTX;
v_warning NUMBER;
v_string_length NUMBER(10);
v_source_locator BLOB;
v_destination_locator BLOB;
v_amount PLS_INTEGER;
v_string CLOB;
BEGIN
SELECT description
INTO v_clob_locator
FROM book_samples
WHERE book_sample_id = 1
FOR UPDATE;
SELECT misc
INTO v_blob_locator
FROM book_samples
WHERE book_sample_id = 1
FOR UPDATE;
v_string_length := DBMS_LOB.GETLENGTH(v_blob_locator);
v_amount := DBMS_LOB.GETLENGTH(v_clob_locator);
CONVERT_ME(v_clob_or_blob,
v_string_length := DBMS_LOB.GETLENGTH(v_blob_locator);
SELECT misc
INTO v_destination_locator
FROM book_samples
WHERE book_sample_id = 2
FOR UPDATE;
v_string_length := DBMS_LOB.GETLENGTH(v_destination_locator);
SELECT description
INTO v_clob_locator
FROM book_samples
WHERE book_sample_id = 2
FOR UPDATE;
SELECT misc
INTO v_blob_locator
FROM book_samples
WHERE book_sample_id = 2
FOR UPDATE;
v_string_length := DBMS_LOB.GETLENGTH(v_clob_locator);
-- v_ammount must equal to BLOB size, otherwise ORA-22993 will return
v_amount := DBMS_LOB.GETLENGTH(v_blob_locator);
CONVERT_ME(v_clob_or_blob,
v_blob_locator,
v_string_length := DBMS_LOB.GETLENGTH(v_clob_locator);
SELECT description
INTO v_string
FROM book_samples
WHERE book_sample_id = 2;
/* BFILE – FILEEXISTS */
-- This function tests whether a file exists by the name specified in the
insert statement
v_exists := DBMS_LOB.FILEEXISTS(v_bfile);
IF v_exists = 0
THEN
DBMS_OUTPUT.PUT_LINE ('The file does not exists in the directory
specified');
ELSE
DBMS_OUTPUT.PUT_LINE ('The file exists and the directory valid!');
DECLARE
v_bfile BFILE;
BEGIN
SELECT bfile_description
INTO v_bfile
FROM book_samples
WHERE book_sample_id = 1;
CHECK_FILE(v_bfile);
END;
/
/* BFILE – FILEOPEN/OPEN */
-- Oracle recommends that OPEN be used instead of FILEOPEN.
PROCEDURE OPEN
Argument Name Type In/Out Default?
––––––––––––––– –––––––––––- ––– ––––
FILE_LOC BINARY FILE LOB IN/OUT
OPEN_MODE BINARY_INTEGER IN DEFAULT
/* BFILE – FILEISOPEN/ISOPEN */
-- ISOPEN should be used in place of FILEISOPEN when possible.
CREATE OR REPLACE PROCEDURE CHECK_STATUS (
v_bfile IN BFILE)
AS
v_isopen PLS_INTEGER := 0;
BEGIN
v_isopen := DBMS_LOB.ISOPEN(v_bfile);
IF v_isopen = 0
THEN
DBMS_OUTPUT.PUT_LINE ('The file is not open. You must open the');
ELSE
DBMS_OUTPUT.PUT_LINE ('The file is open already.');
END IF;
END;
/
DECLARE
v_bfile BFILE;
BEGIN
SELECT bfile_description
INTO v_bfile
FROM book_samples
WHERE book_sample_id = 1;
CHECK_STATUS(v_bfile);
END;
/
CURSOR cur_bfile IS
SELECT bfile_description
FROM book_samples;
BEGIN
DBMS_OUTPUT.PUT_LINE('Open all BFILEs in the table');
OPEN cur_bfile;
LOOP
FETCH cur_bfile INTO v_bfile;
EXIT WHEN cur_bfile%NOTFOUND;
BEGIN
v_counter := v_counter + 1;
DBMS_LOB.OPEN(v_bfile);
v_isopen := DBMS_LOB.ISOPEN(v_bfile);
IF v_isopen = 0
THEN
DBMS_OUTPUT.PUT_LINE ('File number '||v_counter||' is closed');
ELSE
DBMS_OUTPUT.PUT_LINE ('File number '||v_counter||' is open');
END IF;
END;
END LOOP;
CLOSE cur_bfile;
DBMS_LOB.FILECLOSEALL();
DBMS_OUTPUT.PUT_LINE(' DONE ');
END;
/
/* LOADFROMFILE/LOADCLOBFROMFILE/LOADBLOBFROMFILE */
load file contents to CLOB and BLOB columns. It is
recommended that LOADCLOBFROMFILE and LOADBLOBFROMFILE be used for
their specific datatypes rather than using the generic overloaded
LOADFROMFILE.
PROCEDURE LOADBLOBFROMFILE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
DEST_LOB BLOB IN/OUT
SRC_BFILE BINARY FILE LOB IN
AMOUNT NUMBER(38) IN
set serveroutput on
DECLARE
v_dest_blob BLOB;
v_dest_clob CLOB;
v_source_locator1 BFILE := BFILENAME('BOOK_SAMPLES_LOC',
'bfile_example.pdf');
v_source_locator2 BFILE := BFILENAME('BOOK_SAMPLES_LOC',
'bfile_example.txt');
v_source_offset NUMBER := 1;
v_dest_offset NUMBER := 1;
v_lang_context NUMBER := DBMS_LOB.DEFAULT_LANG_CTX;
v_warning PLS_INTEGER;
BEGIN
-- Empty the description and misc columns
UPDATE book_samples
SET description = EMPTY_CLOB(), misc = EMPTY_BLOB()
WHERE book_sample_id = 1;
v_dest_offset := 1;
v_source_offset := 1;
DBMS_LOB.LOADCLOBFROMFILE(v_dest_clob,
v_source_locator2,
DBMS_LOB.LOBMAXSIZE,
v_dest_offset,
v_source_offset,
DBMS_LOB.DEFAULT_CSID,
v_lang_context,
v_warning);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
DBMS_LOB.CLOSE(v_source_locator1);
DBMS_LOB.CLOSE(v_source_locator2);
DBMS_LOB.CLOSE(v_dest_blob);
DBMS_LOB.CLOSE(v_dest_clob);
END;
/
Performance Considerations
-- 2) create Wordlist
BEGIN
ctx_ddl.create_preference ('lob_wordlist', 'basic_wordlist');
ctx_ddl.set_attribute ('lob_wordlist', 'substring_index', 'true');
END;
/
Setup
• Database Side
/* Create Schema cotaining target objects */
create tablespace hrstbs ;
create user hrs identified by h
default tablespace hrstbs
quota unlimited on hrstbs ;
grant create table, create view, create procedure, create session, create
sequence, plustrace to hrs;
grant execute on DBMS_LOCK to hrs;
grant execute on DBMS_RANDOM to hrs;
• OS side: Unix
-- in a folder create the following scripts
-- (1) loadcpu1.sh
#!/bin/bash
# apply CPU load on Oracle DB
# parameters: 1 connections, 2 Iterations
users=$1
SRVC="hrserv"
UNPW="hrs/h"
SQLCMD="/home/oracle/scripts/load/loadcpu1.sql"
x=1
y=$users
ITER=$2
-- (2) loadcpu1.sql
begin
hrs.LOAD_GENERATOR.SpinCPUs(&1);
end;
/
exit
-- (3) loadcpu2.sh
#!/bin/bash
# apply CPU+DB Calls load on Oracle DB
# parameters: 1 connections, 2 Iterations
users=$1
SRVC="hrserv"
UNPW="hrs/h"
SQLCMD="/home/oracle/scripts/load/loadcpu2.sql"
x=1
y=$users
ITER=$2
while [ $x -le $y ]
do
sqlplus -s $UNPW@$SRVC @$SQLCMD $ITER &
x=`expr $x + 1`
done
-- (4) loadcpu2.sql
begin
hrs.LOAD_GENERATOR.SpinCycles(&1);
end;
/
exit
-- (5) loadquery.sh
#!/bin/bash
# apply random queries load on Oracle DB
# parameters: 1 connections, 2 Iterations, 3 rows in names
users=$1
SRVC="hrserv"
UNPW="hrs/h"
SQLCMD="/home/oracle/scripts/load/loadquery.sql"
x=1
y=$users
ITER=$2
MAX=$3
while [ $x -le $y ]
do
sqlplus -s $UNPW@$SRVC @$SQLCMD $ITER $MAX &
x=`expr $x + 1`
done
-- (7) loaddml.sh
#!/bin/bash
# apply random DML load on Oracle DB
# parameters: 1 connections, 2 Iterations, 3 rows in names
users=$1
SRVC="hrserv"
UNPW="hrs/h"
SQLCMD="/home/oracle/scripts/load/loaddml.sql"
x=1
y=$users
ITER=$2
MAX=$3
while [ $x -le $y ]
do
sqlplus -s $UNPW@$SRVC @$SQLCMD $ITER $MAX &
x=`expr $x + 1`
done
-- (8) loaddml.sql
begin
hrs.LOAD_GENERATOR.RANDOMDML (&1, &2);
end;
/
exit
• OS side: Windows
-- in a folder create the following scripts
-- (1) loadcpu1.bat
REM apply CPU load on Oracle DB
REM parameters: 1 connections, 2 Iterations
set users=%1
set SRVC=hrserv
set UNPW=hrs/h
set SQLCMD=C:\TEMP\load\loadcpu1.sql
set x=1
set y=%users%
set ITER=%2
-- (2) loadcpu1.sql
begin
hrs.LOAD_GENERATOR.SpinCPUs(&1);
end;
/
-- (3) loadcpu2.bat
REM apply CPU+DB Calls load on Oracle DB
REM parameters: 1 connections, 2 Iterations
set users=%1
set SRVC=hrserv
set UNPW=hrs/h
set SQLCMD=C:\TEMP\load\loadcpu2.sql
set x=1
set y=%users%
set ITER=%2
-- (4) loadcpu2.sql
begin
hrs.LOAD_GENERATOR.SpinCycles(&1);
end;
/
exit
-- (5) loadquery.bat
REM apply random queries load on Oracle DB
REM parameters: 1 connections, 2 Iterations, 3 rows in names
set users=%1
set SRVC=hrserv
set UNPW=hrs/h
set SQLCMD=C:\TEMP\load\loadquery.sql
set x=1
set y=%users%
set ITER=%2
set MAX=%3
-- (6) loadquery.sql
begin
hrs.LOAD_GENERATOR.RANDOMQUERY (&1, &2);
end;
/
exit
-- (7) loaddml.bat
REM apply random DML load on Oracle DB
REM parameters: 1 connections, 2 Iterations, 3 rows in names
set users=%1
set SRVC=hrserv
-- (8) loaddml.sql
begin
hrs.LOAD_GENERATOR.RANDOMDML (&1, &2);
end;
/
exit
Setup
• Database Side
/* Create sa Schema (if not already there) */
create tablespace satbs
datafile 'C:\ORACLE\ORADATA\ORA11G\satbs1.dbf' size 100m
autoextend on next 12m maxsize 4g
extent management local
segment space management auto ;
-- the package
/* Create Random Load Package */
-- Generates various different loads on the target database
CREATE OR REPLACE PACKAGE LOAD_GENERATOR
IS
-- global vars
G_MAX_ORDER_ID NUMBER;
G_MIN_ORDER_ID NUMBER;
VALUES(V_ORDER_ID,M,V_PROD_IDS(V_PRODUCT_ID),V_PROD_PRICE,V_QUANTITY );
M := M + 1 ;
EXCEPTION
WHEN OTHERS THEN
IF UPPER(SQLERRM) LIKE '%ORDER_ITEMS_UK%' THEN
NULL;
ELSE
RAISE;
END IF;
END ;
END LOOP; -- X loop
UPDATE ORDERS SET ORDER_TOTAL = V_ORDER_TOTAL WHERE ORDER_ID =
V_ORDER_ID;
IF MOD(I,100) = 0 THEN
COMMIT;
END IF;
END LOOP; -- I loop
COMMIT;
END INSERT_ORDERS;
PROCEDURE SpinCPUs (P_ITERATION IN NUMBER)
IS
N NUMBER;
BEGIN
FOR I IN 1.. P_ITERATION LOOP
-- pure CPU processing (no physical or logical read)
N := SQRT(ROUND(DBMS_RANDOM.VALUE(1,1000)));
-- DBMS_LOCK.SLEEP(round(DBMS_RANDOM.VALUE(0.01,0.05),2)); -- in seconds
END LOOP;
END SpinCPUs;
PROCEDURE RandomQuery(P_ITERATION IN NUMBER)
IS
V_START NUMBER;
V_END NUMBER;
N NUMBER;
BEGIN
V_END := G_MAX_ORDER_ID;
V_START := ROUND(DBMS_RANDOM.VALUE(G_MIN_ORDER_ID,G_MAX_ORDER_ID));
FOR I IN 1.. P_ITERATION LOOP
FOR R IN (SELECT O.ORDER_ID, O.ORDER_DATE, C.CUST_LAST_NAME,
O.ORDER_TOTAL
FROM ORDERS O , CUSTOMERS C
-- initial data
exec load_generator.insert_orders(100000);
exec dbms_stats.gather_schema_stats('SA');
• OS side: Unix
• OS side: Windows
-- in a folder create the following scripts
-- (1) loadcpu.bat
REM apply CPU load on Oracle DB
REM parameters: 1 connections, 2 Iterations
set users=%1
set SRVC=ora11g
set UNPW=sa/s
set SQLCMD=C:\TEMP\load\loadcpu.sql
set x=1
set y=%users%
set ITER=%2
-- (2) loadcpu1.sql
begin
hrs.LOAD_GENERATOR.SpinCPU(&1);
end;
/
exit
-- (3) loadquery.bat
REM apply random queries load on Oracle DB
REM parameters: 1 connections, 2 Iterations
set users=%1
set SRVC=ora11g
set UNPW=sa/s
-- (4) loadquery.sql
begin
hrs.LOAD_GENERATOR.RANDOMQUERY(&1);
end;
/
exit
-- (5) loaddml.bat
REM apply random DML load on Oracle DB
REM parameters: 1 connections, 2 Iterations, 3 rows in names
set users=%1
set SRVC=ora11g
set UNPW=sa/s
set SQLCMD=C:\TEMP\load\loaddml.sql
set x=1
set y=%users%
set ITER=%2
-- (6) loaddml.sql
begin
sa.LOAD_GENERATOR.RANDOMDML (&1);
end;
/
exit
Merge Command
/* Marge Command */
MERGE INTO products p /* Destination table
USING product_changes s /* Source table
ON (p.prod_id = s.prod_id) /* Search/join condition
WHEN MATCHED THEN UPDATE /* Update if join
SET p.prod_list_price = s.prod_new_price
WHERE p.prod_status <> 'EXPIRED' /* Conditional update
WHEN NOT MATCHED THEN
INSERT /* Insert if not join
SET p.prod_list_price = s.prod_new_price
WHERE s.prod_status <> 'EXPIRED' /* Conditional insert
Multitable Inserts
/* Multitable Inserts */
-- unconditional
INSERT ALL
INTO target1 VALUES (product_id, customer_id, sysdate, product_quantity)
INTO target2 VALUES (product_id,sysdate,product_price,product_discount)
SELECT s.product_id, s.customer_id, sysdate, s.product_quantity,
s.product_price, s.product_discount
FROM source s;
Parallel Insert
/* Parallel loading into table */
-- must before the hint
ALTER SESSION ENABLE PARALLEL DML;
-- then use the hint
INSERT /*APPEND NOLOGGING PARALLEL */
INTO sales_data
SELECT product_id, customer_id, TRUNC(sales_date),
discount_rate, sales_quantity, sale_price
FROM sales_history;
-- if triggers are there, hint won't be used
DECLARE
N NUMBER;
M NUMBER;
BEGIN
DBMS_OUTPUT.ENABLE(100000);
FOR S IN ( SELECT USERNAME FROM SCHEMA_NAMES WHERE USERNAME <>'MOL' ORDER BY
1) LOOP
FOR O in ( SELECT TABLE_NAME FROM DBA_TABLES@OLDORA11G WHERE OWNER =
S.USERNAME ) LOOP
BEGIN
N := 0;
M := 0;
EXECUTE IMMEDIATE 'SELECT COUNT(ROWID) FROM ' || S.USERNAME ||'."'||
O.TABLE_NAME || '"@OLDORA11G' INTO N;
EXECUTE IMMEDIATE 'SELECT COUNT(ROWID) FROM ' || S.USERNAME ||'."'||
O.TABLE_NAME || '"' INTO M;
IF M <> N THEN
DBMS_OUTPUT.PUT_LINE(S.USERNAME || CHR(9) || O.TABLE_NAME);
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(S.USERNAME || CHR(9) || O.TABLE_NAME);
RAISE;
END;
END LOOP;
END LOOP;
END;
/
RAC
1) Edit the pic on page 274
2) >>continue from here