0% found this document useful (0 votes)
17 views61 pages

Database Tools For Performance Monitoring

Uploaded by

Connor McDonald
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views61 pages

Database Tools For Performance Monitoring

Uploaded by

Connor McDonald
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

www.

oracledba

co.uk
Debugging / Trace

The tools you’ll need


oracledba

.co.uk
Autotrace

10046 trace

Debugging

Error handling

2
oracledba
Pop quiz #1

.co.uk
SQL> select rowid from MY_TABLE;

ROWID
------------------
AAAG+dAALAAACaKAAA How do two different
tables have the same
rowid ?
SQL> select rowid from A_DIFFERENT_TABLE;

ROWID
------------------
AAAG+dAALAAACaKAAA

3
oracledba
Pop quiz #2

.co.uk
• In a table, how many bytes does a ROWID consume
– A) 0
– B) 6
– C) 8

• In an index, how many bytes does a ROWID consume


– A) 6
– B) 10
– C) 3950

4
oracledba
Tools

.co.uk
• Autotrace
• Database trace

5
oracledba
Autotrace

.co.uk
• Used in SQL Plus
– get the most recent version
– requires a little DBA setup

SQL> set autotrace on


Error ORA-942 while gathering statistics
Error enabling STATISTICS report
SQL>

6
oracledba
Autotrace example

.co.uk
SQL> set autotrace on
SQL> select inc_id, incident_ref from ims_incident
2 where off_id_officer_dealing = 1234;

INC_ID INCIDENT_REF mostly correct


---------- -----------------------------------
100001

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=19 Bytes=1615)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'IMS_INCIDENT' (Cost=2 Card=19 Bytes=1615)
2 1 INDEX (RANGE SCAN) OF 'INC_OFF1_DEAL_FK_I' (NON-UNIQUE) (Cost=1 Card=19)

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
7
0 rows processed
oracledba
Autotrace example

.co.uk
SQL> set autotrace on statistics
SQL> select inc_id, incident_ref from ims_incident
2 where off_id_officer_dealing = 1234;

INC_ID INCIDENT_REF
---------- -----------------------------------
100001

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

8
oracledba
Autotrace example

.co.uk
SQL> set autotrace traceonly statistics
SQL> select inc_id, incident_ref from ims_incident
2 where off_id_officer_dealing = 1234;

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

9
oracledba
Autotrace example

.co.uk
SQL> set autotrace on traceonly explain
SQL> select inc_id, incident_ref from ims_incident
2 where off_id_officer_dealing = 1234;

(query not run)

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=19 Bytes=1615)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'IMS_INCIDENT' (Cost=2 Card=19 Bytes=1615)
2 1 INDEX (RANGE SCAN) OF 'INC_OFF1_DEAL_FK_I' (NON-UNIQUE) (Cost=1 Card=19)

10
oracledba
What to look for

.co.uk
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=19 Bytes=1615)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'IMS_INCIDENT' (Cost=2 Card=19 Bytes=1615)
2 1 INDEX (RANGE SCAN) OF 'INC_OFF1_DEAL_FK_I' (NON-UNIQUE) (Cost=1 Card=19)

• Does it make sense ?


• Do the cardinalities appear correct ?

11
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets SQL statements executed in order
2 consistent gets to execute your SQL statement.
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client • triggers
315 bytes received via SQL*Net from client • parsing
1 SQL*Net roundtrips to/from client
0 sorts (memory) • temporary space
0 sorts (disk) • plsql functions
0 rows processed

Should reduce after first execution.


Try to remove if possible.

• fold code into the SQL

12
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets Blocks read in "CURRENT" mode.
2 consistent gets
0 physical reads
0 redo size
Current mode get is a retrieve of a
2384 bytes sent via SQL*Net to client block as it exists right now.
315 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory) • update
0 sorts (disk) • insert
0 rows processed • delete
• full scans

