Você está na página 1de 57

QUERIES

STATUS

Startup time

select to_char(startup_time, 'HH24:MI DD-MON-YY') "Startup time"


from v$instance
/

How large is the database

col "Database Size" format a20


col "Free space" format a20
col "Used space" format a20
select round(sum(used.bytes) / 1024 / 1024 / 1024 ) || ' GB' "Database Size"
, round(sum(used.bytes) / 1024 / 1024 / 1024 ) -
round(free.p / 1024 / 1024 / 1024) || ' GB' "Used space"
, round(free.p / 1024 / 1024 / 1024) || ' GB' "Free space"
from (select bytes from v$datafile
union all
select bytes from v$tempfile
union all
select bytes from v$log) used,
(select sum(bytes) as p from dba_free_space) free
group by free.p
/

Distribution of objects and data

Which schemas are taking up all of the space


set pages 999
col "size MB" format 999,999,999
col "Objects" format 999,999,999
select obj.owner "Owner",obj_cnt "Objects",
decode(seg_size, NULL, 0, seg_size) "size MB"
from (select owner, count(*) obj_cnt
from dba_objects group by owner) obj,
(select owner, ceil(sum(bytes)/1024/1024) seg_size
from dba_segments group by owner) seg
where obj.owner = seg.owner(+)
order by 3 desc ,2 desc, 1
/
Show the ten largest objects in the database

Col owner format a15


Col segment_name format a30
Col segment_type format a15
Col mb format 999,999,999
select owner,segment_name,segment_type,mb
from(select owner,segment_name,segment_type,bytes / 1024 / 1024 "MB"
from dba_segments
order by bytes desc
)
where rownum < 11
/

Is java installed in the database?

This will return 9000'ish if it is...


select count(*)
from all_objects
where object_type like '%JAVA%'
and owner = 'SYS'
/

Display character set information

select * from nls_database_parameters


/

Show all used features

select name
, detected_usages
from dba_feature_usage_statistics
where detected_usages > 0
/
SESSION
Show all connected users

set lines 100 pages 999


col ID format a15
select username,sid || ',' || serial# "ID",status,
last_call_et "Last Activity"
from v$session
where username is not null
order by status desc,
last_call_et desc
/

Time since last user activity

set lines 100 pages 999


select username
, floor(last_call_et / 60) "Minutes"
, status
from v$session
where username is not null
order by last_call_et
/

Sessions sorted by logon time

set lines 100 pages 999


col ID format a15
col osuser format a15
col login_time format a14
select username
, osuser
, sid || ',' || serial# "ID"
, status
, to_char(logon_time, 'hh24:mi dd/mm/yy') login_time
, last_call_et
from v$session
where username is not null
order by login_time
/

Show user info including os pid

col "SID/SERIAL" format a10


col username format a15
col osuser format a15
col program format a40
select s.sid || ',' || s.serial# "SID/SERIAL"
, s.username
, s.osuser
, p.spid "OS PID"
, s.program
from v$session s
, v$process p
Where s.paddr = p.addr
order by to_number(p.spid)
/

Show a users current sql

Select sql_text
from v$sqlarea
where (address, hash_value) in
(select sql_address, sql_hash_value
from v$session
where username like '&username')
/

Session status associated with the specified os process id

select s.username
, s.sid
, s.serial#
, p.spid
, last_call_et
, status
from V$SESSION s
, V$PROCESS p
where s.PADDR = p.ADDR
and p.spid='&pid'
/

All active sql

set feedback off


set serveroutput on size 9999
column username format a20
column sql_text format a55 word_wrapped
begin
for x in
(select username||'('||sid||','||serial#||') ospid = '|| process ||
' program = ' || program username,
to_char(LOGON_TIME,' Day HH24:MI') logon_time,
to_char(sysdate,' Day HH24:MI') current_time,
sql_address,
sql_hash_value
from v$session
where status = 'ACTIVE'
and rawtohex(sql_address) <> '00'
and username is not null ) loop
for y in (select sql_text
from v$sqlarea
where address = x.sql_address ) loop
if ( y.sql_text not like '%listener.get_cmd%' and
y.sql_text not like '%RAWTOHEX(SQL_ADDRESS)%' ) then
dbms_output.put_line( '--------------------' );
dbms_output.put_line( x.username );
dbms_output.put_line( x.logon_time || ' ' || x.current_time || ' SQL#=' ||
x.sql_hash_value);
dbms_output.put_line( substr( y.sql_text, 1, 250 ) );
end if;
end loop;
end loop;
end;
/

Display any long operations

set lines 100 pages 999


col username format a15
col message format a40
col remaining format 9999
select username
, to_char(start_time, 'hh24:mi:ss dd/mm/yy') started
, time_remaining remaining
, message
from v$session_longops
where time_remaining = 0
order by time_remaining desc
/

List open cursors per user

set pages 999


select sess.username
, sess.sid
, sess.serial#
, stat.value cursors
from v$sesstat stat
, v$statname sn
, v$session sess
where sess.username is not null
and sess.sid = stat.sid
and stat.statistic# = sn.statistic#
and sn.name = 'opened cursors current'
order by value
/

Or alternatively...
set lines 100 pages 999
select count(hash_value) cursors
, sid
, user_name
from v$open_cursor
group by
sid
, user_name
order by
cursors
/
INIT PARAMETERS
Show latent parameter changes

select name
, value
from v$parameter
where ismodified != 'FALSE'
/

Show non-default parameters

set pages 999 lines 100


col name format a30
col value format a50
select name
, value
from v$parameter
where isdefault = 'FALSE'
and value is not null
order by name
/

or for name='parameter' style...


