DEADLOCK DETECTED (ORA-00060)Trace實例分析

DEADLOCK DETECTED (ORA-00060)Trace實例分析
Oracle中引入的行級鎖的概念,在大幅提高性能的同時也帶來了一點麻煩。對於設計不良或者說處理不當的應用邏輯,有可能出發死鎖。對於死鎖的跟蹤和分析,最簡單直接的方法就是分析trace文件。每出現死鎖,系統都會生成一個trace文件到USER_DUMP_DEST目錄下。
SQL> show parameter USER_DUMP_DEST;


NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
user_dump_dest string D:/ORACLE/PRODUCT/10.2.0/ADMIN/ORCL/UDUMP
正如Tom所言,Oracle認爲這些應用死鎖是應用自己導致的錯誤。而且Tom說,在大多情況下,Oracle的這種看法是正確的。不同於其他許多的RDBMS,Oracle極少出現死鎖,甚至可以認爲幾乎不存在。通常情況下,必須認爲地提供條件纔會產生死鎖。
在Oracle9i中,如果子表外鍵所在的列沒有加索引,那麼在父表上對主鍵進行更新和刪除的時候要對子表加Share鎖,那麼,如果發現一個SID下的Object涉及到多個表,可以檢察一下是否存在外鍵索引未加的問題。外鍵如果導致死鎖那麼他的類型通常是4 or 5 (S or SSX)。
位圖(Bitmap)索引比較適合於那些取值單一的低基數列,但是對於更新比較頻繁的表,會帶來大量的鎖阻塞的可能性,降低了系統的效率,適合於OLAP。所以使用前要考慮清楚。
那麼10g以後,出現死鎖,並且holds waits爲X的,都是邏輯設計問題。特別嚴重的出現在程序循環中。
下面先舉一個簡單的死鎖例子,看看Trace能帶給我們哪些信息。
下面的例子的原理是
session A locks row X
sesssion B locks row Y
session A tries to lock row Y
session B tries to lock row X
Session A fails after roughly 3 seconds with a deadlock ORA-00060
Session A:
Connected to Oracle Database
10g Enterprise Edition Release 10.2.0.3.0
Connected as johnson_hgc


SQL>

SQL>
create
table t_deadlock_demo( id
int , tname varchar( 200));


Table created
SQL>
insert
into t_deadlock_demo values ( 1,'org_demo1' );


1
row inserted
SQL>
insert
into t_deadlock_demo values ( 2,'org_demo2' );


1
row inserted
SQL>
select * from t_deadlock_demo;


ID TNAME
--------------------------------------- ------
1 org_demo1
2 org_demo2
SQL>
update t_deadlock_demo set tname = 'session1_demo2' where
id = 2;


1
row
updated
Session B:
SQL>
update t_deadlock_demo set tname = 'session2_demo1' where
id = 1;


1
row
updated
這個時候各爲其主,不會發生鎖,都是行級。接下來開始上演死鎖。
Session A:
SQL>
update t_deadlock_demo set tname = 'session1_demo1' where
id = 1; (Lock)
Session B:
SQL>
update t_deadlock_demo set tname = 'session2_demo2' where
id = 2;


1
row
updated
這個時候Session B的操作會導致SessionA的操作發生死鎖,那麼SessionA的最後一步操作會被Oracle強行中斷。剛纔的鎖等待變成了
SQL>
update t_deadlock_demo set tname = 'session1_demo1' where
id = 1;


update t_deadlock_demo set tname = 'session1_demo1' where
id = 1


ORA-00060 : 等待資源時檢測到死鎖
而此時,SessionB順利執行結束,等待提交。
我們可以發現USER_DUMP_DEST目錄下已經出現了一個跟蹤文件【orcl_ora_3448.trc】。
下面是其中的主要內容
Dump file d:/oracle/product/10.2.0/admin/orcl/udump/orcl_ora_3448.trc
Mon Apr 06 14:50:52 2009
ORACLE V10.2.0.3.0 - Production vsnsta=0
vsnsql=14 vsnxtr=3
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
Windows Server 2003 Version V5.2 Service Pack 2
CPU                 : 4 - type 586, 1 Physical Cores
Process Affinity    : 0x00000000
Memory (Avail/Total): Ph:1655M/4060M, Ph+PgF:3370M/5938M, VA:1254M/2047M
Instance name: orcl
Redo thread mounted by this instance: 1
Oracle process number: 20
Windows thread id: 3448, image: ORACLE.EXE (SHAD)

