Chr☆s Kwok 的技术笔记

.NET, C#, WPF, WCF, WF, .NetCore & LINQ ... I know how it works because I know why it works ...

博客园 首页 新随笔 订阅 管理

1、性能调优语句

1.1、批量更新(删除)以及MERGE INTO用法

merge into POOR.APPROVEDACCOUNTLIST A
using (SELECT *  FROM FIAB.TEMP_OP_APPROVED) B
on (A.ENCOUNTERID = B.ENCOUNTERID 
    AND A.ORDERSOURCEFLAG = B.ORDERSOURCEFLAG 
    AND A.PARENTORDERID = B.PARENTORDERID 
    AND A.ORDERID = B.ORDERID 
    AND A.CHILDID = B.CHILDID 
    AND (A.CONSUMEABLECODEID <>B.CONSUMABLECODEID OR B.CONSUMABLEID <> A.CONSUMEABLEID))  
when matched then  
  update  set A.ROWVERSION = A.ROWVERSION -- 必须要有update,而且这里不能有where,否则后面的delete的where条件无效;
  delete  where 1=1  --上一行update过的记录,才会被delete
  ;
  
UPDATE ROLE.EMPLOYEE A SET A.ORG_NAME=(SELECT B.NAME FROM ENTITY.ORGANIZATION B WHERE B.ORGANIZATIONID = A.ORGANIZATIONID) WHERE A.ORGANIZATIONID IN (SELECT ORGANIZATIONID FROM ENTITY.ORGANIZATION B);
DELETE  core.ParameterValue a
WHERE EXISTS (select * from core.ParameterValue b where a.ParameterId =31 and  b.ParameterId=33 and a.Name=b.Name and a.Value=b.Value);
COMMIT;

1.2、索引在线修改及手动(自动)收集统计信息

--手工收集统计
exec dbms_stats.gather_table_stats(ownname => 'prpa',tabname => 'encounterii' ,estimate_percent => null ,method_opt => 'for all indexed columns' ,cascade => true);

--修改(DROP之后再CREATE)索引
DECLARE
  cnt number(10):=0;
BEGIN
  SELECT count(*) INTO cnt FROM dba_indexes WHERE lower(index_name)=lower('PLACERGROUP_CHARGETIME') AND lower(table_name)=lower('PLACERGROUP') AND OWNER='POOR';
  IF cnt=1 THEN
    EXECUTE immediate'drop index  POOR.PLACERGROUP_CHARGETIME';
  END if; 
end;
/
create index POOR.PLACERGROUP_CHARGETIME on POOR.PLACERGROUP(CHARGETIME) tablespace jxindexspace online;
/

 -- 查看表的收集比率
 select dbms_stats.get_prefs('STALE_PERCENT','FIAB','OPACCOUNTLIST') stale_percent from dual; 

 --设置表的【统计信息过期阈值】为5%,(默认为10%)
 exec dbms_stats.set_table_prefs('FIAB','OPACCOUNTLIST','STALE_PERCENT',5);

1.3、GV$SQLAREA视图使用总览

--IO和内存消耗多的sql
SELECT * FROM (  select OPTIMIZER_COST, cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) as elapsed_time_Avg
                    , elapsed_time, executions, cpu_time, buffer_gets, disk_reads,last_load_time,module,hash_value, PARSING_USER_ID,SORTS,COMMAND_TYPE,SQL_FULLTEXT 
                FROM gv$SQLAREA   
                WHERE buffer_gets > 10000000 OR disk_reads > 1000000   
                ORDER BY buffer_gets + 100 * disk_reads DESC
            )where ROWNUM<20 ;

--占IO的sql 
SELECT * FROM ( select OPTIMIZER_COST, cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) as elapsed_time_Avg
                    , elapsed_time, executions, cpu_time, buffer_gets, disk_reads,last_load_time,module,hash_value, PARSING_USER_ID,SORTS,COMMAND_TYPE,SQL_FULLTEXT 
               FROM gv$sqlarea   
               order BY disk_reads DESC  ---可以改为其他排序
            )where ROWNUM<20 ;

--平均执行慢的sql 
SELECT * FROM ( select OPTIMIZER_COST, cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) as elapsed_time_Avg
                    , elapsed_time, executions, cpu_time, buffer_gets, disk_reads,last_load_time,module,hash_value, PARSING_USER_ID,SORTS,COMMAND_TYPE,SQL_FULLTEXT 
               FROM gv$sqlarea   
               order BY cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) DESC   
            )where ROWNUM<20 ;

--总耗时多的sql 
SELECT * FROM ( select OPTIMIZER_COST, cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) as elapsed_time_Avg
                    , elapsed_time, executions, cpu_time, buffer_gets, disk_reads,last_load_time,module,hash_value, PARSING_USER_ID,SORTS,COMMAND_TYPE,SQL_FULLTEXT 
               FROM gv$sqlarea   
               order BY elapsed_time DESC   
            )where ROWNUM<20 ;
            
--占cpu的sql 
SELECT * FROM (  select OPTIMIZER_COST, cast( elapsed_time/(case when executions is null or executions=0 then 1 else executions end) as number(18,0)) as elapsed_time_Avg
                    , elapsed_time, executions, cpu_time, buffer_gets, disk_reads,last_load_time,module,hash_value, PARSING_USER_ID,SORTS,COMMAND_TYPE,SQL_FULLTEXT 
               FROM gv$sqlarea   
               order BY cpu_time DESC   
            )where ROWNUM<20 ;

1.4、查询最近(一段时间内)执行的500条SQL语句:

SELECT ROWNUM, t.* FROM (SELECT a.SQL_ID, a.parsing_schema_name AS SCHEMA, a.module AS MODULE, a.sql_text AS SQL_TEXT 
    , a.sql_fulltext AS SQL_FULLTEXT 
    , a.OPTIMIZER_COST AS OPTIMIZER_COST
    , a.parse_calls AS PARSE_CALLS 
    , a.buffer_gets AS BUFFER_GETS 
    , a.disk_reads AS DISK_READS 
    , decode(a.executions,0,1,a.executions) AS EXECUTIONS 
    , round(a.cpu_time / 1000000, 2) AS CPU_TIME 
    , round(a.cpu_time / (decode(a.executions,0,1,a.executions) * 1000000), 2) AS CPU_TIME_PER_EXE 
    , round(a.elapsed_time / (decode(a.executions,0,1,a.executions) * 1000000), 2) AS ELAPSED_TIME_PER_EXE 
    , a.LAST_LOAD_TIME, a.LAST_ACTIVE_TIME 
FROM gv$sqlarea a 
WHERE ( a.LAST_LOAD_TIME > to_date('2023/04/24 12:18:02', 'yyyy/MM/dd hh24:mi:ss') OR a.LAST_ACTIVE_TIME > to_date('2023/04/24 12:18:02', 'yyyy/MM/dd hh24:mi:ss') )
ORDER BY a.LAST_ACTIVE_TIME DESC, a.LAST_LOAD_TIME DESC) t WHERE ROWNUM <= 500;