13
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets
Request for consistent read of a
2 consistent gets block.
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client
May require reads to the undo
315 bytes received via SQL*Net from client (rollback) information.
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk) Probably the key one to focus on.
0 rows processed
• query tuning
• array fetching
• application processes / timings

14
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets Physical reads from the datafiles
2 consistent gets into the buffer cache.
0 physical reads
0 redo size
2384 bytes sent via SQL*Net to client • Reading from datafiles
315 bytes received via SQL*Net from client • Reading from temp segments
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

15
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets The total amount of redo generated
2 consistent gets in bytes during the execution of this
0 physical reads
0 redo size
statement.
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client • batch up DML
1 SQL*Net roundtrips to/from client
0 sorts (memory) • use SQL not PL/SQL
0 sorts (disk) • avoid overfrequent commits
0 rows processed

16
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets The total number of bytes
2 consistent gets sent/received between the client
0 physical reads
0 redo size
and the server.
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client Total number of SQL*Net
1 SQL*Net roundtrips to/from client
0 sorts (memory) messages sent to and received
0 sorts (disk) from the client.
0 rows processed

Includes roundtrips for FETCHES


from a multiple row result set.

• select columns you need


• array fetching

17
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets Sorts done in the user's session
2 consistent gets memory (sort area). Controlled via
0 physical reads
0 redo size
sort_area_size database
2384 bytes sent via SQL*Net to client parameter.
315 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed

18
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets Sorts that use the disk (temporary
2 consistent gets tablespace) because the sort
0 physical reads
0 redo size
exceeded the users sort area size.
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client DBA concern primarily
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk) Upgrade to ver 9
0 rows processed

19
oracledba
What to look for

.co.uk
Statistics
---------------------------------------------
0 recursive calls
0 db block gets Rows processed by modifications
2 consistent gets or returned from a SELECT
0 physical reads
0 redo size
statement.
2384 bytes sent via SQL*Net to client
315 bytes received via SQL*Net from client • was the result expected?
1 SQL*Net roundtrips to/from client
0 sorts (memory) • updates with subqueries
0 sorts (disk)
0 rows processed

20
oracledba
Database Trace

.co.uk
• The definitive performance measurement tool
– need access to server, OR
– need client software on PC

• Enabling trace
– alter session set sql_trace = true;
– alter session set events = ‘10046 trace name context forever, level nnn’;

– quick and easy way


• when-new-form-instance, FORMS_DDL('alter session set sql_trace = true');

– Build an external enabling facility!

21
oracledba
Database Trace for Developers

.co.uk
• Trace level
– 1 standard trace
– 4 standard + bind variable values
– 8 standard trace + wait events
– 12 standard trace + bind variable values + wait events

22
oracledba
Database trace

.co.uk
SQL> alter session set sql_trace = true;

SQL> select p.value||'/'||lower(d.instance_name) || '_ora_' ||


2 ltrim(to_char(a.spid)) || '.trc' filename
3 from v$process a, v$session b, v$instance d, v$parameter p
4 where a.addr = b.paddr
5 and b.audsid = userenv('sessionid')
6 and p.name = 'user_dump_dest';

FILENAME
--------------------------------------------------------------
/apps/oracle/admin/IMSDEV/udump/imsdev_ora_6560.trc

File is created on the database server

View VW_TRACE_FILE_NAME available in IMS1DE

23
oracledba
The raw data

.co.uk
/apps/oracle/admin/IMSDEV/udump/imsdev_ora_6669.trc
Oracle8i Enterprise Edition Release 8.1.7.4.0 - Production
With the Partitioning option
JServer Release 8.1.7.4.0 - Production
ORACLE_HOME = /apps/oracle/8.1.7.4
System name: SunOS
Node name: gomez
Release: 5.8
Version: Generic_108528-16
Machine: sun4u
Instance name: IMSDEV
Redo thread mounted by this instance: 1
Oracle process number: 17
Unix process pid: 6669, image: oracle@gomez (TNS V1-V3)

