若是有兩個會話,每一個會話都持有另外一個會話想要的資源,此時就會發生死鎖。
用下面實驗來講明死鎖的產生緣由和解決辦法。
SESSION1:
SQL> create table t2 as select * from emp;
SQL> select * from t2 where empno=7369;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 19801217 00:00:00 800 20
SQL> update t2 set sal=sal+200 where empno=7369;
SQL> select * from t2 where empno=7369;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 19801217 00:00:00 1000 20
SESSION2:
SQL> select * from t2 where empno=7900;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7900 JAMES CLERK 7698 19811203 00:00:00 950 30
SQL> update t2 set sal=sal+200 where empno=7900;
1 row updated.
SQL> select * from t2 where empno=7900;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7900 JAMES CLERK 7698 19811203 00:00:00 1150 30
SESSION1:
SQL> select * from t2 where empno=7900;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7900 JAMES CLERK 7698 19811203 00:00:00 950 30
SESSION2:
SQL> select * from t2 where empno=7369;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 19801217 00:00:00 800 20
SESSION1:
SQL> update t2 set sal=sal-200 where empno=7900;
出現等待
SESSION2:
SQL> update t2 set sal=sal-200 where empno=7369;
死鎖發生,session2被阻塞
系統回滾session1跟死鎖有關的sql。
update t2 set sal=sal-200 where empno=7900
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
SESSION1:
SQL> select * from t2 where empno in (7369,7900);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 19801217 00:00:00 1000 20
7900 JAMES CLERK 7698 19811203 00:00:00 950 30
看到系統只回滾了對empno=7900的修改。
而此時SESSION2的update t2 set sal=sal-200 where empno=7369;依然被SESSION1的第一條語句所阻塞。
咱們如今查看產生鎖的狀況
打開第三個會話以DBA身份登陸
SQL> select * from v$lock;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
29434224 29434238 165 XR 4 0 1 0 2998 0
29434280 29434294 165 CF 0 0 2 0 2988 0
294342DC 294342F0 167 PW 1 0 3 0 2980 0
29434338 2943434C 165 RS 25 1 2 0 2983 0
294343F0 29434404 166 RT 1 0 6 0 2983 0
2943444C 29434460 153 TX 589868 325 0 4 24 0
29434560 29434574 167 MR 1 0 4 0 2983 0
294345BC 294345D0 167 MR 2 0 4 0 2983 0
29434618 2943462C 167 MR 3 0 4 0 2983 0
29434674 29434688 167 MR 4 0 4 0 2983 0
294346D0 294346E4 167 MR 5 0 4 0 2983 0
2943472C 29434740 167 MR 6 0 4 0 2983 0
29434788 2943479C 167 MR 7 0 4 0 2983 0
294347E4 294347F8 167 MR 201 0 4 0 2983 0
2943489C 294348B0 164 TS 3 1 3 0 2979 0
288F6030 288F6048 144 TM 53257 0 3 0 51 0
288F60DC 288F60F4 153 TM 53257 0 3 0 24 0
28934170 28934194 153 TX 655363 241 6 0 24 0
28969404 28969428 144 TX 589868 325 6 0 51 1
19 rows selected.
用下面的SQL語句能夠直接得出誰阻塞誰
SQL> select ( select username from v$session where sid=a.sid) blocker, a.sid,
' is blocking ',
(select username from v$session where sid=b.sid) blockee, b.sid
from v$lock a, v$lock b
where a.block=1 and b.request>0 and a.id1=b.id1 and a.id2=b.id2;
BLOCKER SID 'ISBLOCKING' BLOCKEE SID
------------------------------ ---------- ------------- ------------------------------ ----------
STONE 144 is blocking STONE 153
發生死鎖的時候會在alert文件裏記錄下信息。
--查看操做系統下$ORACLE_BASE/admin/orcl/bdump/alert_orcl.log文件,會找到以下信息
Thu Sep 2 20:41:25 2010
ORA-00060: Deadlock detected. More info in file /u01/app/oracle/admin/orcl/udump/orcl_ora_4945.trc.
再查看跟蹤文件詳細信息
*** 2010-09-02 20:41:25.700
*** ACTION NAME () 2010-09-02 20:41:25.699
*** MODULE NAME (SQL*Plus) 2010-09-02 20:41:25.699
*** SERVICE NAME (SYS$USERS) 2010-09-02 20:41:25.699
*** SESSION ID (144.3) 2010-09-02 20:41:25.699
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-00090015-00000146 19 144 X 23 148 X
.......
SESSION2還在被SESSION1阻塞,只有在SESSION1執行提交或回退才能讓SESSION2繼續下去。
SESSION1:
commit; --將提交update t2 set sal=sal+200 where empno=7369的修改
或
rollback;--將取消update t2 set sal=sal+200 where empno=7369的修改
隨即SESSION2獲得1 row updated.的信息。
咱們也能夠用管理員帳號執行kill命令殺死致使阻塞的會話SESSION1來解決死鎖。
sqlplus / as sysdba
從上面查過的信息能夠知道產生阻塞的sid=144
經過查v$session視圖能夠得出serial#
SADDR SID SERIAL# AUDSID PADDR USER# USERNAME COMMAND OWNERID TADDR
-------- ---------- ---------- ---------- -------- ---------- ----------- ---------- ---------- -----
29F0BED4 144 3 210009 29E24174 64 STONE 0 2147483644
殺死這個會話用下面的命令
alter system kill session '144,3';
總結:
Oralce認爲死鎖是應用致使的錯誤,Oracle中不多出現死鎖。致使死鎖的的頭號殺手是外鍵沒有加索引,第二號殺手則是位圖索引遭到併發更新。
若是外鍵沒有索引,咱們更新了父表的主鍵時將會鎖住整個子表。若是外鍵沒有索引,刪除了父表中的一行,整個子表也會被鎖住。這樣就很容易產生不少問題,若是其中任何阻塞的會話鎖住了某一會話須要的資源就會出現一個死鎖。至於位圖索引的併發更新,是會鎖住全部相關聯的行,也會致使問題的發生。
在Oracle9i及以上版本中,這些全表鎖都是短時間的,也就是僅在DML操做期間存在,而不是存在於整個事務期間。html
本文轉自:http://www.itpub.net/thread-1347577-1-1.htmlsql