需求描述:某客戶短信系統需要連接到核心系統查詢信息並進行發送。但是應用開發的有問題,導致db_link用了不釋放。所以僅針對短信系統進行kill session動作作爲備選方案。代碼如下:
create or replace procedure kill_over_time_session(in_last_time number) is
--此過程的目的是用於kill掉遠程某些機器連接到當前數據庫,並且超過一定時間不執行任務的session
--解決此問題的辦法是使用完dblink之後關閉該鏈接:alter session
close database link <db_link_name>;
/*配置寫日誌文件步驟:
1.創建directtory(指定成你希望的路徑):
SQL>create directory user_dump as '/u01/app/oracle/admin/sample10/udump';
2.在direcotry上進行授權:
SQL>grant read,write on directory user_dump to dba;
3.執行
SQL>exec kill_over_time_session(xx),其中xx表示超時時間
*/
--定義與sid,serial#有關參數
TYPE t_sid_cur IS REF CURSOR; --定義存儲sid,serial#的遊標類型
ref_sid_serial# t_sid_cur; --定義sid,serial#的遊標
TYPE t_sid_rec IS RECORD (
sid NUMBER,
serial# NUMBER); --定義record
類型
rec_sid_serial# t_sid_rec; --申明傳遞sid,serial#的record變量
--下面參數需要設置
v_user_status VARCHAR2(20 )
:= UPPER('INACTIVE'); --希望kill用戶的狀態:ACTIVE,INACTIVE,SNIPED
TYPE t_machine_varry IS VARRAY (1000) OF varchar2 (64);
--下面參數需要設置
vry_machine_list t_machine_varry := t_machine_varry( 'node1', 'node2' ); --存儲需要殺掉session的主機名,多主機名格式:
t_machine_varry('node0','node1');
--v_machine_list varchar2(100):='''node1'',''node2''';
v_machine_list varchar2(5000 )
:= ''''; --轉存主機字符串
v_last_time NUMBER :=
in_last_time; --定義保持給定狀態多長時間
--定義sql語句
v_slct_stmt VARCHAR2(5000 ); --此sql獲取需要kill的session
v_kill_stmt VARCHAR2(5000 ); --此sql爲kill
session的語句
--定義trace文件
v_file_name varchar2(100 )
:= 'all_killed_session.log'; --定義trace文件名
v_trace_file UTL_FILE.FILE_TYPE; --定義文件類型變量
--定義其他參數
v_count NUMBER;
BEGIN
--初始化trace文件
v_trace_file := utl_file.fopen( 'USER_DUMP',
v_file_name, 'a' );
utl_file.new_line(v_trace_file, 2);
utl_file.put_line(v_trace_file,
'************************************************Begin
Kill: ' ||
to_char( sysdate, 'yyyy-mm-dd_hh:mi:ss' )
||
'************************************************' ,
true);
--utl_file.putf(v_trace_file,a,b,c);
--utl_file.fflush(v_trace_file);
--utl_file.fclose(v_trace_file);
FOR i in 1 ..
vry_machine_list.count loop
v_machine_list := v_machine_list || vry_machine_list(i) || ''',''';
end loop;
v_machine_list := substr(v_machine_list, 1,
length(v_machine_list) - 2);
--DBMS_OUTPUT.PUT_LINE(sysdate || ': Kill
' || v_user_status ||' session from ' || v_machine_list || ' over ' ||v_last_time || ' seconds');
utl_file.put_line(v_trace_file,
'INFO: ' ||
to_char(sysdate , 'yyyy-mm-dd_hh:mi:ss')
||
': Kill ' ||
v_user_status || ' session from ' ||
v_machine_list || ' over ' ||
v_last_time || ' seconds',
true);
v_slct_stmt := 'select sid,serial# from v$session
where username is not null and machine in (' ||
v_machine_list || ') and status
=''' || v_user_status ||
''' and last_call_et >= ' ||
v_last_time;
--DBMS_OUTPUT.PUT_LINE(v_slct_stmt);
v_count := 0;
OPEN ref_sid_serial# FOR v_slct_stmt;
LOOP
FETCH ref_sid_serial#
INTO rec_sid_serial#;
EXIT WHEN ref_sid_serial#%NOTFOUND;
v_kill_stmt := 'alter system kill session ''' ||
rec_sid_serial#.sid || ',' ||
rec_sid_serial#.serial# || '''immediate';
-- 記錄總共kill掉的session數量
v_count := v_count + 1;
EXECUTE IMMEDIATE v_kill_stmt;
utl_file.put_line(v_trace_file,
' Killed Session SID:
' || rec_sid_serial#.sid ||
' SERIAL#: ' ||
rec_sid_serial#.serial# ||
' with sql:' ||
v_kill_stmt,
true);
--DBMS_OUTPUT.PUT_LINE(' Killed Session
SID: ' || rec_sid_serial#.sid ||' SERIAL#: ' || rec_sid_serial#.serial# ||' with sql:' || v_kill_stmt);
END LOOP;
--DBMS_OUTPUT.PUT_LINE('All killed: ' ||
v_count || ' records!');
utl_file.put_line(v_trace_file,
'All killed: ' ||
v_count || ' records this time!' ,
true);
CLOSE ref_sid_serial#;
utl_file.put_line(v_trace_file,
'************************************************End
Kill: ' ||
to_char( sysdate, 'yyyy-mm-dd_hh:mi:ss' )
||
'************************************************' ,
true);
utl_file.fflush(v_trace_file);
utl_file.fclose(v_trace_file);
EXCEPTION
WHEN OTHERS THEN
IF ref_sid_serial#%ISOPEN THEN
CLOSE ref_sid_serial#;
END IF ;
--DBMS_OUTPUT.PUT_LINE('ERROR: ' || SUBSTR(SQLERRM,
1, 200));
IF UTL_FILE.is_open(v_trace_file) THEN
utl_file.put_line(v_trace_file, 'ERROR: ' ||
SUBSTR(SQLERRM , 1, 200));
utl_file.fclose(v_trace_file);
ELSE
v_trace_file := utl_file.fopen( 'USER_DUMP',
v_file_name, 'a' );
utl_file.put_line(v_trace_file, 'ERROR: ' ||
SUBSTR(SQLERRM , 1, 200));
utl_file.fclose(v_trace_file);
END IF ;
END kill_over_time_session;