1.5、获取SQL的绑定变量(参数)值

-- 1、v$sql_bind_capture
SELECT T.NAME, T.POSITION, T.DATATYPE_STRING, T.VALUE_STRING, T.VALUE_ANYDATA
FROM V$SQL_BIND_CAPTURE T
WHERE SQL_ID = '9gq78x8ns3q1x';

-- 2、DBMS_SQLTUNE.EXTRACT_BINDS( v$sql.BIND_DATA )
SELECT DBMS_SQLTUNE.EXTRACT_BINDS(BIND_DATA) BIND 
FROM V$SQL 
WHERE SQL_ID = '9gq78x8ns3q1x';

-- 3、历史快照表找(DBA_HIST_SQLBIND)
SELECT SNAP_ID, NAME, POSITION, VALUE_STRING, LAST_CAPTURED, WAS_CAPTURED  
FROM DBA_HIST_SQLBIND  
WHERE SQL_ID = '9gq78x8ns3q1x';
----------snap_id, AWR报告的快照ID。
----------name, 绑定变量的名称
----------position,绑定值在SQL语句中的位置,以1,2,3进行标注  
----------value_string,就是绑定变量值
----------last_captured,最后捕获到的时间
----------was_captured,是否绑定被捕获,where子句前面的绑定不进行捕获。

-- 4、系统表找(wrh$_sqlstat)
SELECT 
dbms_sqltune.extract_bind(bind_data, 1).value_string AS a, 
dbms_sqltune.extract_bind(bind_data, 2).value_string AS b
FROM wrh$_sqlstat
WHERE sql_id = '9gq78x8ns3q1x';

1.6、查询没有使用绑定变量来的SQL语句

/*
识别没有使用绑定变量的SQL语句利用v$sql视图的FORCE_MATCHING_SIGNATURE字段,可以识别可能从绑定变量或CURSOR_SHARING获益的SQL语句。
如果SQL已使用绑定变量或者CURSOR_SHARING,则FORCE_MATCHING_SIGNATURE在对其进行标识时将给出同样的签名。
换句话说,如果两个SQL语句除了字面量的值之外都是相同的,它们将拥有相同的FORCE_MATCHING_SIGNATURE,这意味着如果为他们提供了绑定变量或者CURSOR_SHARING,它们就成了完全相同的语句。
使用FORCE_MATCHING_SIGNATURE识别没有使用绑定变来的SQL语句。
*/
WITH FORCE_MATHCES AS
   (SELECT L.FORCE_MATCHING_SIGNATURE MATHCES,
        MAX(L.SQL_ID || L.CHILD_NUMBER) MAX_SQL_CHILD,
        DENSE_RANK() OVER(ORDER BY COUNT(*) DESC) RANKING
    FROM GV$SQL L
    WHERE L.FORCE_MATCHING_SIGNATURE <> 0
        AND L.PARSING_SCHEMA_NAME <> 'SYS'
    GROUP BY L.FORCE_MATCHING_SIGNATURE
    HAVING COUNT(*) > 10)
SELECT V.SQL_ID, V.SQL_FULLTEXT, V.PARSING_SCHEMA_NAME, FM.MATHCES, FM.RANKING
FROM FORCE_MATHCES FM, GV$SQL V
WHERE FM.MAX_SQL_CHILD = (V.SQL_ID || V.CHILD_NUMBER)
    AND FM.RANKING <= 5
ORDER BY FM.RANKING DESC;

--利用FORCE_MATCHING_SIGNATURE捕获非绑定变量SQL
SELECT COUNT(1), TXT FROM (
    SELECT *
    FROM (SELECT SQL_TEXT TXT, --SUBSTR(SQL_TEXT,0,80) TXT,
              FORCE_MATCHING_SIGNATURE,
              COUNT (1) OVER (PARTITION BY FORCE_MATCHING_SIGNATURE) RID
          FROM GV$SQL
          WHERE FORCE_MATCHING_SIGNATURE > 0
              AND FORCE_MATCHING_SIGNATURE != EXACT_MATCHING_SIGNATURE)
    WHERE RID > 100 ) 
GROUP BY TXT 
ORDER BY COUNT(1) DESC;

1.7、查询执行最慢的50条SQL语句:

SELECT *
FROM (SELECT
SA.FIRST_LOAD_TIME,
SA.LAST_ACTIVE_TIME,
SA.SQL_TEXT,
SA.SQL_FULLTEXT,
SA.EXECUTIONS "执行次数",
ROUND(SA.ELAPSED_TIME / 1000000, 2) "总执行时间",
ROUND(SA.ELAPSED_TIME / 1000000 / SA.EXECUTIONS, 2) "平均执行时间",
SA.COMMAND_TYPE,
SA.PARSING_USER_ID,
U.USERNAME,
SA.HASH_VALUE
FROM V$SQLAREA SA
LEFT JOIN ALL_USERS U
ON SA.PARSING_USER_ID = U.USER_ID
WHERE SA.EXECUTIONS > 0
--AND U.USERNAME=‘APPS’ 
ORDER BY SA.LAST_ACTIVE_TIME DESC,(SA.ELAPSED_TIME / SA.EXECUTIONS) DESC)
WHERE ROWNUM <= 50;

1.8、查询当天执行慢(大于5秒)的SQL语句:

