殺遠程指定主機超時session

需求描述:某客戶短信系統需要連接到核心系統查詢信息並進行發送。但是應用開發的有問題,導致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;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章