死锁是数据库经常发生的问题,数据库一般不会无缘无故产生死锁,死锁通常都是由于我们应用程序的设计本身造成的。
会话1:
-- 创建一个测试表,插入两行
18:03:48 SCOTT@wailon>create table tab_dl (id int,name varchar2(30));
Table created.
18:05:50 SCOTT@wailon>insert into tab_dl values (1,'DeadLock 1');
1 row created.
18:05:56 SCOTT@wailon>insert into tab_dl values (2,'DeadLock 2');
1 row created.
18:06:04 SCOTT@wailon>commit;
Commit complete.
-- 分别在不同的会话对这两行进行更新
18:06:06 SCOTT@wailon>update tab_dl set name='DeadLock 3' where id=1;
1 row updated.
会话2:
18:07:14 SCOTT@wailon>update tab_dl set name='DeadLock 4' where id=2;
1 row updated.
会话1:
18:07:37 SCOTT@wailon>update tab_dl set name='DeadLock 5' where id=2; --此会话在等待,在会话2更新id=1时检测到死锁,自动终止其中一个会话
update tab_dl set name='DeadLock 5' where id=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
会话2:
18:08:00 SCOTT@wailon>update tab_dl set name='DeadLock 6' where id=1; --此会话一直在等等
-- 以上实验结果得出结论:两个会话同时互相阻塞对方的事务修改时,会产生死锁。
产生死锁时,如何解决呢,下面是常规的解决办法:
会话1:
1)执行下面SQL,先查看哪些表被锁住了:
18:09:22 SCOTT@wailon>select b.owner,b.object_name,a.session_id,a.locked_mode
from v$locked_object a,dba_objects b
where b.object_id = a.object_id;
OWNER OBJECT_NAME SESSION_ID LOCKED_MODE
------------------------------ -------------------- ---------- -----------
SCOTT TAB_DL 144 3
SCOTT TAB_DL 21 3
2)查看引起死锁的会话
18:09:24 SCOTT@wailon>select b.username,b.sid,b.serial#,logon_time
18:09:40 2 from v$locked_object a,v$session b
18:09:40 3 where a.session_id = b.sid order by b.logon_time;
USERNAME SID SERIAL# LOGON_TIME
------------------------------ ---------- ---------- ------------
SCOTT 21 53 27-SEP-13
SCOTT 144 369 27-SEP-13
3)查看被阻塞的会话
18:11:09 SCOTT@wailon>select * from dba_waiters;
WAITING_SESSION HOLDING_SESSION LOCK_TYPE MODE_HELD MODE_REQUESTED LOCK_ID1 LOCK_ID2
--------------- --------------- -------------------------- ---------- --------------- ---------- ----------
144 21 Transaction Exclusive Exclusive 655372 1186
4)可以提交或回滚阻塞的话,释放锁或者杀掉ORACLE进程:
ALTER SYSTEM KILL SESSION 'SID,SERIAL#'; --对应上例中的21,53