SELECT S.SQL_TEXT, S.SQL_FULLTEXT, S.SQL_ID, ROUND(ELAPSED_TIME / 1000000 / (CASE WHEN (EXECUTIONS = 0 OR NVL(EXECUTIONS, 1 ) = 1) THEN 1 ELSE EXECUTIONS END), 2) "执行时间’S’"
  , S.EXECUTIONS "执行次数", S.OPTIMIZER_COST COST, S.SORTS, S.PARSING_SCHEMA_NAME, S.MODULE --连接模式(JDBC THIN CLIENT:程序)
  , S.LOCKED_TOTAL, S.PHYSICAL_READ_REQUESTS "物理读请求", S.PHYSICAL_READ_BYTES "物理读", S.PHYSICAL_WRITE_REQUESTS "物理写请求", S.PHYSICAL_WRITE_BYTES "物理写"
  , S.ROWS_PROCESSED "返回行数", S.DISK_READS "磁盘读", S.DIRECT_WRITES "直接路径写", S.PARSING_SCHEMA_NAME, S.LAST_ACTIVE_TIME
  FROM GV$SQLAREA S
  WHERE ROUND(ELAPSED_TIME / 1000000 / (CASE WHEN (EXECUTIONS = 0 OR NVL(EXECUTIONS, 1 ) = 1) THEN 1 ELSE EXECUTIONS END),2) > 5 --1000000微秒 = 1S
    --AND S.PARSING_SCHEMA_NAME = USER -- USER-当前连接用户
    --AND S.COMMAND_TYPE IN (2, 3, 5, 6, 189) -- 2-INSERT; 3-SELECT 6-UPDATE; 7-DELETE; 189-MERGE
    AND (S.LAST_LOAD_TIME >= TRUNC(SYSDATE-1) OR S.LAST_ACTIVE_TIME >= TRUNC(SYSDATE-1))
  ORDER BY "执行时间’S’" DESC;

1.9、 查询执行次数最多前100条SQL语句

SELECT *
FROM (SELECT S.SQL_ID, S.SQL_TEXT, S.SQL_FULLTEXT, S.EXECUTIONS, S.PARSING_USER_ID, U.USERNAME
      ,RANK() OVER(ORDER BY EXECUTIONS DESC) EXEC_RANK FROM V$SQL S LEFT JOIN ALL_USERS U ON U.USER_ID = S.PARSING_USER_ID) T
WHERE EXEC_RANK <= 100;

1.10、查询最近一分钟最消耗CPU的SQL语句

--最近一分钟最消耗CPU的语句
SELECT ASH.INST_ID, ASH.SQL_ID, (SELECT VS.SQL_TEXT FROM GV$SQLAREA VS WHERE VS.SQL_ID = ASH.SQL_ID AND ASH.INST_ID = VS.INST_ID) SQL_TEXT
       , ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME, ASH.SESSION_INFO, COUNTS, PCTLOAD * 100 || '%' PCTLOAD
FROM (SELECT ASH.INST_ID, ASH.SQL_ID, ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME
        , (ASH.MODULE || '--' || ASH.ACTION || '--' || ASH.PROGRAM || '--' || ASH.MACHINE || '--' || ASH.CLIENT_ID || '--' || ASH.SESSION_TYPE) SESSION_INFO
        , COUNT(*) COUNTS, ROUND(COUNT(1)/SUM(COUNT(1)) OVER(), 2) PCTLOAD, DENSE_RANK() OVER(ORDER BY COUNT(1) DESC) RANK_ORDER
        FROM GV$ACTIVE_SESSION_HISTORY ASH
        WHERE  ASH.SESSION_TYPE <> 'BACKGROUND' AND ASH.SESSION_STATE = 'ON CPU' AND SAMPLE_TIME > SYSDATE-1 / (24*60)
        GROUP BY ASH.INST_ID, ASH.SQL_ID, ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME
          , (ASH.MODULE || '--' || ASH.ACTION || '--' || ASH.PROGRAM || '--' || ASH.MACHINE || '--' || ASH.CLIENT_ID || '--' || ASH.SESSION_TYPE)
      ) ASH
WHERE RANK_ORDER <= 10
ORDER BY COUNTS DESC;

--最近一分钟最消耗CPU的会话
SELECT V.SESSION_ID, 
       COUNT(*)
FROM   V$ACTIVE_SESSION_HISTORY V
WHERE  V.SESSION_STATE = 'ON CPU'
AND    V.SAMPLE_TIME > SYSDATE - 10/ (24 * 60)
GROUP  BY V.SESSION_ID
ORDER  BY COUNT(*) DESC;

1.11、查询最近一分钟最消耗I/O的SQL语句

--最近一分钟最消耗I/O(资源)的SQL语句
SELECT ASH.INST_ID, ASH.SQL_ID
       , (SELECT VS.SQL_TEXT FROM GV$SQLAREA VS WHERE VS.SQL_ID = ASH.SQL_ID AND ASH.INST_ID = VS.INST_ID) SQL_TEXT
       , ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME, ASH.SESSION_INFO, COUNTS, PCTLOAD * 100 || '%' PCTLOAD
FROM ( SELECT ASH.INST_ID, ASH.SQL_ID, ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME
         , (ASH.MODULE || '--' || ASH.ACTION || '--' || ASH.PROGRAM || '--' || ASH.MACHINE || '--' || ASH.CLIENT_ID || '--' || ASH.SESSION_TYPE) SESSION_INFO
         , COUNT(*) COUNTS, ROUND(COUNT(*) / SUM(COUNT(*)) OVER(), 2) PCTLOAD, DENSE_RANK() OVER(ORDER BY COUNT(*) DESC) RANK_ORDER
       FROM GV$ACTIVE_SESSION_HISTORY ASH
       WHERE ASH.SESSION_TYPE <> 'BACKGROUND' AND ASH.SESSION_STATE = 'WAITING' AND ASH.SAMPLE_TIME > SYSDATE - 1 / (24*60)
         AND ASH.WAIT_CLASS = 'USER I/O'
       GROUP BY ASH.INST_ID, ASH.SQL_ID, ASH.SQL_CHILD_NUMBER, ASH.SQL_OPNAME
         ,(ASH.MODULE || '--' || ASH.ACTION || '--' || ASH.PROGRAM || '--' || ASH.MACHINE || '--' || ASH.CLIENT_ID || '--' || ASH.SESSION_TYPE)
     ) ASH
WHERE RANK_ORDER <= 10
ORDER BY COUNTS DESC;

--最近一分钟最消耗I/O(资源)的会话
SELECT ASH.SESSION_ID,
       ASH.SESSION_SERIAL#,
       ASH.USER_ID,
       ASH.PROGRAM,
       SUM(DECODE(ASH.SESSION_STATE, 'ON CPU', 1, 0)) "CPU",
       SUM(DECODE(ASH.SESSION_STATE, 'WAITING', 1, 0)) - SUM(DECODE(ASH.SESSION_STATE, 'WAITING', DECODE(ASH.WAIT_CLASS, 'USER I/O', 1, 0), 0)) "WAITING",
       SUM(DECODE(ASH.SESSION_STATE, 'WAITING', DECODE(ASH.WAIT_CLASS, 'USER I/O', 1, 0), 0)) "IO",
       SUM(DECODE(ASH.SESSION_STATE, 'ON CPU', 1, 1)) "TOTAL"