*** 2009-04-06 14:50:52.539
*** ACTION NAME Command Window - New) 2009-04-06 14:50:52.539
*** MODULE NAME PL/SQL Developer) 2009-04-06 14:50:52.539
*** SERVICE NAME orcl) 2009-04-06 14:50:52.539
*** SESSION ID:(149.17) 2009-04-06 14:50:52.539
DEADLOCK DETECTED ( ORA-00060 )
[Transaction Deadlock]
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or frCAom issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:
Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-000c0029-00001c1f        20     149     X              21     152           X
TX-00080010-00003474        21     152     X              20     149           X
session 149: DID 0001-0014-00000004 session 152: DID 0001-0015-00000002
session 152: DID 0001-0015-00000002 session 149: DID 0001-0014-00000004
Rows waited on:
Session 152: obj - rowid = 00086FCA - AACG/KAAbAAAAScAAB
  (dictionary objn - 552906 , file - 27, block - 1180, slot - 1)
Session 149: obj - rowid = 00086FCA - AACG/KAAbAAAAScAAA
  (dictionary objn - 552906 , file - 27, block - 1180, slot - 0)
Information on the OTHER waiting sessions:
Session 152:
  pid=21 serial=21 audsid=1330117 user: 165/JOHNSON_HGC
  O/S info: user: johnsonjiang, term: DELAWARE, ospid: 7984:9504, machine: GEARTEKS/DELAWARE
            program: PlSqlDev.exe
  application name: PL/SQL Developer, hash value=1190136663
  action name: Command Window - New, hash value=254318129
  Current SQL Statement:
 
update t_deadlock_demo set tname = 'session2_demo2'where id = 2
End of information on OTHER waiting sessions.
Current SQL statement for this session:
update t_deadlock_demo set tname = 'session1_demo1'where id = 1
===================================================
幾個重要的信息就是鎖的類型是X,說明是DML語句導致的行級排他鎖,涉及到兩個Session:149和152。149就是報錯ora-00060的Session。
下面是兩個Session涉及到的對象ID,三種顏色其實代表的都是同樣的意思。
0086PCA的10進制就是552906
SQL> select dbms_rowid.rowid_object( 'AACG/KAAbAAAAScAAA' ) from dual;

