儘管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