FROM V$ACTIVE_SESSION_HISTORY ASH
WHERE ASH.SAMPLE_TIME > SYSDATE - 1 / (24 * 60)
GROUP BY ASH.SESSION_ID, ASH.USER_ID, ASH.SESSION_SERIAL#, ASH.PROGRAM
ORDER BY SUM(DECODE(ASH.SESSION_STATE, 'ON CPU', 1, 1));  

1.12、查询最近一天使用了全表扫描的语句

SELECT s.sql_text, P.OBJECT_OWNER,
       P.SQL_ID,
       P.OPERATION,
       P.OPTIONS,
       S.LAST_ACTIVE_TIME,
       ROW_NUMBER() OVER(PARTITION BY P.SQL_ID ORDER BY P.SQL_ID) AS ROWNUMS
       FROM GV$SQL_PLAN P, GV$SQLAREA S
 WHERE S.SQL_ID = P.SQL_ID
   AND P.OPERATION = 'TABLE ACCESS'
   AND P.OPTIONS = 'FULL'
   AND P.OBJECT_OWNER != 'SYS'
   AND S.LAST_ACTIVE_TIME >= trunc(SYSDATE-1)
 ORDER BY S.LAST_ACTIVE_TIME DESC;

1.13、查看SQL执行计划(EXPLAIN PLAN)

-->>>> 第一步:set autotrace on
-->>>> 第二步:explain plan for select sysdate from dual; 
-->>>> 第三步:dbms_xplan.DISPLAY_CURSOR 

ALTER SESSION SET STATISTICS_LEVEL = ALL;  --不设置无法获得A-ROWS等信息
SELECT SYSDATE FROM DUAL;  --运行一个SQL

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS'));  --如果SQL_ID 输入NULL 则默认为之前运行的一条SQL,即SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR)
ALTER SESSION SET STATISTICS_LEVEL=TYPICAL;

-- 如果通过AWR已经获取了SQL_ID,则可以直接得到执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('1v1gv616u8jdb'));
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('1v1gv616u8jdb',NULL,'ADVANCED ALLSTATS LAST PEEKED_BINDS'));

1.14、使用执行计划视图(DBA_HIST_SQL_PLAN / GV$SQL_PLAN)定位执行成本高的SQL语句

SELECT A.SQL_ID, MODULE,PLAN_HASH_VALUE,
       ID,
       LPAD (' ', DEPTH) || OPERATION OPERATION,
       OPTIONS,
       OBJECT_OWNER,
       OBJECT_NAME,
       OPTIMIZER,
       COST,
       ACCESS_PREDICATES,
       FILTER_PREDICATES
FROM DBA_HIST_SQL_PLAN A, (SELECT SQL_ID, MODULE FROM GV$SQL) B
WHERE A.SQL_ID=B.SQL_ID AND B.MODULE IN ('jsenv.exe','w3wp.exe')
      AND COST > 20000
      --AND OBJECT_NAME NOT IN ('PRINTCHECKTREATCREDENCEVIEW','PERSONALAPPLICATIONMEDIVIEW','PERSONALAPPLICATIONMEDIVIEW_CS','PERSONALAPPLICATIONMEDIVIEW_cs','QUERYCONTEXTIDENTITY','PLACERGROUPQUERYVIEW')
      --AND FILTER_PREDICATES IS NOT NULL 
      --AND A.SQL_ID = 'f705bwx3q0ydq'
ORDER BY COST DESC;


SELECT '| Operation                         |Object Name                    |  Rows | Bytes|   Cost |'
AS "Explain Plan in library cache:" FROM DUAL
UNION ALL
SELECT RPAD('| '||SUBSTR(LPAD(' ',1*(DEPTH-1))||OPERATION||
       DECODE(OPTIONS, NULL,'',' '||OPTIONS), 1, 35), 36, ' ')||'|'||
       RPAD(DECODE(ID, 0, '----------------------------',
       SUBSTR(DECODE(SUBSTR(OBJECT_NAME, 1, 7), 'SYS_LE_', NULL, OBJECT_NAME)
       ||' ',1, 30)), 31, ' ')||'|'|| LPAD(DECODE(CARDINALITY,NULL,'  ',
       DECODE(SIGN(CARDINALITY-1000), -1, CARDINALITY||' ',
       DECODE(SIGN(CARDINALITY-1000000), -1, TRUNC(CARDINALITY/1000)||'K',
       DECODE(SIGN(CARDINALITY-1000000000), -1, TRUNC(CARDINALITY/1000000)||'M',
       TRUNC(CARDINALITY/1000000000)||'G')))), 7, ' ') || '|' ||
       LPAD(DECODE(BYTES,NULL,' ',
       DECODE(SIGN(BYTES-1024), -1, BYTES||' ',
       DECODE(SIGN(BYTES-1048576), -1, TRUNC(BYTES/1024)||'K',
       DECODE(SIGN(BYTES-1073741824), -1, TRUNC(BYTES/1048576)||'M',
       TRUNC(BYTES/1073741824)||'G')))), 6, ' ') || '|' ||
       LPAD(DECODE(COST,NULL,' ', DECODE(SIGN(COST-10000000), -1, COST||' ',
       DECODE(SIGN(COST-1000000000), -1, TRUNC(COST/1000000)||'M',
       TRUNC(COST/1000000000)||'G'))), 8, ' ') || '|' AS "Explain plan"
FROM GV$SQL_PLAN SP
WHERE SQL_ID='f705bwx3q0ydq' ;


2、查询阻塞事件、锁及杀锁

2.1、查询历史等待事件

--阻塞
 SELECT  SAMPLE_TIME,SESSION_ID,SQL_ID,EVENT,P1,BLOCKING_SESSION, BLOCKING_SESSION_STATUS,PROGRAM,MODULE,MACHINE,SQL_OPNAME,SQL_PLAN_OPERATION,SQL_PLAN_OPTIONS,SQL_EXEC_START
 FROM GV$ACTIVE_SESSION_HISTORY -- DBA_HIST_ACTIVE_SESS_HISTORY 
 WHERE BLOCKING_SESSION IS NOT NULL  
 AND SAMPLE_TIME >TO_TIMESTAMP('2023-04-22 22:00:00','yyyy-mm-dd hh24:mi:ss')
 AND SAMPLE_TIME <TO_TIMESTAMP('2023-04-23 22:30:00','yyyy-mm-dd hh24:mi:ss');
  
