尽管Oracle的锁定机制已经够完善,但还是有很多人在数据库编程时陷入死锁之中。不要怨天尤人,仔细回顾一下你的设计模型和操作逻辑,问题就在自己身上。
下面程序可以帮助你解除死锁,以解燃眉之急。死锁发生原因在后续文章中会详细讨论。
@echo off
echo Author: Gmtsao Date: 2004-10-19 17:08
echo **********************************************************
echo **** *** *** ** *** ** *** ** ** ******
echo **** ** ** *** ** ** ** ** ** ****** ** *****
echo **** ** ** *** ** * ** * ** ****** ** *****
echo **** ** *** ** ** ** ** *****
echo **** * *** *** ** * ** * ** ****** * ******
echo **** ** ** *** ** ** ** ** ** ****** ** *****
echo **** *** ** *** *** ** *** ** ** *** ****
echo **********************************************************
echo 用法:将全部文本另存为ccs.bat文件 执行 ccs.bat uid/pwd@servname 即可
echo ORACLE数据库解锁...
set args=""
if "%1"=="" goto end
set args=%1
:loop
shift
if "%1"=="" goto end
set args=%args% %1
goto loop
:end
if %args%=="" goto cancel
del /q c:/ckutl.cc
echo CREATE OR REPLACE PROCEDURE SYS.PRC_KILL_LOCKED(P1 NUMBER DEFAULT 0, P2 NUMBER DEFAULT 0) AS>> c:/ckutl.cc
echo V_SID NUMBER;>> c:/ckutl.cc
echo V_SERIAL NUMBER;>> c:/ckutl.cc
echo V_SQL VARCHAR2(4000);>> c:/ckutl.cc
echo TYPE CUROBJ IS REF CURSOR;>> c:/ckutl.cc
echo CCOBJ CUROBJ;>> c:/ckutl.cc
echo -->> c:/ckutl.cc
echo BEGIN>> c:/ckutl.cc
echo IF P1 IS NOT NULL AND P2 IS NOT NULL AND P1 != 0 AND P2 != 0 THEN>> c:/ckutl.cc
echo V_SQL := CONCAT('ALTER SYSTEM KILL SESSION ''', P1);>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ', ');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, P2);>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, '''');>> c:/ckutl.cc
echo EXECUTE IMMEDIATE V_SQL;>> c:/ckutl.cc
echo RETURN;>> c:/ckutl.cc
echo END IF;>> c:/ckutl.cc
echo -->> c:/ckutl.cc
echo V_SQL := 'SELECT SID,SERIAL# FROM V$SESSION WHERE SID IN (SELECT SID FROM V$LOCK)';>> c:/ckutl.cc
echo /*>> c:/ckutl.cc
echo V_SQL := 'select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ a.sid, a.serial#';>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' from v$session a, v$lock b, v$sqltext c');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' where a.username is not null and a.lockwait = b.kaddr and c.hash_value =a.sql_hash_value');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' union');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ a.sid, a.serial#');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' from v$session a, v$lock b, v$sqltext c');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' where b.id1 in (');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' select /*+ NO_MERGE(d) NO_MERGE(e) */ distinct e.id1');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' from v$session d, v$lock e');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' where d.lockwait = e.kaddr');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ' ) and a.username is not null and a.sid = b.sid and b.request=0 and c.hash_value =a.sql_hash_value');>> c:/ckutl.cc
echo */>> c:/ckutl.cc
echo -->> c:/ckutl.cc
echo OPEN CCOBJ FOR V_SQL;>> c:/ckutl.cc
echo -->> c:/ckutl.cc
echo LOOP>> c:/ckutl.cc
echo FETCH CCOBJ INTO V_SID, V_SERIAL;>> c:/ckutl.cc
echo EXIT WHEN CCOBJ%%NOTFOUND;>> c:/ckutl.cc
echo V_SQL := CONCAT('ALTER SYSTEM KILL SESSION ''', V_SID);>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, ', ');>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, V_SERIAL);>> c:/ckutl.cc
echo V_SQL := CONCAT(V_SQL, '''');>> c:/ckutl.cc
echo EXECUTE IMMEDIATE V_SQL;>> c:/ckutl.cc
echo END LOOP;>> c:/ckutl.cc
echo CLOSE CCOBJ;>> c:/ckutl.cc
echo EXCEPTION>> c:/ckutl.cc
echo WHEN OTHERS THEN>> c:/ckutl.cc
echo NULL;>> c:/ckutl.cc
echo END;>> c:/ckutl.cc
echo />> c:/ckutl.cc
echo EXEC SYS.PRC_KILL_LOCKED>> c:/ckutl.cc
echo />> c:/ckutl.cc
echo DROP PROCEDURE SYS.PRC_KILL_LOCKED>> c:/ckutl.cc
echo />> c:/ckutl.cc
echo QUIT>> c:/ckutl.cc
echo />> c:/ckutl.cc
sqlplus %args% @c:/ckutl.cc
del /q c:/ckutl.cc
@echo on
exit
:cancel