DBMS_ROWID.ROWID_OBJECT('AACG/
------------------------------
                        552906

SQL> select dbms_rowid.rowid_object( 'AACG/KAAbAAAAScAAB' ) from dual;

DBMS_ROWID.ROWID_OBJECT('AACG/
------------------------------
                        552906

查找對象:
SQL> SELECT t.owner, t.object_name, t.object_type FROM all_objects t WHERE t.data_object_id = 552906
OWNER OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------------ -------------------
JOHNSON_HGC T_DEADLOCK_DEMO TABLE
update t_deadlock_demo set tname = 'session2_demo2'where id = 2
End of information on OTHER waiting sessions.
Current SQL statement for this session:
update t_deadlock_demo set tname = 'session1_demo1'where id = 1
說明id=1這句死在了id=2的搶下。
===============================================================================================
下面這個例子是上面例子的延伸,上面這樣的例子如果不是處理超級複雜的更新,很慢,一般來說也不回碰到這麼巧合的事情。
但是如果一個程序邏輯複雜,處理流程較多,尤其是在TRIGGER中處理邏輯,甚至還用上了CURSOR來逐條處理的時候,死鎖就比較容易發生了。
下面舉一個簡單模擬的例子。
創建兩個表:
CREATE
TABLE t_deadlock1( id INTEGER);
CREATE
TABLE t_deadlock2( id INTEGER);
創建兩個表的插入觸發器。
create
or
replace
trigger t_deadlock1_i
after INSERT on t_deadlock1
for each row
declare
i INTEGER;
t_temp VARCHAR2( 200);
begin
update t_deadlock_demo set tname = 'session1_demo2'where id = 2;


i := 0;
WHILE i <= 9999999 LOOP
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';


i := i + 1;
END LOOP;


update t_deadlock_demo set tname = 'session1_demo1'where id = 1;


end t_deadlock1_u;
/
create
or
replace
trigger t_deadlock2_i
after INSERT on t_deadlock2
for each row
declare
i INTEGER;
t_temp VARCHAR2( 200);
begin
update t_deadlock_demo set tname = 'session2_demo1'where id = 1;


i := 0;
WHILE i <= 9999999 LOOP
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
t_temp := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';


i := i + 1;
END LOOP;


update t_deadlock_demo set tname = 'session2_demo2'where id = 2;




end t_deadlock2_u;
/
分別執行兩條插入語句:
Session 152:
SQL> insert into t_deadlock2 values (1);


insert into t_deadlock2 values (1)


ORA-00060: 等待資源時檢測到死鎖
ORA-06512: 在 "JOHNSON_HGC.T_DEADLOCK2_I", line 21
ORA-04088: 觸發器 'JOHNSON_HGC.T_DEADLOCK2_I' 執行過程中出錯
Session 149:
SQL> insert into t_deadlock1 values (1);


1 row inserted
Trace文件:
Dump file d:/oracle/product/10.2.0/admin/orcl/udump/orcl_ora_3164.trc
Mon Apr 06 16:32:55 2009
ORACLE V10.2.0.3.0 - Production vsnsta=0
vsnsql=14 vsnxtr=3
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
Windows Server 2003 Version V5.2 Service Pack 2
CPU                 : 4 - type 586, 1 Physical Cores
Process Affinity    : 0x00000000
Memory (Avail/Total): Ph:1642M/4060M, Ph+PgF:3360M/5938M, VA:1236M/2047M
Instance name: orcl
Redo thread mounted by this instance: 1
Oracle process number: 21
Windows thread id: 3164, image: ORACLE.EXE (SHAD)

*** 2009-04-06 16:32:55.571
*** ACTION NAME:(Command Window - New) 2009-04-06 16:32:55.571
*** MODULE NAME:(PL/SQL Developer) 2009-04-06 16:32:55.571
*** SERVICE NAME:(orcl) 2009-04-06 16:32:55.571
*** SESSION ID:(152.27) 2009-04-06 16:32:55.571
DEADLOCK DETECTED ( ORA-00060 )
[Transaction Deadlock]
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:
Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-000b0005-00001d18        21     152     X              20     149           X
TX-00010005-00002513        20     149     X              21     152           X
session 152: DID 0001-0015-00000004 session 149: DID 0001-0014-00000006
session 149: DID 0001-0014-00000006 session 152: DID 0001-0015-00000004
Rows waited on:
Session 149: obj - rowid = 00086FCA - AACG/KAAbAAAAScAAA
  (dictionary objn - 552906 , file - 27, block - 1180, slot - 0)
Session 152: obj - rowid = 00086FCA - AACG/KAAbAAAAScAAB
  (dictionary objn - 552906 , file - 27, block - 1180, slot - 1)
Information on the OTHER waiting sessions:
Session 149:
  pid=20 serial=20 audsid=1330124 user: 165/JOHNSON_HGC
  O/S info: user: johnsonjiang, term: DELAWARE, ospid: 7984:9504, machine: GEARTEKS/DELAWARE
            program: PlSqlDev.exe
  application name: PL/SQL Developer, hash value=1190136663
  action name: Command Window - New, hash value=254318129
  Current SQL Statement:
 
insert into t_deadlock1 values (1)
End of information on OTHER waiting sessions.
Current SQL statement for this session:
UPDATE T_DEADLOCK_DEMO SET TNAME = 'session2_demo2'WHERE ID = 2
----- PL/SQL Call Stack -----
  object      line  object
  handle    number  name
57C4C314        21  JOHNSON_HGC.T_DEADLOCK2_I
===================================================
死掉的是Session152進程。這裏提示的語句是Trigger中執行的子句,也是出現中斷的語句。
而另一條導致死鎖的語句由於成功執行,所以這裏顯示出來的是最外圍的語句
insert into t_deadlock1 values (1)
所以大家以後查錯的時候,只要注意和152進程出錯對象 552906相關的149對象的程序包即可。

發佈了24 篇原創文章 · 獲贊 10 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章