--事件
 SELECT SAMPLE_TIME,SESSION_ID,SQL_ID,EVENT,P1,BLOCKING_SESSION, BLOCKING_SESSION_STATUS,PROGRAM,MODULE,MACHINE,SQL_OPNAME,SQL_PLAN_OPERATION,SQL_PLAN_OPTIONS,SQL_EXEC_START
 FROM GV$ACTIVE_SESSION_HISTORY -- DBA_HIST_ACTIVE_SESS_HISTORY 
 WHERE (EVENT = 'enq: TX - row lock contention' OR EVENT LIKE 'library cache%')
 AND SAMPLE_TIME >TO_TIMESTAMP('2023-04-22 22:00:00','yyyy-mm-dd hh24:mi:ss')
 AND SAMPLE_TIME <TO_TIMESTAMP('2023-04-23 22:30:00','yyyy-mm-dd hh24:mi:ss');

--事件次数 
WITH T AS( 
    SELECT S.SQL_ID, COUNT(1) CC 
    FROM DBA_HIST_ACTIVE_SESS_HISTORY S 
    WHERE  S.EVENT LIKE 'latch: row cache objects%'  -- LATCH: ROW CACHE OBJECTS等待事件
    AND S.SNAP_ID IN( 
        SELECT SNAP_ID FROM DBA_HIST_SNAPSHOT S 
        WHERE BEGIN_INTERVAL_TIME >TO_TIMESTAMP('2023-04-22 16:00:00','yyyy-mm-dd hh24:mi:ss') 
        AND BEGIN_INTERVAL_TIME <TO_TIMESTAMP('2023-04-23 22:30:00','yyyy-mm-dd hh24:mi:ss')) --快照时间
    GROUP BY  S.SQL_ID
 )
 SELECT S.SQL_ID, S.SQL_TEXT,CC
 FROM DBA_HIST_SQLTEXT S, T 
 WHERE S.SQL_ID = T.SQL_ID 
 ORDER BY CC DESC;

2.2、快速杀锁(包括临时表被占用导致无法修改表结构/存储过程被占用导致无法编译)

--快速杀锁
SELECT 'alter system kill session '''|| SID ||',' || SERIAL# || ',@'|| INST_ID ||''' immediate;'
FROM  GV$SESSION WHERE SID IN (
    SELECT BLOCKING_SESSION FROM GV$SESSION WHERE BLOCKING_SESSION IS NOT NULL);

--SELECT A.BLOCKING_SESSION ,A.* FROM GV$SESSION A WHERE A.BLOCKING_SESSION IS NOT NULL;
SELECT 'alter system kill session '''|| SID ||',' || SERIAL# || ',@'|| INST_ID ||''' immediate;',
   SYS_CONNECT_BY_PATH(A.SID || '@' || A.INST_ID, ' <- ') TREE, --  TREE最后一个为最终阻塞者.
   A.INST_ID,   A.PROCESS,   A.SID,   A.SERIAL#,   A.SQL_ID,   A.EVENT,   A.STATUS,   A.PROGRAM,
   A.MACHINE,   CONNECT_BY_ISLEAF AS ISLEAF,   LEVEL AS TREE_LEVEL
FROM GV$SESSION A
 START WITH A.BLOCKING_SESSION IS NOT NULL
 CONNECT BY (A.SID || '@' || A.INST_ID) = PRIOR
       (A.BLOCKING_SESSION || '@' || A.BLOCKING_INSTANCE);
       
--等待事件
--从v$session_wait中查找有问题的wait
SELECT EVENT,COUNT(*) FROM GV$SESSION_WAIT WHERE EVENT NOT LIKE '%idle%' GROUP BY EVENT ORDER BY COUNT(0) DESC;

-- 如果有library cache lock时,查看lock的都是些什么语句
SELECT A.USERNAME, A.MACHINE, A.PROGRAM, A.SID, A.SERIAL#, A.INST_ID, A.STATUS,A.BLOCKING_SESSION,A.BLOCKING_INSTANCE,A.BLOCKING_SESSION_STATUS
     , A.LOCKWAIT ,A.WAIT_TIME_MICRO,A.LOGON_TIME, A.SQL_EXEC_START ,A.PREV_EXEC_START
     , B.SPID "OS Process ID", A.SQL_ID, C.SQL_FULLTEXT 
FROM GV$SESSION A, GV$PROCESS B, GV$SQLAREA C 
WHERE B.ADDR=A.PADDR AND A.SQL_ADDRESS=C.ADDRESS(+) 
AND A.BLOCKING_SESSION IS NOT NULL
--AND A.SID IN (SELECT SID FROM GV$SESSION_WAIT WHERE EVENT = 'cursor: pin S wait on X')
ORDER BY A.SID ;

--或--
SELECT A.USERNAME, A.MACHINE, A.PROGRAM, A.SID, A.SERIAL#, A.INST_ID, A.STATUS,A.BLOCKING_SESSION,A.BLOCKING_INSTANCE,A.BLOCKING_SESSION_STATUS
     , A.LOCKWAIT ,A.WAIT_TIME_MICRO,A.LOGON_TIME, A.SQL_EXEC_START ,A.PREV_EXEC_START
     , A.SQL_ID,C.SQL_FULLTEXT 
FROM GV$SESSION A,  GV$SQLAREA C 
WHERE   A.SQL_ADDRESS=C.ADDRESS 
AND A.SID IN (SELECT SID FROM GV$SESSION_WAIT WHERE  EVENT ='Disk file operations I/O' OR EVENT='enq: TX - row lock contention') 
ORDER BY A.SID ; 

--发现有Library语句我们需要进一步blocker会话是谁
--注意:X$KGLPN是ORACLE系统表,需要用system用户以normal身份登录才能看到(使用)
SELECT S.SID, KGLPNMOD "Mode", KGLPNREQ "Req", SPID "OS Process",A.BLOCKING_SESSION,A.BLOCKING_INSTANCE,A.BLOCKING_SESSION_STATUS
FROM GV$SESSION_WAIT W, X$KGLPN P, GV$SESSION S ,GV$PROCESS O
WHERE P.KGLPNUSE=S.SADDR
AND KGLPNHDL=W.P1RAW
AND W.EVENT LIKE '%cursor%'
AND S.PADDR=O.ADDR;