*** 2003-07-17 12:04:51.924


*** SESSION ID:(15.107) 2003-07-17 12:04:51.862
APPNAME mod='SQL*Plus' mh=3669949024 act='' ah=4029777240

24
oracledba
The raw data

.co.uk
PARSING IN CURSOR #1 len=29 dep=0 uid=156 oct=3 lid=156
tim=2762254524 hv=1415343577 ad='81e07370'
select count(*) from nominal
END OF STMT
PARSE #1:c=20,e=23,p=4,cr=533,cu=0,mis=1,r=0,dep=0,og=4,tim=2762254524
EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=2762254524
WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0
WAIT #1: nam='file open' ela= 0 p1=0 p2=0 p3=0
WAIT #1: nam='db file sequential read' ela= 2 p1=9 p2=5033 p3=1
WAIT #1: nam='db file scattered read' ela= 2 p1=9 p2=5034 p3=3
FETCH #1:c=0,e=4,p=4,cr=3,cu=4,mis=0,r=1,dep=0,og=4,tim=2762254528
WAIT #1: nam='SQL*Net message from client' ela= 0 p1=1650815232 p2=1 p3=0
FETCH #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=2762254528
WAIT #1: nam='SQL*Net message to client' ela= 0 p1=1650815232 p2=1 p3=0

25
oracledba
The raw data

.co.uk
PARSING IN CURSOR #2 len=283 dep=1 uid=0 oct=3 lid=0
tim=2762255287 hv=955191413 ad='826270fc'
select obj#,type#,ctime,mtime,stime,status,dataobj#,flags,oid$,
spare1 from obj$ where owner#=:1 and name=:2 and namespace=:3
and(remoteowner=:4 or remoteowner is null and :4 is
null)and(linkname=:5 or linkname is null and :5 is
null)and(subname=:6 or subname is null and :6 is null)
END OF STMT
PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
EXEC #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
FETCH #2:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
EXEC #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
FETCH #2:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=2762255287
=====================
PARSING IN CURSOR #3 len=46 dep=1 uid=0 oct=3 lid=0
tim=2762255287 hv=2918884618 ad='823c04ec'
select node,owner,name from syn$ where obj#=:1
END OF STMT
PARSE #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
EXEC #3:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
FETCH #3:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=2762255287
EXEC #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=2762255287
FETCH #2:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=2762255287
26
oracledba
The raw data – a closer look

.co.uk
len = length of SQL dep = recursive depth uid = user executing
oct = oracle command type
lid = access user id
tim = time snapshot
ad = sql address
PARSING IN CURSOR #1 len=29 dep=0 uid=156 oct=3 lid=156
tim=2762254524 hv=1415343577 ad='81e07370' hv = hash value

select count(*) from nominal


END OF STMT
c = cpu p = physical reads cu = current reads r = rows processed og = optimizer goal

PARSE #1:c=20,e=23,p=4,cr=533,cu=0,mis=1,r=0,dep=0,og=4,tim=2762254524

e = elapsed cr = consistent reads mis = library cache miss dep = recursive depth tim = time snapshot

EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=2762254524
WAIT #1: nam='db file sequential read' ela= 2 p1=9 p2=5033 p3=1
FETCH #1:c=0,e=4,p=4,cr=3,cu=4,mis=0,r=1,dep=0,og=4,tim=2762254528
27
ela = elapsed p1,p2,p3 = dependent on wait
oracledba
Cleaning it up

.co.uk
tkprof imsdev_ora_6669.trc xyz.prf sort=… sys=…

select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156

Rows Row Source Operation


------- ---------------------------------------------------
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913)
28
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156 How many times ?
Rows Row Source Operation
------- --------------------------------------- Parse to execute ratio.
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913)
All counts = 1 for all SQL
(not using bind variables)

29
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156

Rows Row Source Operation Was this query already in the


------- --------------------------------------- shared pool?
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913)