set pages 999 lines 100
select name || '=' || decode(type, 2, '''') || value
|| decode(type, 2, '''') parameter
from v$parameter
where isdefault = 'FALSE'
and value is not null
order by name
/

Reset/Unset a spfile parameter

Setting a parameter to =' ' often isn't enough. Do this instead...


alter system reset <parameter> scope=spfile sid='*'
/

The sid='*' bit is always necessary, even in non RAC database.

USER
List users

set pages 999 lines 100


col username format a20
col status format a8
col tablespace format a20
col temp_ts format a20
select username
, account_status status
, created
, default_tablespace tablespace
, temporary_tablespace temp_ts
from dba_users
order by username
/

Lock or unlock a user

alter user <username> account lock;

And to unlock...

alter user <username> account unlock;

ROLE
Find a role

select *
from dba_roles
where role like '&role'
/

Show what roles are granted to a user

select grantee
, granted_role
, admin_option
from dba_role_privs
where grantee like upper('&username')
/

Show what system privileges are granted to a role

select privilege
, admin_option
from role_sys_privs
where role like '&role'
/

Show what table privileges are granted to a role

select owner || '.' || table_name "TABLE"


, column_name
, privilege
, grantable
from role_tab_privs
where role like '&role'
/

Administration - ASM

• Check if css is running/working


• Display disk-groups
• Show disk space usage
• Create a disk group
• Add a disk to a group
• Drop a disk group
• Is ASM performing a balancing operation
• Check the internal consistency of a diskgroup

Check if css is running/working

crsctl check cssd

Display disk-groups

set lines 100


col name format a10
col path format a30
select name
, group_number
, disk_number
, mount_status
, state
, path
from v$asm_disk
order by group_number
/
note. A group number of zero his indicates that a disk is available but hasn't yet been assigned to a
disk group.

Show disk space usage

select name
, group_number
, disk_number
, total_mb
, free_mb
from v$asm_disk
order by group_number
/

Create a disk group

create diskgroup data1


external redundancy
disk '/dev/raw/raw1'
/

or with multiple raw partitions...


multiple disks
create diskgroup data2
external redundancy
disk '/dev/raw/raw2'
, '/dev/raw/raw3'
/

or with multiple fail groups...


create diskgroup data3
normal redundancy
failgroup controller1 disk '/dev/raw/raw4'
failgroup controller2 disk '/dev/raw/raw6'
/

Add a disk to a group

alter diskgroup data1


add disk '/dev/raw/raw4'
/

Wildcards can be used for raw device names (eg. raw*)

Drop a disk group

drop diskgroup '<name>'


/

Is ASM performing a balancing operation

select *
from v$asm_operation
/

Mount/dismount disk groups


alter diskgroup all mount

alter diskgroup data1 mount

alter diskgroup all dismount

alter diskgroup data1 dismount

Check the internal consistency of a diskgroup

alter diskgroup data1 check all


/
Administration - RAC 10gR2

• Start, stop and check CRS (Cluster Ready Services)


• Start/stop nodeapps
• Start/stop asm
• Start/stop a database (all nodes)
• Start/stop an individual instance
• Check the VIP config
• Change the VIP address, subnetmask or interface
• Locate the voting disk
• Retrive OCR (Oracle Cluster Registry) information
• To prevent a database starting at boot time
• Change the private interconnect subnet

Start, stop and check CRS (Cluster Ready Services)

Note. Start/stop need to be run as root from the CRS home.

Start CRS
crsctl start crs

Stop CRS
crsctl stop crs

Check CRS's status


crsctl check crs

See the status of the various services


crs_stat -t

Start/stop nodeapps

srvctl start nodeapps -n <node name>

srvctl stop nodeapps -n <node name>

Start/stop asm

srvctl start asm -n <node name>

srvctl stop asm -n <node name>


Start/stop a database (all nodes)

srvctl start database -d <database name>

srvctl stop database -d <database name>

Start/stop an individual instance

srvctl start instance -d <database name> -i <instance name>

srvctl stop instance -d <database name> -i <instance name>

Check the VIP config

srvctl config nodeapps -n <node> -a -g -s -l

Change the VIP address, subnetmask or interface

srvctl stop nodeapps -n <node1>


srvctl stop nodeapps -n <node2>
srvctl modify nodeapps -n <node1> -A <ip_address>/<net mask>/<interface>
srvctl modify nodeapps -n <node2> -A <ip_address>/<net mask>/<interface>
srvctl start nodeapps -n <node1>
srvctl start nodeapps -n <node2>

Locate the voting disk

crsctl query css votedisk

Retrive OCR (Oracle Cluster Registry) information

ocrcheck

To prevent a database starting at boot time

srvctl disable database -d <database name>

Change the private interconnect subnet


First find the interface which is in use as the interconnect - run as root from the crs home:
oifcfg getif

Make a note of the interface name (eth1 in the following example), then
run the following:
oifcfg delif -global eth1
oifcfg setif -global eth1/<your new subnet>:cluster_interconnect

Administration - Job Scheduler

• List scheduled jobs


• Submit a job
• Remove a job
• Reset a broken job
• Add a program to the 10g scheduler (os program)
• Add a program to the 10g scheduler (stored procedure)
• Schedule a 10g job

List scheduled jobs

set lines 100 pages 999


col schema_user format a15
col fails format 999
select job
, schema_user
, to_char(last_date, 'hh24:mi dd/mm/yy') last_run
, to_char(next_date, 'hh24:mi dd/mm/yy') next_run
, failures fails
, broken
, substr(what, 1, 15) what
from dba_jobs
order by 4
/

Submit a job

dbms_job.submit('<code>', <start time>, <repeat time>, TRUE);

For example:
declare
job_id number;
begin
dbms_job.submit(
job_id
, 'andy.daily_data_clense'
, trunc(sysdate+1)+22/24
, 'sysdate+1'
, true);
end;
/

This will run a stored procedure called 'daily_data_clense' each day at 10pm.

Remove a job

You need to be connected as the user who owns the job


exec dbms_job.remove(<job number>);

Reset a broken job

You need to be connected as the user who owns the job


exec dbms_job.broken(<job number>, FALSE);

Add a program to the 10g scheduler (os program)

begin
dbms_scheduler.create_program(
program_name=>'ANDY.job_test',
program_action=>'/home/oracle/andyb/job_test.sh',
program_type=>'EXECUTABLE',
comments=>'test job',
enabled=>TRUE);
end;
/

Add a program to the 10g scheduler (stored procedure)

begin
dbms_scheduler.create_program(
program_name=>'ANDY.job_test',
program_action=>'andy.job_test',
program_type=>'STORED_PROCEDURE',
comments=>'test program',
enabled=>TRUE);
end;
/

Schedule a 10g job

begin
dbms_sheduler.create_job(
job_name=>'andy.andy_job_test',
program_name=>'andy.job_test',
start_date=>
)

Administration - Recycle bin

• Display the contents of the recycle bin


• Empty the recycle bin
• Drop an object with out putting it in the recycle bin

Display the contents of the recycle bin

show recyclebin

Empty the recycle bin

purge recyclebin

Drop an object with out putting it in the recycle bin

drop <object_type> <object_name> purge;

Structure - Tablespace

• Tablespace usage
• Show the files that comprise a tablespace
• Tablespaces >80% full
• User quotas on all tablespaces
• List all objects in a tablespace
• Show all tablespaces used by a user
• Create a temporary tablespace
• Alter a databases default temporary tablespace
• Show segments that are approaching max_extents
• List the contents of the temporary tablespace(s)

Tablespace usage

set pages 999


col tablespace_name format a40
col "size MB" format 999,999,999
col "free MB" format 99,999,999
col "% Used" format 999
select tsu.tablespace_name, ceil(tsu.used_mb) "size MB"
, decode(ceil(tsf.free_mb), NULL,0,ceil(tsf.free_mb)) "free MB"
, decode(100 - ceil(tsf.free_mb/tsu.used_mb*100), NULL, 100,
100 - ceil(tsf.free_mb/tsu.used_mb*100)) "% used"
from (select tablespace_name, sum(bytes)/1024/1024 used_mb
from dba_data_files group by tablespace_name union all
select tablespace_name || ' **TEMP**'
, sum(bytes)/1024/1024 used_mb
from dba_temp_files group by tablespace_name) tsu
, (select tablespace_name, sum(bytes)/1024/1024 free_mb
from dba_free_space group by tablespace_name) tsf
where tsu.tablespace_name = tsf.tablespace_name (+)
order by 4
/

Show the files that comprise a tablespace

set lines 100


col file_name format a70
select file_name
, ceil(bytes / 1024 / 1024) "size MB"
from dba_data_files
where tablespace_name like '&TSNAME'
/

Tablespaces >80% full

set pages 999 lines 100


col tablespace_name format a40
col "size MB" format 999999999
col "% Used" format 999
col "80%" format 999999
col "75%" format 999999
select tsu.tablespace_name
, ceil(tsu.used_mb) "size MB"
, 100 - floor(tsf.free_mb/tsu.used_mb*100) "% Used"
, (tsu.used_mb / 100) * (20 - floor(tsf.free_mb/tsu.used_mb*100)) "80%"
, (tsu.used_mb / 100) * (25 - floor(tsf.free_mb/tsu.used_mb*100)) "75%"
from (select tablespace_name, sum(bytes)/1024/1024 used_mb
from dba_data_files group by tablespace_name) tsu
, (select tablespace_name, sum(bytes)/1024/1024 free_mb
from dba_free_space group by tablespace_name) tsf
where tsu.tablespace_name = tsf.tablespace_name (+)
and 100 - floor(tsf.free_mb/tsu.used_mb*100) >= 80
order by 3,4,5
/

User quotas on all tablespaces

col quota format a10


select username
, tablespace_name
, decode(max_bytes, -1, 'unlimited'
, ceil(max_bytes / 1024 / 1024) || 'M' ) "QUOTA"
from dba_ts_quotas
where tablespace_name not in ('TEMP')
/

List all objects in a tablespace

set pages 999


col owner format a15
col segment_name format a40
col segment_type format a20
select owner
, segment_name
, segment_type
from dba_segments
where lower(tablespace_name) like lower('%&tablespace%')
order by owner, segment_name
/

Show all tablespaces used by a user

select tablespace_name
, ceil(sum(bytes) / 1024 / 1024) "MB"
from dba_extents
where owner like '&user_id'
group by tablespace_name
order by tablespace_name
/

Create a temporary tablespace

create temporary tablespace temp


tempfile '<file_name>' size 500M
/

Alter a databases default temporary tablespace

alter database default temporary tablespace temp


/

Show segments that are approaching max_extents

col segment_name format a40


select owner
, segment_type
, segment_name
, max_extents - extents as "spare"
, max_extents
from dba_segments
where owner not in ('SYS','SYSTEM')
and (max_extents - extents) < 10
order by 4
/

To change maxextents
alter <segment_type> <segment_name> storage(maxextents 150);

List the contents of the temporary tablespace(s)

set pages 999 lines 100


col username format a15
col mb format 999,999
select su.username
, ses.sid
, ses.serial#
, su.tablespace
, ceil((su.blocks * dt.block_size) / 1048576) MB
from v$sort_usage su
, dba_tablespaces dt
, v$session ses
where su.tablespace = dt.tablespace_name
and su.session_addr = ses.saddr
/

Structure - Objects

• Find an object
• Invalid objects
• Show the size of an object
• All objects owned by a user
• Source code of a procedure
• Get an objects ddl (9i onwards)
• Display compilation errors and warnings
• Find all tables containing the specified column
• List all tables owned by a user sorted by size

Find an object

set pages 999


col owner format a15
col object_name format a40
col object_type format a20
select owner
, object_name
, object_type
from dba_objects
where lower(object_name) like lower('%&object%')
order by owner, object_type, object_name
/
Invalid objects

List invalid objects...


set lines 200 pages 999
col "obj" format a40
select owner || '.' || object_name "obj",
object_type
from dba_objects
where status = 'INVALID'
/

Recompile all invalid objects...


@?/rdbms/admin/utlrp.sql

Show the size of an object

col segment_name format a20


select segment_name
, bytes "SIZE_BYTES"
, ceil(bytes / 1024 / 1024) "SIZE_MB"
from dba_segments
where segment_name like '&obj_name'
/

All objects owned by a user

col object_name format a40


select object_name
, object_type
from dba_objects
where owner = '&user'
order by object_type, object_name
/

Source code of a procedure

select text
from dba_source
where owner = 'ANDY'
and name = 'FILE_TEST'
and type = 'PACKAGE BODY'
order by line
/

Get an objects ddl (9i onwards)


Note. Works for 9i and newer.
Parameters: OBJECT_TYPE, OBJECT_NAME, SCHEMA
set pagesize 0
set long 90000
select dbms_metadata.get_ddl('TABLE','TABLE_A','ANDY') from dual;

Display compilation errors and warnings

show errors
show errors view <veiw_name>
show errors procedure <proc_name>

select * from dba_errors;

Find all tables containing the specified column

set pages 999 lines 100


col tab format a60
col column_name format a20
select owner || '.' || table_name as tab
, column_name
from dba_tab_columns
where column_name like upper('&col')
/

List all tables owned by a user sorted by size

set lines 100 pages 999


col segment_name format a40
col mb format 999,999,999
select segment_name
, ceil(sum(bytes) / 1024 / 1024) "MB"
from dba_segments
where owner like '&user'
and segment_type = 'TABLE'
group by segment_name
order by ceil(sum(bytes) / 1024 / 1024) desc
/

Structure - Indexes

• Index info by table


• Show indexed columns

Index info by table


select i.index_name
, i.tablespace_name
, ceil(s.bytes / 1048576) "Size MB"
from dba_indexes i
, dba_segments s
where i.index_name = s.segment_name
and table_name like '&table'
order by 2, 1
/

Show indexed columns

select column_name
from dba_ind_columns
where index_name = '&index'
order by column_position
/

Structure - Files

• Display all datafiles, tempfiles and logfiles (and their sizes)


• Quick datafile health check
• Show directories that contain datafiles
• List autoextensible datafiles
• Turn autoextend off for all datafiles
• Move files between disks
• List controlfiles
• Create an OS command for every file in the database
• Find duplicate filenames
• List files that are in hot-backup mode

Display all datafiles, tempfiles and logfiles (and their sizes)

set lines 100 pages 999


col name format a50
select name, bytes
from (select name, bytes
from v$datafile
union all
select name, bytes
from v$tempfile
union all
select lf.member "name", l.bytes
from v$logfile lf
, v$log l
where lf.group# = l.group#
union all
select name, 0
from v$controlfile) used
, (select sum(bytes) as p
from dba_free_space) free
/

Quick datafile health check

You should only see online and system (maybe read-only too)
select distinct status from v$datafile
/

Show directories that contain datafiles

select distinct substr(name, 1, instr(name, '/', -1)) DIR


from v$datafile
order by 1
/

List autoextensible datafiles

select file_name
from dba_data_files
where autoextensible = 'YES'
/

Turn autoextend off for all datafiles

select 'alter database datafile ''' || file_name || ''' autoextend off;'


from dba_data_files
/

Move files between disks

set trimspool on wrap off


set heading off
set verify off
set pages 1000 lines 100

spool rename.sql

select 'alter database rename file ''' ||


name || ''' to ''' ||
replace(name || ''';', '/u01', '/u02')
from v$datafile
/

select 'alter database rename file ''' ||


member || ''' to ''' ||
replace(member || ''';', '/u01', '/u02')
from v$logfile
/

spool off

List controlfiles

select name
from v$controlfile
/

Create an OS command for every file in the database

The example deletes all files


select 'rm ' || name
from (select name
from v$datafile
union all
select name
from v$tempfile
union all
select member
from v$logfile
union all
select name
from v$controlfile
)
/

Find duplicate filenames

Searches for files with the same name in all directories


select count(substr(name, instr(name, '/', -1) + 1, 999)) "total"
, count(distinct substr(name, instr(name, '/', -1) + 1, 999)) "distinct"
from v$datafile
/

List files that are in hot-backup mode

set lines 100 pages 999


col name format a60
select df.name
, b.status
, to_char(time, 'hh24:mi:ss dd/mm/yyyy') time
from v$datafile df
, v$backup b
where df.file# = b.file#
and b.status = 'ACTIVE'
order by b.file#
/

Structure - Redo Logs

• Remove drop
• add logfile members
• List members and sizes

Remove drop

alter database drop logfile member '<filename>';

add logfile members

alter database add logfile member '<filename>' to group <group>;

List members and sizes

col member format a60


col "Size MB" format 9,999,999
select lf.member
, ceil(lg.bytes / 1024 / 1024) "Size MB"
from v$logfile lf
, v$log lg
where lg.group# = lf.group#
order by 1
/

Structure - Undo
• Converting from Rollback to Undo
• Display the rollback segments
• Alter undo retention
• What's in undo
• Is anything rolling back at the moment?

Display the rollback segments

select segment_name
, status
from dba_rollback_segs
/

Alter undo retention

alter system set undo_retention=500 scope=memory;

Note. This is in seconds

What's in undo

select tablespace_name
, status
, count(*) as HOW_MANY
from dba_undo_extents
group by tablespace_name
, status
/

Is anything rolling back at the moment?

Look for the used_ublk value decreasing. If it is, the session connected with it is rolling back.
When it reaches zero, rollback is complete.
set lines 100 pages 999
col username format a15
col command format a20
select ses.username
, substr(ses.program, 1, 19) command
, tra.used_ublk
from v$session ses
, v$transaction tra
where ses.saddr = tra.ses_addr
/

Structure - Constraints

• Show all constraints on a table


• List tables that are using the specified table as a foreign key
• Produce a list of disabled fk constraints
• Produce enable statements all disabled fk constraints
• List parent tables that may need fixing/re-importing
• List missing foriegn key values
• Show all table constraints for a user

Show all constraints on a table

col type format a10


col cons_name format a30
select decode(constraint_type,
'C', 'Check',
'O', 'R/O View',
'P', 'Primary',
'R', 'Foreign',
'U', 'Unique',
'V', 'Check view') type
, constraint_name cons_name
, status
, last_change
from dba_constraints
where owner like '&owner'
and table_name like '&table_name'
order by 1
/

List tables that are using the specified table as a foreign key

set lines 100 pages 999


select a.owner
, a.table_name
, a.constraint_name
from dba_constraints a
, dba_constraints b
where a.constraint_type = 'R'
and a.r_constraint_name = b.constraint_name
and a.r_owner = b.owner
and b.owner = '&table_owner'
and b.table_name = '&table_name'
/

Same as above, but produces 'disable constraint' statements


set lines 100 pages 999
col discon format a100
select 'alter table '||a.owner||'.'||a.table_name||' disable constraint
'||a.constraint_name||';' discon
from dba_constraints a
, dba_constraints b
where a.constraint_type = 'R'
and a.r_constraint_name = b.constraint_name
and a.r_owner = b.owner
and b.owner = '&table_owner'
and b.table_name = '&table_name'
/

Produce a list of disabled fk constraints

set lines 100 pages 999


col table format a60
col constraint_name format a30
select owner||'.'||table_name "table"
, constraint_name
from dba_constraints
where status = 'DISABLED'
and constraint_type = 'R'
and owner not in ('SYS','SYSTEM')
order by 1,2
/

Produce enable statements all disabled fk constraints

set lines 100 pages 999


select 'alter table '||owner||'.'||table_name||' enable constraint
'||constraint_name||';' "enable"
from dba_constraints
where status = 'DISABLED'
and constraint_type = 'R'
and owner not in ('SYS','SYSTEM')
order by 1
/

List parent tables that may need fixing/re-importing

select distinct r.owner || '.' || r.table_name "exp"


from dba_constraints c
, dba_constraints r
where c.status = 'DISABLED'
and c.constraint_type = 'R'
and c.r_owner = r.owner
and c.r_constraint_name = r.constraint_name
and c.owner not in ('SYS','SYSTEM')
order by 1
/

List missing foriegn key values

Note. Useful for resolving ORA-02298


select 'select '||cc.column_name-
||' from '||c.owner||'.'||c.table_name-
||' a where not exists (select ''x'' from '-
||r.owner||'.'||r.table_name-
||' where '||rc.column_name||' = a.'||cc.column_name||')'
from dba_constraints c,
dba_constraints r,
dba_cons_columns cc,
dba_cons_columns rc
where c.constraint_type = 'R'
and c.owner not in ('SYS','SYSTEM')
and c.r_owner = r.owner
and c.owner = cc.owner
and r.owner = rc.owner
and c.constraint_name = cc.constraint_name
and r.constraint_name = rc.constraint_name
and c.r_constraint_name = r.constraint_name
and cc.position = rc.position
and c.owner = '&table_owner'
and c.table_name = '&table_name'
and c.constraint_name = '&constraint_name'
order by c.owner, c.table_name, c.constraint_name, cc.position
/

Show all table constraints for a user

Note. This still needs some work...


set lines 100 pages 999
break on table_name
select table_name
, decode(constraint_type,
'C', 'Check',
'O', 'R/O View',
'P', 'Primary',
'R', 'Foreign',
'U', 'Unique',
'V', 'Check view') type
, nvl(index_name, R_CONSTRAINT_NAME) "IDX"
from dba_constraints
where owner like '&user'
order by table_name
, decode(constraint_type,
'P','0','R','1','U','2','C','3','O','4','V','5')
/

Structure - Materialized view

• Create a view log for the master table


• List all materialized view logs
• Create a simple materialized view
• Show all materialized and resfresh times
• Show materialized view tables and masters
• Show refresh jobs in dba_jobs
• Manually start a refresh
• Force a complete refresh

Create a view log for the master table

This is required for fast refresh


create materialized view log on <table>
/

or...
create materialized view log on <table>
tablespace <tablespace_name>
/
List all materialized view logs

select log_owner
, log_table
from dba_mview_logs
/

Create a simple materialized view

create materialized view andy_mview


refresh [fast | complete | force]
start with sysdate
next sysdate + 1/24
with primary key
as select * from test_table
/

Fast = update changes only


Complete = wipe and repopulate the mview
Force = fast if possible, complete if not.

Show all materialized and resfresh times

set lines 100 pages 999


col last_refresh format a20
select owner
, mview_name
, to_char(last_refresh_date, 'dd/mm/yy hh24:mi') last_refresh
from dba_mviews
order by owner, last_refresh
/

Show materialized view tables and masters

set lines 100


col mview format a40
col master format a40
select owner || '.' || name mview
, master_owner || '.' || master master
from dba_mview_refresh_times
/

Show refresh jobs in dba_jobs

This is useful for spotting failures


set lines 100
col job format 9999
col log_user format a15
col last format a15
col next format a15
col fail format 9999
col what format a20
select job
, log_user
, to_char(last_date, 'dd/mm/yy hh24:mi') last
, to_char(next_date, 'dd/mm/yy hh24:mi') next
, failures fail
, replace(what, '"') what
from dba_jobs
where what like '%dbms_refresh.refresh%'
/

Manually start a refresh

execute dbms_mview.refresh ('<owner.mv_table>');

Force a complete refresh

execute dbms_mview.refresh ('<owner.mv_table>','C');

Structure - Partitions

• List partitioned tables


• List a tables partitions
• Show partition sizes for the specified table
• Move a partition to a new tablespace
• Add a partition
• Split a partition
• Drop a partition
• Truncate a partition

List partitioned tables

set pages 999 lines 100


col table_name format a40
select table_name
, partitioning_type type
, partition_count partitions
from dba_part_tables
where owner = '&owner'
order by 1
/
List a tables partitions

set pages 999 lines 100


col high_value format a20
col tablespace_name format a20
select partition_name
, tablespace_name
, high_value
from dba_tab_partitions
where table_owner = '&owner'
and table_name = '&table_name'
order by partition_position
/

Show partition sizes for the specified table

set pages 999 lines 100


col tablespace_name format a20
col num_rows format 999,999,999
select p.partition_name
, p.tablespace_name
, p.num_rows
, ceil(s.bytes / 1024 / 1204) mb
from dba_tab_partitions p
, dba_segments s
where p.table_owner = s.owner
and p.partition_name = s.partition_name
and p.table_name = s.segment_name
and p.table_owner = '&owner'
and p.table_name = '&table_name'
order by partition_position
/

Move a partition to a new tablespace

alter table <table_name>


move partition <partition_name>
tablespace <tablespace_name>
nologging
/

Add a partition

alter table <table_name>


add partition <partition_name> values less than (<value>)
tablespace <tablespace_name>
/

or...
alter table <table_name>
add partition <partition_name> values (<value>)
tablespace <tablespace_name>
/

Split a partition

alter table <table_name>


split partition <partition_name> at (<value>)
into (partition <partition_name>, partition <partition_name>)
update global indexes
/

Drop a partition

alter table <table_name> drop partition <partition_name>


/

Truncate a partition

alter table <table_name> truncate partition <partition_name>


/

Performance - General

• Show currently exectuing sql


• Session statistics
• Resource intensive sql
• File io stats
• In session tracing
• switch on event 10046
• Rows per block
• Show the buffer cache advisory

Show currently exectuing sql

select sql_text
from v$sqlarea
where users_executing > 0
/

Session statistics

select sn.name
, st.value
from v$sesstat st
, v$statname sn
where st.STATISTIC# = sn.STATISTIC#
and st.VALUE > 0
and st.SID = &SID
order by value desc
/

Resource intensive sql

change 8192 to match block size


select sql_text
, executions
, to_char((((disk_reads+buffer_gets)/executions) * 8192)/1048576,
'9,999,999,990.00')
as total_gets_per_exec_mb
, to_char((( disk_reads /executions) * 8192)/1048576,
'9,999,999,990.00')
as disk_reads_per_exec_mb
, to_char((( buffer_gets /executions) * 8192)/1048576,
'9,999,999,990.00')
as buffer_gets_per_exec_mb
, parsing_user_id
from v$sqlarea
where executions > 10
order by 6 desc
/

File io stats

Requires timed_statistics=true
set lines 80 pages 999
col fname heading "File Name" format a60
col sizemb heading "Size(Mb)" format 99,999
col phyrds heading "Reads" format 999,999,999
col readtim heading "Time" format 99.999
col phywrts heading "Writes" format 9,999,999
col writetim heading "Time" format 99.999
select lower(name) fname
, (bytes / 1048576) sizemb
, phyrds
, readtim
, phywrts
, writetim
from v$datafile df
, v$filestat fs
where df.file# = fs.file#
order by 1
/

In session tracing

To switch it on:
exec dbms_system.set_sql_trace_in_session (<sid>, <serial#>, true);

To switch it off:
exec dbms_system.set_sql_trace_in_session (<sid>, <serial#>, false);

switch on event 10046

To switch it on:
alter session set events '10046 trace name context forever, level 8';

To switch it off:
alter session set events '10046 trace name context off';

Note. use tkprof to interpret the results.

Rows per block

select avg(row_count) avg


, max(row_count) max
, min(row_count) min
from (
select count(*) row_count
from &table_name
group by substr(rowid, 1, 15)
)
/

Show the buffer cache advisory

Note. The current setting is halfway down and has a read factor of one.
set lines 100 pages 999
col est_mb format 99,999
col estd_physical_reads format 999,999,999,999,999
select size_for_estimate est_mb
, estd_physical_read_factor
, estd_physical_reads
from v$db_cache_advice
where name = 'DEFAULT'
order by size_for_estimate
/

db_cache_advice needs to be on for the above to work


alter system set db_cache_advice=on;

Performance - Locks DML

• Show sessions that are blocking each other


• Show locked objects
• Show which row is locked
• List locks

Show sessions that are blocking each other

select 'SID ' || l1.sid ||' is blocking ' || l2.sid blocking


from v$lock l1, v$lock l2
where l1.block =1 and l2.request > 0
and l1.id1=l2.id1
and l1.id2=l2.id2
/

Show locked objects

set lines 100 pages 999


col username format a20
col sess_id format a10
col object format a25
col mode_held format a10
select oracle_username || ' (' || s.osuser || ')' username
, s.sid || ',' || s.serial# sess_id
, owner || '.' || object_name object
, object_type
, decode( l.block
, 0, 'Not Blocking'
, 1, 'Blocking'
, 2, 'Global') status
, decode(v.locked_mode
, 0, 'None'
, 1, 'Null'
, 2, 'Row-S (SS)'
, 3, 'Row-X (SX)'
, 4, 'Share'
, 5, 'S/Row-X (SSX)'
, 6, 'Exclusive', TO_CHAR(lmode)) mode_held
from v$locked_object v
, dba_objects d
, v$lock l
, v$session s
where v.object_id = d.object_id
and v.object_id = l.id1
and v.session_id = s.sid
order by oracle_username
, session_id
/

Show which row is locked

select do.object_name
, row_wait_obj#
, row_wait_file#
, row_wait_block#
, row_wait_row#
, dbms_rowid.rowid_create (1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#,
ROW_WAIT_BLOCK#, ROW_WAIT_ROW#)
from v$session s
, dba_objects do
where sid=&sid
and s.ROW_WAIT_OBJ# = do.OBJECT_ID
/

Then select the row with that rowid...


select * from <table> where rowid=<rowid>;

List locks

column lock_type format a12


column mode_held format a10
column mode_requested format a10
column blocking_others format a20
column username format a10
SELECT session_id
, lock_type
, mode_held
, mode_requested
, blocking_others
, lock_id1
FROM dba_lock l
WHERE lock_type NOT IN ('Media Recovery', 'Redo Thread')
/

Performance - Locks DDL

• Show all ddl locks in the system


• Slightly more simple version of the above
• Generate kill statement for ddl locking sessions

Show all ddl locks in the system

select decode(lob.kglobtyp,
0, 'NEXT OBJECT', 1, 'INDEX', 2, 'TABLE', 3, 'CLUSTER',
4, 'VIEW', 5, 'SYNONYM', 6, 'SEQUENCE',
7, 'PROCEDURE', 8, 'FUNCTION', 9, 'PACKAGE',
11, 'PACKAGE BODY', 12, 'TRIGGER',
13, 'TYPE', 14, 'TYPE BODY',
19, 'TABLE PARTITION', 20, 'INDEX PARTITION', 21, 'LOB',
22, 'LIBRARY', 23, 'DIRECTORY', 24, 'QUEUE',
28, 'JAVA SOURCE', 29, 'JAVA CLASS', 30, 'JAVA RESOURCE',
32, 'INDEXTYPE', 33, 'OPERATOR',
34, 'TABLE SUBPARTITION', 35, 'INDEX SUBPARTITION',
40, 'LOB PARTITION', 41, 'LOB SUBPARTITION',
42, 'MATERIALIZED VIEW',
43, 'DIMENSION',
44, 'CONTEXT', 46, 'RULE SET', 47, 'RESOURCE PLAN',
48, 'CONSUMER GROUP',
51, 'SUBSCRIPTION', 52, 'LOCATION',
55, 'XML SCHEMA', 56, 'JAVA DATA',
57, 'SECURITY PROFILE', 59, 'RULE',
62, 'EVALUATION CONTEXT','UNDEFINED'
) object_type
, lob.kglnaobj object_name
, pn.kglpnmod lock_mode_held
, pn.kglpnreq lock_mode_requested
, ses.sid
, ses.serial#
, ses.username
from v$session_wait vsw
, x$kglob lob
, x$kglpn pn
, v$session ses
where vsw.event = 'library cache lock'
and vsw.p1raw = lob.kglhdadr
and lob.kglhdadr = pn.kglpnhdl
and pn.kglpnmod != 0
and pn.kglpnuse = ses.saddr
/

Slightly more simple version of the above

select ses.username
, ddl.session_id
, ses.serial#
, owner || '.' || ddl.name object
, ddl.type
, ddl.mode_held
from dba_ddl_locks ddl
, v$session ses
where owner like '%userid%'
and ddl.session_id = ses.sid
/

Generate kill statement for ddl locking sessions

select 'alter system kill session ''' || ddl.session_id || ',' || ses.serial#


|| ''' immediate;'
from dba_ddl_locks ddl
, v$session ses
where owner like '%userid%'
and ddl.session_id = ses.sid
/
Performance - Waits

• Top ten hotest objects by touch count


• Waits by file
• Segment Waits
• Time waited for latches
• Identify hot blocks
• Look at the performance stats for the instance

Top ten hotest objects by touch count

col owner format a20 trunc


col object_name format a30
col touches format 9,999,999
select *
from (
select count(*)
, sum(tch) TOUCHES
, u.name OWNER
, o.name OBJECT_NAME
from x$bh x
, obj$ o
, user$ u
where x.obj = o.obj#
and o.owner# = u.user#
group by u.name, o.name
order by 2 desc
)
where rownum < 11
/

Waits by file

col name format a60


select name
, count
from x$kcbfwait
, v$datafile
where indx + 1 = file#
order by 2
/

Segment Waits

select object_name
, obj#
, statistic_name
, value
from v$segment_statistics
where owner like '&owner'
and statistic_name like '%waits%'
and value > 0
order by statistic_name
, value desc
/

Time waited for latches

col event format a30


select event
, time_waited
, round(time_waited*100/ SUM (time_waited) OVER(),2) wait_pct
from (
select event
, time_waited
from v$system_event
where event not in (
'Null event'
,'client message'
,'rdbms ipc reply'
,'smon timer'
,'rdbms ipc message'
,'PX Idle Wait'
,'PL/SQL lock timer'
,'file open'
,'pmon timer'
,'WMON goes to sleep'
,'virtual circuit status'
,'dispatcher timer'
,'SQL*Net message from client'
,'parallel query dequeue wait'
,'pipe get')
union
(
select name
, value
from v$sysstat
where name like 'CPU used when call started'
)
)
order by 2 desc
/

Identify hot blocks

Look at all waits for the instance


col event format a30
select event
, total_waits
, time_waited
from v$system_event
where event like '%wait%'
order by 2,3
/
If there are lots of 'data block' waits, get a break-down of them
select *
from v$waitstat
/

Then run this to identify the file, block and reason code...
select p1 "File #"
, p2 "Block #"
, p3 "Reason Code"
from v$session_wait
where event = 'buffer busy waits'
/

Note. You might need to run this a few times before anything is displayed.

Look at the performance stats for the instance

select n.name
, s.value
from v$statname n
, v$sysstat s
where n.statistic# = s.statistic#
order by n.class
, n.name
/

Performance - Statistics

• Gather database statistics


• Gather stats for a single schema...
• Delete stats
• Gather system stats
• Export/Import optimizer statistics
• Old style analyze
• Show a count of analyezed tables broken down by schema
• Show tables that have analyze dates older than today

Gather database statistics

Gather stats on the entire database...


execute dbms_stats.gather_database_stats;

Or...
execute dbms_stats.gather_database_stats( -
estimate_percent => 1, -
method_opt => 'FOR ALL COLUMNS SIZE 1',-
cascade => TRUE);
Gather stats for a single schema...

execute dbms_stats.gather_schema_stats('SCOTT');

Or...
execute dbms_stats.gather_schema_stats( -
ownname => 'SCOTT', -
estimate_percent => 1, -
method_opt => 'FOR ALL COLUMNS SIZE 1',-
cascade => TRUE);

You can let oracle come up with the estimate figure by using dbms_stats.auto_sample_size

or...
execute dbms_stats.gather_schema_stats( -
ownname => 'SYS', -
cascade => TRUE);

Table statistics
exec dbms_stats.gather_table_stats('<owner>', '<table_name>');

Delete stats

exec dbms_stats.delete_database_stats;

exec dbms_stats.delete_schema_stats('SCOTT');

exec dbms_stats.delete_table_stats('SCOTT', 'EMPLOYEES');

exec dbms_stats.delete_index_stats('SCOTT', 'EMPLOYEES_PK');

Gather system stats

execute dbms_stats.gather_system_stats('Start');

Wait for a while - idealy with the database under a typical workload
execute dbms_stats.gather_system_stats('Stop');

To see the current system statistics


select pname
, pval1
from sys.aux_stats$
where sname = 'SYSSTATS_MAIN'
/
Export/Import optimizer statistics

Create a table to hold the statistics...


exec dbms_stats.create_stat_table(ownname => 'SYS',-
stattab => 'prod_stats', tblspace => 'USERS');

Populate the table with the current stats...


exec dbms_stats.export_schema_stats(ownname => 'SCOTT',-
statown=>'SYS', stattab=>'prod_stats');

At this point you need to:


1) take an export of the 'prod_stats' table
2) import 'prod_stats' into the target database
3) load the statistics using this command...
exec dbms_stats.import_schema_stats(ownname => 'SCOTT',-
statown=>'SYS', stattab=>'prod_stats');

Old style analyze

analyze table employees compute statistics;

analyze table employees estimate statistics sample 100 rows;

analyze table employees estimate statistics sample 15 percent;

analyze index employees_ind compute statistics;

Show a count of analyezed tables broken down by schema

set pages 999 lines 100


select a.owner
, a.total_tables tables
, nvl(b.analyzed_tables,0) analyzed
from (select owner
, count(*) total_tables
from dba_tables
group by owner) a
, (select owner
, count(last_analyzed) analyzed_tables
from dba_tables
where last_analyzed is not null
group by owner) b
where a.owner = b.owner (+)
and a.owner not in ('SYS', 'SYSTEM')
order by a.total_tables - nvl(b.analyzed_tables,0) desc
/
Show tables that have analyze dates older than today

This is useful if you are running an analyze and want to see how much is left to do
select count(last_analyzed) left_to_do
from dba_tables
where owner = '&schema'
and trunc(last_analyzed) < trunc(sysdate)
order by 1
/

Performance - Query Tuning

• Create a plan table


• Autotrace
• Explain plan
• Find a query's hash
• Grab the sql associated with a hash
• Look at a query's stats in the sql area

Create a plan table

@?/rdbms/admin/utlxplan.sql

Autotrace

To switch it on:
column plan_plus_exp format a100

set autotrace on explain # Displays the execution plan only.


set autotrace traceonly explain # dont run the query
set autotrace on # Shows the execution plan as well as statistics of the
statement.
set autotrace on statistics # Displays the statistics only.
set autotrace traceonly # Displays the execution plan and the statistics

To switch it off:
set autotrace off

Explain plan

explain plan for


select ...

or...
explain plan set statement_id = 'bad1' for
select...

Then to see the output...


set lines 100 pages 999
@?/rdbms/admin/utlxpls

Find a query's hash

Put something unique in the like clause


select hash_value, sql_text
from v$sqlarea
where sql_text like '%TIMINGLINKS%FOLDERREF%'
/

Grab the sql associated with a hash

select sql_text
from v$sqlarea
where hash_value = '&hash'
/

Look at a query's stats in the sql area

select executions
, cpu_time
, disk_reads
, buffer_gets
, rows_processed
, buffer_gets / executions
from v$sqlarea
where hash_value = '&hash'
/

Performance - Memory

• SGA breakdown
• PGA usage by username
• Display pool usage

SGA breakdown

set lines 100 pages 999


col bytes format 999,999,999
compute sum of bytes on pool
break on pool skip 1
select pool
, name
, bytes
from v$sgastat
order by pool
, name
/

PGA usage by username

select st.sid "SID",


sn.name "TYPE",
ceil(st.value / 1024 / 1024) "MB"
from v$sesstat st,
v$statname sn
where st.statistic# = sn.statistic#
and sid in (select sid
from v$session
where username like '&user')
and upper(sn.name) like '%PGA%'
order by st.sid,
st.value desc
/

Display pool usage

select name
, sum(bytes)
from v$sgastat
where pool like 'shared pool'
group by name
/

Performance - Statspack

• Take a snapshot
• Delete one or more snapshots
• Generate a report
• List snapshots
• Install statspack
• Uninstall statspack
• Schedule and hourly snapshot

Take a snapshot

exec statspack.snap;

Or to specify a level...
exec statspack.snap(i_snap_level => 6, i_modify_parameter => 'true');
Level 0 - This level captures general statistics, including rollback segment, row cache, SGA,
system events, background events, session events, system statistics, wait statistics, lock statistics,
and Latch information.

Level 5 - This level includes capturing high resource usage SQL Statements, along with all data
captured by lower levels.

Level 6 - This level includes capturing SQL plan and SQL plan usage information for high
resource usage SQL Statements, along with all data captured by lower levels.

Level 7 - This level captures segment level statistics, including logical and physical reads, row
lock, itl and buffer busy waits, along with all data captured by lower levels.

Level 10 - This level includes capturing Child Latch statistics, along with all data captured by
lower levels.

Delete one or more snapshots

@?/rdbms/admin/sppurge;

Generate a report

@?/rdbms/admin/spreport.sql

List snapshots

col "Date/Time" format a30


select snap_id
, snap_level
, to_char(snap_time,'HH24:MI:SS DD-MM-YYYY') "Date/Time"
from stats$snapshot
, v$database
order by snap_id
/

Install statspack

1. Create a tablespace (minimum size 100MB)


2. Run...
@?/rdbms/admin/spcreate

Uninstall statspack

@?/rdbms/admin/spdrop
Schedule and hourly snapshot

@?/rdbms/admin/spauto.sql

Note. This uses dbms_job, so job_queue_processes needs to be set greater than 0.

To see the job:


select job
, what
from dba_jobs
/

To delete the job:


exec dbms_job.remove(<job number>);

Performance - AWR

• Display a list of snapshots


• Produce a report
• To see the snapshot interval and retention period
• Change the snapshot interval
• Change the retention period
• Manually take a snapshot
• List all baselines
• Create a baseline
• Remove a baseline
• Enable/Disable automatic snapshots
• Time model queries
• Produce an Active Session History (ASH) report

Display a list of snapshots

set lines 100 pages 999


select snap_id
, snap_level
, to_char(begin_interval_time, 'dd/mm/yy hh24:mi:ss') begin
from dba_hist_snapshot
order by 1
/

Produce a report

@?/rdbms/admin/awrrpt.sql
To see the snapshot interval and retention period

col snap_interval format a30


col retention format a30
select snap_interval
, retention
from dba_hist_wr_control
/

Change the snapshot interval

Note. This example changes it to 30 minutes


exec dbms_workload_repository.modify_snapshot_settings (interval => 30)

Change the retention period

Note. This example changes it to two weeks (14 days)


exec dbms_workload_repository.modify_snapshot_settings (retention => 14*24*60)

Manually take a snapshot

exec dbms_workload_repository.create_snapshot

List all baselines

set lines 100


col baseline_name format a40
select baseline_id
, baseline_name
, start_snap_id
, end_snap_id
from dba_hist_baseline
order by 1
/

Create a baseline

exec dbms_workload_repository.create_baseline (<start snap>,


<endsnap>,'<name>')

Remove a baseline

exec dbms_workload_repository.drop_baseline('<baseline name>')


Enable/Disable automatic snapshots

Note. This job is enabled by default


exec dbms_scheduler.enable('GATHER_STATS_JOB')

and to disable...
exec dbms_scheduler.disable('GATHER_STATS_JOB')

Time model queries

System time model


set lines 100 pages 999
select stat_name
, value
from v$sys_time_model
order by value desc
/

Session time model


set lines 100 pages 999
select stat_name
, value
from v$sess_time_model
where sid = '&sid'
order by value desc
/

Produce an Active Session History (ASH) report

@?/rdbms/admin/ashrpt.sql

Backup - DataGuard

• Startup commands
• To remove a delay from a standby
• Cancel managed recovery
• Register a missing log file
• If FAL doesn't work and it says the log is already registered
• Check which logs are missing
• Disable/Enable archive log destinations
• Turn on fal tracing on the primary db
• Stop the Data Guard broker
• Show the current instance role
• Logical standby apply stop/start
• See how up to date a physical standby is
• Display info about all log destinations
• Display log destinations options
• List any standby redo logs

Startup commands

startup nomount
alter database mount standby database;
alter database recover managed standby database disconnect;

To remove a delay from a standby

alter database recover managed standby database cancel;


alter database recover managed standby database nodelay disconnect;

Cancel managed recovery

alter database recover managed standby database cancel;

Register a missing log file

alter database register physical logfile '<fullpath/filename>';

If FAL doesn't work and it says the log is already registered

alter database register or replace physical logfile '<fullpath/filename>';

If that doesn't work, try this...


shutdown immediate
startup nomount
alter database mount standby database;
alter database recover automatic standby database;

wait for the recovery to finish - then cancel


shutdown immediate
startup nomount
alter database mount standby database;
alter database recover managed standby database disconnect;

Check which logs are missing

Run this on the standby...


select local.thread#
, local.sequence# from
(select thread#
, sequence#
from v$archived_log
where dest_id=1) local
where local.sequence# not in
(select sequence#
from v$archived_log
where dest_id=2 and
thread# = local.thread#)
/

Disable/Enable archive log destinations

alter system set log_archive_dest_state_2 = 'defer';


alter system set log_archive_dest_state_2 = 'enable';

Turn on fal tracing on the primary db

alter system set LOG_ARCHIVE_TRACE = 128;

Stop the Data Guard broker

alter system set dg_broker_start=false


/

Show the current instance role

select database_role
from v$database
/

Logical standby apply stop/start

Stop...
alter database stop logical standby apply;

Start...
alter database start logical standby apply;

See how up to date a physical standby is

Run this on the primary


set numwidth 15
select max(sequence#) current_seq
from v$log
/

Then run this on the standby


set numwidth 15
select max(applied_seq#) last_seq
from v$archive_dest_status
/

Display info about all log destinations

To be run on the primary


set lines 100
set numwidth 15
column ID format 99
column "SRLs" format 99
column active format 99
col type format a4

select ds.dest_id id
, ad.status
, ds.database_mode db_mode
, ad.archiver type
, ds.recovery_mode
, ds.protection_mode
, ds.standby_logfile_count "SRLs"
, ds.standby_logfile_active active
, ds.archived_seq#
from v$archive_dest_status ds
, v$archive_dest ad
where ds.dest_id = ad.dest_id
and ad.status != 'INACTIVE'
order by
ds.dest_id
/

Display log destinations options

To be run on the primary


set numwidth 8 lines 100
column id format 99
select dest_id id
, archiver
, transmit_mode
, affirm
, async_blocks async
, net_timeout net_time
, delay_mins delay
, reopen_secs reopen
, register,binding
from v$archive_dest
order by
dest_id
/
List any standby redo logs

set lines 100 pages 999


col member format a70
select st.group#
, st.sequence#
, ceil(st.bytes / 1048576) mb
, lf.member
from v$standby_log st
, v$logfile lf
where st.group# = lf.group#
/

Backup - Flashback

• To put the session back in time


• Copy old data into a new table
• Export a database from a point in time
• Find the current SCN number
• Set the database recovery directory and size
• Set the flashback database retention target
• Turn on flashback database
• What is the earliest time the database can be flashed back to?
• Get a list of times and scn numbers
• Flash the database back

To put the session back in time

Note. undo_management must be auto


Note. Take a look at undo_retention to get an idea of how far back you might be able to go.
Note. This can't be run as sys - system works though
exec dbms_flashback.enable_at_time(to_date('2006-AUG-24 12:00:00', 'YYYY-MON-DD
HH24:MI:SS'));

To disable flashback run...


exec dbms_flashback.disable;

Copy old data into a new table

First, create an empty copy of the source table...


create table old_test_table
tablespace andy
as select *
from test_table
where rownum < 1
/
Now, insert the old data into it...
insert /*+ APPEND */ old_test_table
(select * from test_table as of timestamp
to_timestamp('24-AUG-06 12:00:00','DD-MON-YY HH24:MI:SS'))
/

Export a database from a point in time

exp / file=full_scr9.dmp log=full_scr9.log flashback_time=TO_TIMESTAMP('10-09-


2006 09:00:00', 'DD-MM-YYYY HH24:MI:SS')

exp / parfile=full_scr9.par

parfile...
userid=system/******
file=full_scr9.dmp
log=full_scr9.log
flashback_time='2006-09-13 12:00:00'

Find the current SCN number

select dbms_flashback.get_system_change_number from dual


/

Set the database recovery directory and size

These settings are dynamic


alter system set db_recovery_file_dest='<path>' scope=both
/
alter system set db_recovery_file_dest_size=<size> scope=both
/

Set the flashback database retention target

alter system set db_flashback_retention_target=<minutes> scope=both


/

Turn on flashback database

shutdown immediate
startup mount
alter database flashback on;
alter database open;
What is the earliest time the database can be flashed back to?

select oldest_flashback_scn scn


, to_char(oldest_flashback_time, 'hh24:mi:ss dd/mm/yyyy') oldest_time
from v$flashback_database_log
/

Get a list of times and scn numbers

set pages 999


select scn
, to_char(time_dp, 'hh24:mi:ss dd/mm/yyyy') time
from smon_scn_time
order by scn
/

Flash the database back

shutdown immediate
startup mount exclusive

flashback database to scn <scn>;

or...
flashback database to timestamp to_timestamp('22/04/2007 19:30:00','dd/mm/yyyy
hh24:mi:ss');

alter database open resetlogs;

Manual upgrade from 9i to 10g Release 2


This procedure describes the steps necessary to manually upgrade a database from 9.2.x to 10.2.x.
It assumes that you have already installed 10g onto the server. Of course, it is essential that you
take a backup of your database before attempting any upgrade.

• 1. Compile any invalid objects

@?/rdbms/admin/utlrp.sql

• 2. Create a sysaux tablespace

Having a sysaux tablespace is a requirement in 10g. So, if you haven't already got one, create one
now.
create tablespace sysaux
datafile '<file_name>' size 512M
extent management local
segment space management auto
/

• 3. Run utlu102i.sql

This utility script checks that the database is ready to be upgraded to 10g. It also identifies any
actions that need to be taken. The script is located in the 10g oracle home, so you will need to
specify the full path to it.
@/u01/app/oracle/product/10.2.0/db_1/rdbms/admin/utlu102i.sql
Review the output and make any necessary alterations. Make a note of how many invalid objects
there are.

• 4. Shut the database down with either normal or immediate

shutdown immediate

• 5. Copy the spfile (or pfile) and the password file from the existing home to the 10g one.

cp ${ORACLE_HOME}/dbs/*${ORACLE_SID}* <new_home>/dbs/

• 6. Edit oratab

Alter /etc/oratab (or /var/opt/oracle/oratab) to point to the10g home. Once done, rerun oraenv to
bring the alteration into effect.

• 7. Upgrade the database

sqlplus "/ as sysdba"

startup upgrade
This next bit is the upgrade itself. It takes roughly half an hour to complete. Spool the output to a
file so that you can review it afterward.
@?/rdbms/admin/catupgrd.sql

• 8. Recompile any invalid objects

@?/rdbms/admin/utlrp.sql
Compare the number of invalid objects with the number noted in step 3. It should hopefully be the
same or less.

• 9. Then check the status of the upgrade

@?/rdbms/admin/utlu102s.sql

• 10. Alter or remove initialisation parameters

Temporarily creating a pfile is the easiest way.


create pfile from spfile;

shutdown immediate

vi ${ORACLE_HOME}/dbs/init${ORACLE_SID}.ora
Alter/remove parameters identified in step 9. Set compatible to 10.2.0.0.0
startup

create spfile from pfile;

shutdown immediate

startup
That's it!

Capture all SQL run between two points in time


tnsManager - Distribute tnsnames the easy way and for free!

There are situations where it is useful to capture the SQL that a particular user is running in the
database. Usually you would simply enable session tracing for that user, but there are two potential
problems with that approach.

The first is that many web based applications maintain a pool of persistent database connections
which are shared amongst multiple users. The second is that some applications connect, run some
SQL and disconnect very quickly, making it tricky to enable session tracing at all (you could of
course use a logon trigger to enable session tracing in this case).

A quick and dirty solution to the problem is to capture all SQL statements that are run between two
points in time.

The following procedure will create two tables, each containing a snapshot of the database at a
particular point. The tables will then be queried to produce a list of all SQL run during that period.

If possible, you should do this on a quiet development system - otherwise you risk getting way too
much data back.

• 1. Take the first snapshot


Run the following sql to create the first snapshot:
• create table sql_exec_before as
• select executions
• , hash_value
• from v$sqlarea
• /
• 2. Get the user to perform their task within the application

• 3. Take the second snapshot


• select aft.hash_value
• from sql_exec_before bef
• , sql_exec_after aft
• where aft.executions > bef.executions
• and aft.hash_value = bef.hash_value (+)
• /
• 4. Check the results
Now that you have captured the SQL it is time to query the results.

This first query will list all query hashes that have been executed:
• select aft.hash_value
• from sql_exec_before bef
• , sql_exec_after aft
• where aft.executions > bef.executions
• and aft.hash_value = bef.hash_value (+)
• /

This one will display the hash and the SQL itself:

set pages 999 lines 100


break on hash_value
select hash_value
, sql_text
from v$sqltext
where hash_value in (
select aft.hash_value
from sql_exec_before bef
, sql_exec_after aft
where aft.executions > bef.executions
and aft.hash_value = bef.hash_value (+)
)
order by
hash_value
, piece
/

• 5. Tidy up
Don't forget to remove the snapshot tables once you've finished:
• drop table sql_exec_before
• /

• drop table sql_exec_after
• /