--临时表被占用,无法修改表结构
SELECT  'alter system kill session '''|| SID ||',' || SERIAL# || ',@'|| INST_ID ||''' immediate;'
    FROM GV$SESSION  WHERE SID IN 
    (SELECT SID FROM GV$ENQUEUE_LOCK T WHERE T.TYPE='TO' 
        AND  ID1 IN (SELECT OBJECT_ID FROM DBA_OBJECTS WHERE LOWER(OBJECT_NAME)='temp_tablename') );  --TEMP_TABLENAME是临时表名,不带用户名,如TEMP_QUERYORDER
 
--存储过程被占用,无法编译
SELECT * FROM (
    SELECT 'alter system kill session '''|| SID ||',' || SERIAL# || ',@'|| INST_ID ||''' immediate;' 
    FROM  GV$SESSION WHERE SID IN (
        SELECT SESSION_ID FROM DBA_DDL_LOCKS 
        WHERE LOWER(NAME) = LOWER('PROC_NAME')  --说明:PROC_NAME为存储过程名,不带用户名,比如SENDSURGERYREQUESTBY
        )
    UNION SELECT 'alter procedure OWNER.PROC_NAME compile;'   --说明:OWNER.PROC_NAME为存储过程名,带用户名,比如POOR.SENDSURGERYREQUESTBY
        FROM DUAL
) ORDER BY 1 DESC;

--oracle手动锁表 
lock table tbl_t1 in row share mode nowait;                --2
lock table tbl_t1 in share update mode nowait;             --2
lock table tbl_t1 in row exclusive mode nowait;            --3
lock table tbl_t1 in share mode nowait;                    --4
lock table tbl_t1 in share row exclusive mode nowait;      --5
lock table tbl_t1 in exclusive mode nowait;                --6

/*
0:none
1:null      空                 
2:Row-S     行共享(RS):共享表锁   
3:Row-X     行排他锁(RX):用于行的修改
4:Share     共享锁(S):阻止其他DML操作
5:S/Row-X   共享行排他(SRX):阻止其他事务操作
6:exclusive 排他锁(X):独立访问使用
*/

2.3、检查是否有手工执行sql且锁表

SELECT  
    O.OWNER || '.' || O.OBJECT_NAME 被锁表名 , S.MACHINE  电脑, NVL(S.SQL_EXEC_START,S.PREV_EXEC_START) SQL执行时间,  L.CTIME 已持有或者等待锁的时间, S.PROGRAM, O.OBJECT_TYPE,
     'ALTER SYSTEM KILL SESSION '||''''|| S.SID ||','|| S.SERIAL# ||',@'|| S.INST_ID || '''  immediate;' AS 执行这个SQL可以KILL相应进程,
    S.INST_ID, S.SID ,  S.SERIAL# , S.TERMINAL, S.OSUSER ,
    S.MODULE, S.USERNAME, L.BLOCK, --是否阻塞其他会话锁申请 1:阻塞 0:不阻塞
    DECODE(L.TYPE,'TM','TABLE LOCK', 'TX','ROW LOCK', 'UL','用户锁', L.TYPE) LOCK_LEVEL,
    L.LMODE --会话保持的锁的模式。 
			-- 0=NONE; 
			-- 1=NULL ; 
			-- 2=ROW-S (SS,行级共享锁,其他对象只能查询这些数据行),SQL操作有SELECT FOR UPDATE、LOCK FOR UPDATE、LOCK ROW SHARE; 
      -- 3=ROW-X (SX,行级排它锁,在提交前不允许做DML操作),SQL操作有INSERT、UPDATE、DELETE、LOCK ROW SHARE;
      -- 4=SHARE(共享锁),SQL操作有CREATE INDEX、LOCK SHARE;
      -- 5=S/ROW-X (SSX,共享行级排它锁),SQL操作有LOCK SHARE ROW EXCLUSIVE;
      -- 6=EXCLUSIVE(排它锁),ALTER TABLE、DROP TABLE、DROP INDEX、TRUNCATE TABLE、LOOK EXCLUSIVE等DDL    
    ,S.SQL_EXEC_START,S.PREV_EXEC_START,S.STATUS,S.LOCKWAIT, S.CURRENT_QUEUE_DURATION,S.WAIT_TIME,S.WAIT_CLASS--, A.ACTION     
    ,S.BLOCKING_SESSION,S.BLOCKING_INSTANCE,S.BLOCKING_SESSION_STATUS
    ,S.WAIT_TIME_MICRO,S.LOGON_TIME
    ,A.SQL_TEXT
  FROM GV$SESSION S,  GV$LOCK L,  DBA_OBJECTS O,  GV$SQLAREA A
  WHERE L.SID         = S.SID
  AND L.ID1           = O.OBJECT_ID(+)
  AND S.USERNAME     IS NOT NULL
  AND S.PREV_SQL_ADDR = A.ADDRESS(+)  
  AND S.SQL_ADDRESS = A.ADDRESS(+)
  AND O.OBJECT_TYPE   ='TABLE'
  AND L.TYPE         IN ('TM','TX')
  AND OWNER NOT IN ('SYS')
  --AND L.BLOCK>0
  AND L.LMODE IN (3, 5,6) --行级排它锁 / 共享行级排它锁 / 排它锁
  AND PROGRAM IN ('SQL Developer','plsqldev.exe')
  AND O.OBJECT_NAME<>'PLAN_TABLE';

2.4、查询锁进程、主机、语句