30
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156

Rows Row Source Operation What optimizer did I use?


------- ---------------------------------------
1 SORT AGGREGATE (Note: Does not tell you the
832 INDEX FAST FULL SCAN (object id 75913)
results of ‘choose’)

31
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156 SQL> select username
2 from dba_users
Rows Row Source Operation
------- --------------------------------------- 3 where user_id = 156;
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913) USERNAME
------------------------------
PD71986
32
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156
The true explain plan that was
Rows Row Source Operation
------- --------------------------------------- used.
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913) The only one you can really
trust.

33
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156
The important stuff.
Rows Row Source Operation
------- ---------------------------------------
1 SORT AGGREGATE Big CPU/Elapsed = problems
832 INDEX FAST FULL SCAN (object id 75913)
CPU vs Elapsed = waiting?

34
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156

Rows Row Source Operation


------- ---------------------------------------
Am I doing single row (bad)
1 SORT AGGREGATE fetches or array (good) fetch ?
832 INDEX FAST FULL SCAN (object id 75913)

35
oracledba
A closer look

.co.uk
select count(*)
from nominal

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.10 0.13 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.04 4 3 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.10 0.17 4 3 4 1

Misses in library cache during parse: 1


Optimizer goal: CHOOSE
Parsing user id: 156
How much physical and logical
Rows Row Source Operation
------- --------------------------------------- I/O did the query do?
1 SORT AGGREGATE
832 INDEX FAST FULL SCAN (object id 75913) High numbers = problems

36
oracledba
Database Trace

.co.uk
• Options
– sort controls order of SQL output (tkprof no parameters)
– sys omit/include recursive SQL from output
– record present list of SQL’s in order executed

37
oracledba
Debugging in the database

.co.uk
• Package dbpk_debug (for database routines)
dbpk_debug.msg('Up to here in code');

Puts 'Up to here in code' in CLIENT_INFO field in V$SESSION

dbpk_debug.msg('Adding GUS_ID %s to table',100);

'Adding GUS_ID 100 to table'

dbpk_debug.msg('Users %s, %s, %s are invalid',


'USER1',
'USER2'
'USER3');
'Users USER1, USER2, USER3 are invalid'

38
oracledba
Example

.co.uk
PROCEDURE dbp_convert_nominal AS
BEGIN
dbpk_debug.msg('Start');
IF pc_sex_code IS NULL THEN
lc_sex_code := dbpk_common.dbf_string('SEX NOT KNOWN');
lc_sex_desc := NULL;
ELSE
lc_sex_code := pc_sex_code;
lc_sex_desc := pc_sex_desc;
END IF;

dbpk_debug.msg('Obtaining destn ref for sex id %s',ln_sex_id);


dbpk_common.dbp_destn_ref ( 'IDM'
,'PERSON_SEX'
,lc_sex_code
,lc_sex_desc
,'IMS'
,ln_sex_id
,lc_destn_desc );

etc etc
39
oracledba
Debugging in the database

.co.uk
• Automatic tracking of
– module name
– line number
• Efficient
– supports approx. 5000 executions per second
• External tracking
– view messages in CLIENT_INFO field from any other session
– can dynamically write to file if required
• Linked in with trace
– trace facilities also controlled with same procedure

40
oracledba
Database Trace for Developers

.co.uk
• "dbpk_debug" controlled with the "init" procedure
SQL> desc TRACE_MODULES
Name Null? Type
----------------------- -------- -------------
USER_SESSION NOT NULL VARCHAR2(30)
TRACE_LEVEL NUMBER(2)
DEBUG_FILE VARCHAR2(100)
DEBUG_DIR VARCHAR2(100)
DEBUG_LEVEL NUMBER(2)

SQL> exec dbpk_debug.init('PD12345',1);


Turn on sql trace for anything run by user PD12345
SQL> exec dbpk_debug.init('35-1543', 12);
Turn on level 12 trace for the current session SID=35, SERIAL# = 1543

