Test steps:
1. create tables
script: cr_tab.sql
create two tables: p and c, which has parent-child relationship
2. In Session 1, insert into the parent table without commit:
SQL> variable n number
SQL> exec :n := 201
PL/SQL procedure successfully completed.
SQL> insert into p values(:n, 35);
1 row created.
3. In Session 2, insert into the child table:
SQL> variable n number
SQL> exec :n := 201
PL/SQL procedure successfully completed.
SQL> insert into c values(2, :n);
4. In another session, we can see the blocker and waiter sessions:
SQL> @bw 'WAITER' : WAITER SID : 87 SERIAL# : 24 SPID : 27274 USERNAME : Zxxx294 MACHINE : MSHOME\NTBK SESS_AGE_MIN : 17 HASH_VALUE : 3262381862 QUERY_TXT : insert into c values(:"SYS_B_0", :n) ----------------- PL/SQL procedure successfully completed. 'BLOCKER' : BLOCKER SID : 126 SERIAL# : 512 SPID : 57 USERNAME : Zxxx294 MACHINE : MSHOME\NTBK SESS_AGE_MIN : 2 HASH_VALUE : 716205104 QUERY_TXT : insert into p values(:n, :"SYS_B_0") -----------------
5. Logon to the server, issue the following command:
$> estk_dump.sh 27274
$> estk_dump.sh 512
Where 27274 and 512 are the OS pid (SPID) of the blocker and waiter session respectively
6. Analyze the trace files:
In the udump dir, trace files were generated, for the waiter session, we can see the bind value
(by search value=), for example:
In the trace file from pid=512
---------------------------------------- Cursor 1 (ffffffff7ca60458): CURBOUND curiob: ffffffff7ca69828 curflg: 4c curpar: 0 curusr: b7 curses 3b433bb88 cursor name: insert into c values(:"SYS_B_0", :n) child pin: 3b7b98c88, child lock: 3b7b947f8, parent lock: 3b7b94bb0 xscflg: 110664, parent handle: 3bcaae0a0, xscfl2: f900008 Dumping Literal Information Bind Pos: 0, Bind Len: 2, Bind Val: nxt: 3.0x00000420 nxt: 2.0x000001d0 nxt: 1.0x00000208 Cursor frame allocation dump: frm: -------- Comment -------- Size Seg Off bhp size: 216/600 bind 0: dty=2 mxl=22(02) mal=00 scl=00 pre=00 oacflg=10 oacfl2=100 size=24 offset=0 bfp=ffffffff7ca694f0 bln=22 avl=02 flg=09 value=2 bind 1: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=03 oacfl2=0 size=24 offset=0 bfp=ffffffff7ca5e040 bln=22 avl=03 flg=05 value=201 End of cursor dump
In addtion,we can find DML LOCK information as can be seen:
DML LOCK: tab=508254 flg=11 chi=0 his[0]: mod=3 spn=302 (enqueue) TM-0007C15E-00000000 DID: 0001-000D-0000005A lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 res: 3b4a42960, mode: SX, prv: 3b4a42970, sess: 3b433bb88, proc: 3b41ac6d8 ---------------------------------------- SO: 3b60e47b0, type: 34, owner: 3b63c7540, flag: INIT/-/-/0x00 DML LOCK: tab=508252 flg=11 chi=0 his[0]: mod=2 spn=302 (enqueue) TM-0007C15C-00000000 DID: 0001-000D-0000005A lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 res: 3b4a45758, mode: SS, prv: 3b4a45768, sess: 3b433bb88, proc: 3b41ac6d8
However, from the blocker session trace file, we can not find any bind values. Notice that waiter session was shown as 'ACTIVE' and blocker session shown as 'INACTIVE' in the v$session view. Nevertheless, we can still find DML lock info:
---------------------------------------- SO: 3b60e4540, type: 34, owner: 3b643fbe0, flag: INIT/-/-/0x00 DML LOCK: tab=508254 flg=11 chi=0 his[0]: mod=2 spn=11931 (enqueue) TM-0007C15E-00000000 DID: 0001-000A-00000E56 lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 res: 3b4a42960, mode: SS, prv: 3b60e4b28, sess: 3b4355778, proc: 3b41ab6b8 ---------------------------------------- SO: 3b60e4060, type: 34, owner: 3b643fbe0, flag: INIT/-/-/0x00 DML LOCK: tab=508252 flg=11 chi=0 his[0]: mod=3 spn=11931 (enqueue) TM-0007C15C-00000000 DID: 0001-000A-00000E56 lv: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 res: 3b4a45758, mode: SX, prv: 3b60e47e8, sess: 3b4355778, proc: 3b41ab6b8
If we feed the DML lock information from the trace file (i.e. tab=508252) into the following query, we canget:
SQL> select object_name from dba_objects where object_id=508252;
OBJECT_NAME
------------------------------
P
SQL> select object_name from dba_objects where object_id=508254;
OBJECT_NAME
------------------------------
C
So it is interesting to know the blocker session holds SX mode DML lock on P, and SS mode DML lock on C; whereas the waiter session holds SS mode DML lock on P, and SX mode DML lock on C. If we see such kind of info, we can check the relationship between P and C, and may speculate the block/waiter is caused by FK constriant.
Appendix:
--- script: estk_dump.sh ----- #!/bin/ksh ospid=$1 sqlplus -s "/ as sysdba" <<EOF oradebug setospid $ospid oradebug unlimit oradebug dump errorstack 2 EOF --- script: bw.sql ------------ exec print_table(' select distinct ''WAITER'', vs.sid, vs.serial#, vp.SPID, vs.username, vs.machine, round((sysdate - vs.logo n_time) * (24*60)) sess_age_min, va.hash_value, substr(va.sql_text,1,800) Query_Txt from v$sqlarea va, dba_waiters wait, v$se ssion vs, v$process vp where vs.sid=wait.waiting_session and vs.PADDR = vp.ADDR (+) and vs.sql_address=va.address (+) and vs .sql_hash_value=va.hash_value (+) '); exec print_table(' select distinct ''BLOCKER'' ,vs.sid, vs.serial#, vp.SPID, vs.username, vs.machine, round((sysdate - vs.log on_time) * (24*60)) sess_age_min,va.hash_value, substr(va.sql_text,1,800) Query_Txt from v$sqlarea va, dba_blockers block, v$ session vs, v$process vp where vs.sid=block.holding_session and vs.PADDR = vp.ADDR (+) and vs.sql_address=va.address (+) and vs.sql_hash_value=va.hash_value (+) '); ---- script: cr_tab.sql ---------- set echo on drop table c; drop table p; create table p as select rownum id, trunc(rownum/20) d from all_objects where rownum <=200; alter table p add constraint p_pk primary key (id); create table c as select rownum id, mod(rownum+1000, 200) + 1 fk1 from all_objects where rownum <=200; alter table c add constraint c_fk foreign key(fk1) references p(id); exec dbms_stats.gather_table_stats(user, 'p', cascade=> true); exec dbms_stats.gather_table_stats(user, 'c', cascade=> true);
Update: Feb 2012
Reference: How to read ERRORSTACK output
1 comment:
Excellent Post.
Post a Comment