SELECT  -- 'ALTER SYSTEM KILL SESSION '||''''|| S.SID ||','|| S.SERIAL# ||',@'|| S.INST_ID || '''  immediate;',
    S.INST_ID, S.SID ,  S.SERIAL# , S.MACHINE, S.PROGRAM, S.TERMINAL, S.OSUSER , L.CTIME, --已持有或者等待锁的时间
    S.MODULE, S.USERNAME, L.BLOCK, --是否阻塞其他会话锁申请 1:阻塞 0:不阻塞
    DECODE(L.TYPE,'TM','TABLE LOCK', 'TX','ROW LOCK', 'UL','用户锁', L.TYPE) LOCK_LEVEL,
    L.LMODE --会话保持的锁的模式。 0=NONE; 1=NULL ; 2=ROW-S (SS,行级共享锁,其他对象只能查询这些数据行),SQL操作有SELECT FOR UPDATE、LOCK FOR UPDATE、LOCK ROW SHARE; 
            -- 3=ROW-X (SX,行级排它锁,在提交前不允许做DML操作),SQL操作有INSERT、UPDATE、DELETE、LOCK ROW SHARE;
            -- 4=SHARE(共享锁),SQL操作有CREATE INDEX、LOCK SHARE;
            -- 5=S/ROW-X (SSX,共享行级排它锁),SQL操作有LOCK SHARE ROW EXCLUSIVE;
            -- 6=EXCLUSIVE(排它锁),ALTER TABLE、DROP TABLE、DROP INDEX、TRUNCATE TABLE、LOOK EXCLUSIVE等DDL
    ,O.OWNER, O.OBJECT_NAME, O.OBJECT_TYPE
    ,S.SQL_EXEC_START,S.PREV_EXEC_START,S.STATUS,S.LOCKWAIT, S.CURRENT_QUEUE_DURATION,S.WAIT_TIME,S.WAIT_CLASS, A.ACTION     
    ,S.BLOCKING_SESSION,S.BLOCKING_INSTANCE,S.BLOCKING_SESSION_STATUS
    ,S.WAIT_TIME_MICRO,S.LOGON_TIME
    ,A.SQL_FULLTEXT
  FROM GV$SESSION S,  GV$LOCK L,  DBA_OBJECTS O,  GV$SQLAREA A
  WHERE L.SID         = S.SID
  AND L.ID1           = O.OBJECT_ID(+)
  AND S.USERNAME     IS NOT NULL
  --AND S.PREV_SQL_ADDR = A.ADDRESS(+)  
  AND S.SQL_ADDRESS = A.ADDRESS(+)
  AND O.OBJECT_TYPE   ='TABLE'
  AND L.TYPE         IN ('TM','TX')
  --AND L.BLOCK>0
  AND L.LMODE IN ( 5,6)
  --AND EXISTS (SELECT * FROM GV$LOCK LB WHERE L.SID=LB.SID AND LB.BLOCK=1 )
  ;   

2.5、查询正在执行的SQL语句

-- 正在执行的语句
SELECT 'ALTER SYSTEM KILL SESSION '||''''|| B.SID ||','|| B.SERIAL# || ',@' || B.INST_ID || '''  immediate;', B.USERNAME 登录ORACLE用户名
       , B.SID , B.SERIAL#, SPID 操作系统ID, PADDR
       , B.MACHINE 计算机名,B.PROGRAM, B.OSUSER 
       , B.SQL_EXEC_START,B.PREV_EXEC_START,B.STATUS,B.LOCKWAIT, B.CURRENT_QUEUE_DURATION,B.WAIT_TIME,B.WAIT_CLASS,B.BLOCKING_SESSION,B.BLOCKING_INSTANCE
       , BLOCKING_SESSION_STATUS, SQL_TEXT 正在执行的SQL
FROM GV$PROCESS A, GV$SESSION B, GV$SQLAREA C
WHERE A.ADDR = B.PADDR
  AND B.SQL_HASH_VALUE = C.HASH_VALUE
  -- AND B.STATUS NOT IN ('KILLED','INACTIVE')
  AND B.STATUS IN ('ACTIVE')
  --AND LOWER(B.MACHINE) LIKE '%bj%'
ORDER BY B.SQL_EXEC_START;

-- 正在执行的语句(一段时间内)
SELECT SID, S.USERNAME 用户名, S.LAST_CALL_ET 持续时间, S.STATUS 状态, S.LOCKWAIT 等待锁, S.MACHINE, S.TERMINAL, S.PROGRAM, S.SQL_ADDRESS
    , A.EXECUTIONS 同SQL_执行次数, A.DISK_READS 同SQL_磁盘读次数, A.PHYSICAL_READ_BYTES 同SQL_物理读字节
    , A.DIRECT_WRITES 同SQL_DIRECT_WRITES, A.BUFFER_GETS 同SQL_BUFFER_GETS, A.APPLICATION_WAIT_TIME 同SQL_APPLICATION_WAIT_TIME
    , A.CLUSTER_WAIT_TIME 同SQL_CLUSTER_WAIT_TIME,  A.USER_IO_WAIT_TIME 同SQL_USER_IO_WAIT_TIME
    , A.OPTIMIZER_COST 同SQL_OPTIMIZER_COST, S.LOGON_TIME 开始登入时间, A.SQL_TEXT
FROM GV$SESSION S, GV$PROCESS P, GV$SQLAREA A
WHERE S.PADDR = P.ADDR AND S.SQL_HASH_VALUE = A.HASH_VALUE 
--    AND S.STATUS = 'ACTIVE'
--    AND S.USERNAME IS NOT NULL
--ORDER BY S.LAST_CALL_ET DESC; 
    AND S.STATUS NOT IN ('INACTIVE')
    AND S.LOGON_TIME > SYSDATE-0.2
ORDER BY A.DISK_READS DESC; 

-- 每个Session的CPU占用情况
SELECT SS.SID, SE.COMMAND, SS.VALUE CPU, SE.USERNAME, SE.PROGRAM,SE.MACHINE,SE.SQL_ID, SE.*
FROM V$SESSTAT SS, V$SESSION SE
WHERE SS.STATISTIC# IN
    ( SELECT STATISTIC#
      FROM V$STATNAME
      WHERE LOWER(NAME) = 'cpu used by this session' )
    AND SE.SID = SS.SID
    AND SS.SID > 6
ORDER BY CPU DESC ;

2.6、查询分布式事务(2PC)遗留锁

-- 查询未提交的锁
SELECT * FROM DBA_2PC_PENDING;
SELECT * FROM SYS.PENDING_TRANS$; --要存在 DBA_2PC_PENDING.LOCAL_TRAN_ID 的一样记录;否则要补数据
SELECT * FROM SYS.PENDING_SESSIONS$ --要存在 DBA_2PC_PENDING.LOCAL_TRAN_ID 的一样记录;否则要补数据
--输出结果:LOCAL_TRAN_ID GLOBAL_TRAN_ID  STATE MIXED ADVICE  TRAN_COMMENT  FAIL_TIME FORCE_TIME  RETRY_TIME  OS_USER OS_TERMINAL HOST  DB_USER COMMIT#
--1 18.0.229  SGSYTEST.4e936cdb.18.0.229  collecting  no      2021/12/3 17:49:36    2023/1/10 18:00:05  luyanlin  unknown luyanlin-5040 APPS  3696577323
--2 28.24.1850  SGSYTEST.4e936cdb.28.24.1850  collecting  no      2022/5/7 10:39:30   2023/1/10 18:00:05  heshushu  unknown Hss APPS  5298498559