41
oracledba
Database Trace for Developers

.co.uk
SQL> begin
2 dbpk_debug.init('PD12345',
3 '/tmp','debug.dat',
4 dbpk_debug.debug_on);
5 end;
6 / Write debug calls to file for anything run by user PD12345

SQL> begin
2 dbpk_debug.init('35-1342',
3 '/tmp','debug.dat',
4 dbpk_debug.debug_off);
5 end;
6 / Stop writing debug information to file for session 35,1342
42
oracledba
Database Trace for Developers

.co.uk
SQL> set serveroutout on
SQL> exec DBPK_DEBUG.SHOW_SESSIONS

Session User Module Status


---------- ---------- ------------------ ----------------------
7-28105 IMS Idle for 4097 secs
9-47803 IMS SQL*Plus Idle for 274 secs
15-58197 PD71176 IMSF8220 Idle for 0 secs
18-14543 PD71953 IMSF1100 Idle for 445 secs
19-9720 IMS Idle for 170906 secs
23-16831 IMS Idle for 834 secs
24-39498 IMS SQL*Plus Idle for 36 secs
25-16854 IMS Idle for 3153 secs
26-5276 IMSWAPS SQL*Plus Currently running SQL
27-42288 IMS Idle for 73539 secs
28-59199 IMS T.O.A.D. Idle for 1421 secs
29-44907 PD71404 WAPF0100 Idle for 2674 secs
30-15146 IMS Idle for 72920 secs

43
oracledba
Database Trace for Developers

.co.uk
SQL> select * from all_trace_files;

USER_SESSION FILENAME DT
------------------ ------------------------------ ---------
10-38245 im1dev_ora_23246.trc 16/OCT/03
26-5276 im1dev_ora_15905.trc 16/OCT/03
PD71986 im1dev_ora_23296.trc 16/OCT/03

SQL> @gettrace
Enter value for user_session: 10-38256

INFO
-------------------------------------
Processing file im1dev_ora_23246.trc

PL/SQL procedure successfully completed.


TKPROF: Release 8.1.7.0.0 - Production on Thu Jul 17 16:19:36 2003

Trace file: im1dev_ora_23246.trc


Sort options: default
44
etc
oracledba
Database Trace for Developers

.co.uk
SQL> @getdebug
Enter value for file: /tmp/debug.dat

INFO
-------------------------------------
Processing file /tmp/debug.dat

PL/SQL procedure successfully completed.

(appears in notepad)

45
oracledba
Debugging in Forms

.co.uk
• Forms counterpart lk_debug
lk_debug.msg(m=>'Jumping to CTRL_ABC');

lk_debug.msg('10','WHEN-NEW-FORM-INSTANCE',
m=>'Jumping to CTRL_ABC');

• Will be controlled with lk_debug. init


lk_debug.init(
pv_module=>'IMSF0420',
pv_user=>'*',
pv_file=>'my_forms_file_name',
pv_dir=>'/apps/ims',
pn_debug_level=>lk_debug.debug_on);

46
oracledba
Error handling

.co.uk
• Guideline #1
– It is an EXCEPTION HANDLER
– If you can take remedial action
• include the handler
– If you get no value from handling the error
• do NOT handle it
– The calling level is the only routine that needs handlers

47
oracledba
Guideline #1

.co.uk
procedure PROC1(p_nom_id number, p_nom_date OUT date) is
begin
select nom_date_from
into p_nom_date
from nominal Problem with the query?
where nom_id = p_nom_id; Data integrity problem?

exception
when too_many_rows then
Maybe ok?
p_nom_date := null;
Is NOM_DATE_FROM nullable?
when no_data_found then
Have we just created work for caller?
p_nom_date := null;
when others then
raise; Waste of code – gains nothing
end;

48
oracledba
Error handling

.co.uk
• Guideline #2
– PL/SQL programs are single logical units of work
– Do not interrupt transaction flow

