Oracle Kill oracle dead-lock session without DBA role
--查 Oracle 目前所有 LOCK_OBJECT
SELECT * FROM TABLE(QUERY_LOCK_OBJECT);
--強制刪除當前連線使用者有 LOCK_OBJECT 之 SESSION (帶入數字)
BEGIN
KILL_SESSION(sid, serial#);
END; DBA_query_lock_object.sql
CREATE OR REPLACE FUNCTION DBA.query_lock_object
RETURN LOCK_OBJECT_TABLE
IS
CURSOR c_lock IS SELECT t2.USERNAME,
t2.SID,
t2.SERIAL#,
t3.OBJECT_NAME,
t2.OSUSER,
t2.MACHINE,
t2.PROGRAM,
t2.LOGON_TIME,
t2.COMMAND,
t2.LOCKWAIT,
t2.SADDR,
t2.PADDR,
t2.TADDR,
t2.SQL_ADDRESS,
t1.LOCKED_MODE
FROM SYS.V_$LOCKED_OBJECT t1,
SYS.V_$SESSION t2,
SYS.DBA_OBJECTS t3
-- WHERE USERNAME = SYS_CONTEXT('USERENV', 'SESSION_USER')
-- AND t1.SESSION_ID = t2.SID
WHERE t1.SESSION_ID = t2.SID
AND t1.OBJECT_ID = t3.OBJECT_ID
ORDER BY t2.LOGON_TIME;
o_data LOCK_OBJECT;
t_result LOCK_OBJECT_TABLE;
BEGIN
FOR r_lock IN c_lock
LOOP
o_data := LOCK_OBJECT(
r_lock.USERNAME,
r_lock.SID,
r_lock.SERIAL#,
r_lock.OBJECT_NAME,
r_lock.OSUSER,
r_lock.MACHINE,
r_lock.PROGRAM,
r_lock.LOGON_TIME,
r_lock.COMMAND,
r_lock.LOCKWAIT,
r_lock.SADDR,
r_lock.PADDR,
r_lock.TADDR,
r_lock.SQL_ADDRESS,
r_lock.LOCKED_MODE
);
t_result := LOCK_OBJECT_TABLE();
t_result.EXTEND;
t_result(t_result.COUNT) := o_data;
END LOOP;
RETURN t_result;
END query_lock_object;
DBA_kill_session.sql
CREATE OR REPLACE PROCEDURE DBA.kill_session(p_sid NUMBER, p_serial NUMBER)
AUTHID DEFINER IS
l_session_count PLS_INTEGER;
l_locked_obj_count PLS_INTEGER;
l_exec_user VARCHAR2(30);
l_is_admin BOOLEAN := FALSE;
BEGIN
SELECT UPPER(SYS_CONTEXT('USERENV', 'SESSION_USER')) INTO l_exec_user FROM DUAL;
l_is_admin := l_exec_user IN ('SYS', 'SYSTEM', 'DBA');
-- DBMS_OUTPUT.PUT_LINE(SYS.DIUTIL.BOOL_TO_INT(l_is_admin));
IF l_is_admin THEN
SELECT COUNT(1)
INTO l_session_count
FROM SYS.V_$SESSION
WHERE SID = p_sid
AND SERIAL# = p_serial;
ELSE
SELECT COUNT(1)
INTO l_session_count
FROM SYS.V_$SESSION
WHERE USERNAME = l_exec_user
AND SID = p_sid
AND SERIAL# = p_serial;
END IF;
IF l_session_count = 1 THEN
SELECT COUNT(1)
INTO l_locked_obj_count
FROM SYS.V_$LOCKED_OBJECT t1,
SYS.V_$SESSION t2
WHERE t1.SESSION_ID = t2.SID
AND SID = p_sid
AND SERIAL# = p_serial;
IF l_locked_obj_count > 0 THEN
EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || p_sid || ',' || p_serial || '''';
ELSIF l_is_admin THEN
RAISE_APPLICATION_ERROR(-20004,
'Blocked kill session attempt, there is no locked object with session (sid=['
|| p_sid || '] serial#=[' || p_serial || '])');
ELSE
RAISE_APPLICATION_ERROR(-20003,
'Blocked kill session attempt, there is no locked object with session (owner=['
|| l_exec_user || '] sid=[' || p_sid || '] serial#=[' || p_serial || '])');
END IF;
ELSIF l_is_admin THEN
RAISE_APPLICATION_ERROR(-20003,
'Blocked kill session attempt, there is no session with given condition (sid=['
|| p_sid || '] serial#=[' || p_serial || '])');
ELSE
RAISE_APPLICATION_ERROR(-20002,
'Blocked kill session attempt, there is no session with given condition (owner=['
|| l_exec_user || '] sid=[' || p_sid || '] serial#=[' || p_serial || '])');
END IF;
END kill_session;
DBA_LOCK_OBJECT.sql
create or replace TYPE LOCK_OBJECT IS OBJECT (
USERNAME VARCHAR2(128),
SID NUMBER,
SERIAL# NUMBER,
OBJECT_NAME VARCHAR2(128),
OSUSER VARCHAR2(128),
MACHINE VARCHAR2(64),
PROGRAM VARCHAR2(48),
LOGON_TIME DATE,
COMMAND NUMBER,
LOCKWAIT VARCHAR2(16),
SADDR RAW(8),
PADDR RAW(8),
TADDR VARCHAR2(16),
SQL_ADDRESS RAW(8),
LOCKED_MODE NUMBER
);
create or replace TYPE LOCK_OBJECT_TABLE IS TABLE OF LOCK_OBJECT;