-- 杀锁
SELECT 'rollback force ''' || LOCAL_TRAN_ID || '''' FROM SYS.PENDING_TRANS$;
-- 或
SELECT 'commit force ''' || LOCAL_TRAN_ID||'''' FROM SYS.PENDING_TRANS$;
-- 断开所有客户端连接
SELECT 'alter system kill session ''' || SID || ',' || SERIAL# || ''';'  FROM V$SESSION WHERE SID>50;

--*****××××××××××××××× 如果DBA_2PC_PENDING找不到报错提示的LOCAL_TRAN_ID,则可能是数据不完整,要手工插入数据后再ROLLBACK *************************
-- ORACLE系统表X$KTUXE(以及X$打头的)需要用system的normal身份登录才可以看到(查询)
--1、查基表,确认是否存在报错的事务ID
SELECT KTUXEUSN, KTUXESLT, KTUXESQN /* TRANSACTION ID */
    ,KTUXESTA STATUS, KTUXECFL FLAGS 
FROM X$KTUXE
WHERE KTUXESTA!='INACTIVE'
    --AND KTUXEUSN= 72
    ;
-- 通过X$KTUXE这个基表,我们看到确实存在这个事务,而且是PREPARED状态。
    
--2、由于DBA_2PC_PENDING试图是依赖于PENDING_TRANS$这个表,同时事务是与SESSION关联在一起的,所以我们需要手工往PENDING_TRANS$和PENDING_SESSIONS$两个表中插入数据。
INSERT INTO SYS.PENDING_TRANS$ (LOCAL_TRAN_ID, GLOBAL_TRAN_FMT, GLOBAL_ORACLE_ID
    ,STATE,  STATUS,  SESSION_VECTOR, RECO_VECTOR,TYPE#,  FAIL_TIME, RECO_TIME)
VALUES( '72.0.1608712',  306206,  'XXXXXXX.12345.1.2.3',
    'prepared','P',  HEXTORAW( '00000001' ),  HEXTORAW( '00000000' ),  0, SYSDATE, SYSDATE );
     
INSERT INTO SYS.PENDING_SESSIONS$
VALUES( '72.0.1608712',
    1, HEXTORAW('05004F003A1500000104'),
    'C', 0, 30258592, '',
    146 );
    
COMMIT;

--3、ROLLBACK 
ROLLBACK FORCE '72.0.1608712';

2.7、查询作业(执行情况)(ALL_SCHEDULER_JOBS; DBA_SCHEDULER_JOBS; DBA_SCHEDULER_RUNNING_JOBS; DBA_SCHEDULER_JOB_RUN_DETAILS)

declare
  row_job ALL_SCHEDULER_JOBS%rowtype;
  cursor cur_job
  is select * from ALL_SCHEDULER_JOBS where "ENABLED"='TRUE' AND OWNER in ('APPS','CONCEPT','CONFIG','DATA','ESB','FIAB','GZRHIN','POOR','PORX','PRPA');
begin
  open cur_job;
  loop
    fetch cur_job into row_job;
    exit when cur_job%notfound;
    dbms_output.put_line('begin');
    dbms_output.put_line('  sys.dbms_scheduler.disable(name => ''' || row_job.OWNER || '.' || row_job.JOB_NAME || ''');');
    dbms_output.put_line('end;');
    dbms_output.put_line('/');
  end loop;
  close cur_job;
end;
/

-- 查看没有正常运行的作业
SELECT A.OWNER, A.JOB_NAME, A.COMMENTS, A.ENABLED ,A.STATE 
FROM DBA_SCHEDULER_JOBS A 
WHERE (A.ENABLED<>'TRUE' OR A.STATE<>'SCHEDULED') 
--AND  A.OWNER NOT IN ('SYS') 
;

-- 查看job的运行日志
SELECT T.OWNER, T.JOB_NAME, T.STATUS, T.ERROR#, T.ERRORS, T.REQ_START_DATE, T.ACTUAL_START_DATE, T.RUN_DURATION, T.*
FROM DBA_SCHEDULER_JOB_RUN_DETAILS T
--WHERE T.JOB_NAME = 'JOB_BOOK1' 
WHERE T.ACTUAL_START_DATE > SYSDATE-0.01 
ORDER BY T.LOG_DATE DESC;

-- 查看job的最后运行时间
SELECT OWNER, JOB_NAME, STATUS, ERROR#, ERRORS, MAX(LOG_DATE) 最后运行时间
FROM DBA_SCHEDULER_JOB_RUN_DETAILS T
WHERE ACTUAL_START_DATE >TO_DATE('2023-04-01 00:00:00','yyyy-mm-dd HH24:mi:ss')  
GROUP BY OWNER,JOB_NAME,STATUS,ERROR#,ERRORS
ORDER BY MAX(LOG_DATE) DESC;

-- 查看有哪些作业正在运行
SELECT * FROM DBA_SCHEDULER_RUNNING_JOBS;

--<<运行作业>>===============
grant execute on dbms_job to sys; 
grant execute on dbms_job to fiab; 
BEGIN
    dbms_scheduler.run_job('"FIAB"."testjob"');
END;

--<<停止作业>>===============
--1、查看正在运行的job;
SELECT * FROM USER_SCHEDULER_RUNNING_JOBS ;

--2、根据SID查出对应的SESSION;
SELECT SID, SERIAL# FROM V$SESSION WHERE SID=690;

--3、KILL对应的SESSION;
ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE;

2.8、ORACLE自带(系统)作业

select * FROM DBA_SCHEDULER_JOBS where job_name not in (select JOB_NAME FROM ALL_SCHEDULER_JOBS);

PROGRAM_NAME列这些内容要到下面的系统表找对应存储过程

SELECT * FROM dba_scheduler_programs; (譬如 dbms_scheduler.auto_purge 对应 SYS.DBMS_SCHEDULER 包里面的存储过程 auto_purge)
测试代码:
begin
  -- Call the procedure
  sys.dbms_scheduler.auto_purge;
end;

posted on 2023-04-24 14:17  Chr☆s  阅读(93)  评论(0编辑  收藏  举报