49
oracledba
Guideline #2

.co.uk
procedure PROC2(p_nom_id number) is
x number;
begin
insert into NOMINAL values (p_nom_id);

insert into NOM_AUDIT values (p_nom_id);

x := 1 / 0;

update RECORD_COUNT set CNT = CNT + 1;

exception Anything wrong here ?


when others then
rollback;
end;

50
oracledba
Guideline #2

.co.uk
WHEN-BUTTON-PRESSED

begin
post;
delete from OLD_NOM where NOM_ID = :block.nom_id;
proc2;
update OTHER_TABLE set OTHER_COLUMNS = …
end;

Data corruption

51
oracledba
Guideline #2

.co.uk
procedure PROC2(p_nom_id number) is
x number;
begin
insert into NOMINAL values (p_nom_id);
insert into NOM_AUDIT values (p_nom_id);
x := 1 / 0;
update RECORD_COUNT set CNT = CNT + 1;
end;

SQL> exec PROC2

ORA-01476: divisor is equal to zero

What reparative action is needed ?

NONE !!!
52
oracledba
Error handling

.co.uk
• Guideline #3
– Return codes are bad bad news
– Breaks rule number #2

53
oracledba
Guideline #3

.co.uk
procedure PROC2(p_nom_id number, p_ret_code OUT number) is
x number;
begin
insert into NOMINAL values (p_nom_id);
insert into NOM_AUDIT values (p_nom_id);
x := 1 / 0;
update RECORD_COUNT set CNT = CNT + 1;

p_ret_code := 0;
exception
when others then
p_ret_code := 1;
end;

54
oracledba
Guideline #3

.co.uk
WHEN-BUTTON-PRESSED

declare
ln_err_code number;
begin
PROC2(:block.nom_id, ln_err_code);

if ln_err_code = 1 then

What do I here ?
- don't know why it fell over (no error code)
- I've got a massive transaction mess (two
pending inserts that the trigger does not
know about)
- if I raise a new exception, I obfuscate the
location of where the code failed

55
oracledba
Error handling

.co.uk
• Guideline #4
– Re-cast errors only if you provide additional information

56
oracledba
Guideline #4

.co.uk
procedure PROC1(p_nom_id number, p_nom_date OUT date) is
l_error_pos number;
begin
l_error_pos := 10;
select nom_date_from We gain nothing over what Oracle
into p_nom_date would have given us anyway
from nominal
where nom_id = p_nom_id;

exception
when too_many_rows then
raise_application_error(-20000,
'TOO_MANY_ROWS error at pos '||l_error_pos||' in PROC1');
end;

57
oracledba
Guideline #4

.co.uk
procedure PROC1(p_nom_id number, p_nom_date OUT date) is
l_error_pos number;
begin
l_error_pos := 10;
select nom_date_from
into p_nom_date Now we know the offending row
from nominal
where nom_id = p_nom_id;

exception
when too_many_rows then
raise_application_error(-20000,
'TOO_MANY_ROWS for NOM_ID='||p_nom_id);
end;

58
oracledba
Error handling

.co.uk
• Guideline #5
– If you need to close cursors, your code is probably wrong

59
oracledba
Guideline #5

.co.uk
procedure PROC2(p_nom_id number) is
cursor CUR1 is …
cursor CUR2 is …
begin Waste of code and effort

exception
when others then
if CUR1%IS_OPEN then close CUR1; end if;
if CUR2%IS_OPEN then close CUR1; end if;
raise;
end;

60
oracledba
Guideline #5

.co.uk
package PKG1
cursor CUR1 is …
cursor CUR2 is …
procedure PROC2; Valid but were those cursors
end; really needed in the package?
package body PKG1
procedure PROC2(p_nom_id number) is
begin


exception
when others then
if CUR1%IS_OPEN then close CUR1; end if;
if CUR2%IS_OPEN then close CUR1; end if;
raise;
end;
end;
61

You might also like