PL/SQL 包编译时hang住的处理

PL/SQL 包编译时hang住的处理

转自:http://blog.csdn.net/leshami/article/details/7616923

最近PL/SQL包在编译时被hang住,起初以为是所依赖的对象被锁住。结果出乎意料之外。下面直接看代码演示。


1、在SQL*Plus下编译包时被hang住   
       
SQL> alter package bo_syn_data_pkg compile;  
alter package bo_syn_data_pkg compile  
*  
ERROR at line 1:  
ORA-01013: user requested cancel of current operation  
 
Elapsed: 00:04:52.65                                                                  -->强行中断,此时编译时间已经超过4分钟   
 
SQL> alter package bo_syn_data_pkg compile body;          -->编译Body时也被hang住   
>alter package bo_syn_data_pkg compile body  
*  
ERROR at line 1:  
ORA-01013: user requested cancel of current operation  
 
Elapsed: 00:06:58.05  
 
SQL> select * from v$mystat where rownum<2;  
 
    SID STATISTIC#          VALUE  
------ ---------- ----------   
  1056                                  1  
 
Elapsed: 00:00:00.01  

SQL> select sid,serial#,username from v$session where sid=1056;  
 
    SID      SERIAL#        Oracle User  
------ ---------- ---------------   
  1056          57643 GOEX_ADMIN  
 
Elapsed: 00:00:00.01  
 
2、故障分析  
-->在session 2中监控,没有任何对象被锁住   
SQL> @locks_blocking   
no rows selected  
 
-->监控编译的session时发现出现library cache pin事件   
SQL> select sid,seq#,event,p3text,wait_class from v$session_wait where event like 'library cache pin';  
 
            SID            SEQ# EVENT                                        P3TEXT                                                                    WAIT_CLASS  
---------- ---------- ------------------------- ---------------------------------------- --------------------   
          1056                69 library cache pin                100*mode namespace                                            Concurrency  
 
-->来看看library cache pin   
-->The library cache pin wait event is associated with library cache concurrency. It occurs when the   
-->session tries to pin an object in the library cache to modify or examine it. The session must acquire a   
-->pin to make sure that the object is not updated by other sessions at the same time. Oracle posts this   
-->event when sessions are compiling or parsing PL/SQL procedures and views.   
-->上面的描述即是需要将对象pin到library cache,且此时这个对象没有被其他对象更新或持有。对我们的这个包而言,即此时没有其它对象   
-->修改该对象或者其依赖的对象没有被锁住。而此时出现该等待事件意味着包或其依赖对象一定被其它session所持有。前面的查询没有找到任何   
-->锁定对象,看来一定包被其它session所持有。   
 
-->查看当前数据库所有的session的情况   
-->发现有一个unknow的session   
SQL> @sess_users_active  
 
----------------------------------------------------    
| Active User Sessions (All)                                                |  
----------------------------------------------------    
 
    SID Serial ID      Status      Oracle User        O/S User  O/S PID Session Program                          Terminal    Machine  
------ --------- --------- -------------- ------------ -------- -------------------------- ---------- ---------   
  1086        59678      ACTIVE        GOEX_ADMIN            oracle    5840    oracle@Dev-DB-04 (J000)          UNKNOWN  Dev-DB-04  
  1093        54214      ACTIVE        GOEX_ADMIN            oracle    3847    sqlplus@Dev-DB-04 (TNS V1-          pts/1 Dev-DB-04  
 
-->查询该session运行的SQL语句   
-->经验证下面的SQL语句正是所编译包中的一部分   
SQL> @sess_query_sql  
Enter value for sid: 1086  
old    8:    AND s.sid = &&sid  
new    8:    AND s.sid = 1086  
 
SQL_TEXT  
--------------------------------------------------------------------------------   
SELECT BO_SYN_DATA_PKG.GEN_NEW_RECID AS REC_ID, TO_CHAR( GOATOTIMESTAMP, 'yyyymm  
dd' ) AS TRADE_DATE, 'DMA' AS TRANS_TYPE, TO_CHAR( GOATOACTIONID ) AS EXEC_KEY,  
GOATOGROUPREFNUM AS GRP_REF_NUM, GOATOL1ORDERID AS L1_ORDER_ID, GOATOCLORDID AS  
CLORDER_ID, TO_CHAR( GOATOACTION ) AS ACTION, GOATOACTIONSTATUS AS ACTION_STATUS  
, GOATOACCNUM AS ACC_NUM, GOATOPLCD AS PL_CD, GOATOTIMESTAMP AS ENTRY_DT, GOATOE  
NDTIMESTAMP AS EXEC_TIMESTAMP, GOATOBUYORSELL AS ORDER_SIDE, LTRIM( GOATOSTOCKCO  
DE, '0' ) AS STOCK_CD, GOATOORDERQTY AS ORDER_QTY, GOATOORDERTYPE AS ORDER_TYPE,  
  GOATOINPUTSOURCE AS ORDER_CHANNEL, GOATOINPUTSOURCE AS INPUTSOURCE, GOATOQTY AS  
  TRADED_QTY, GOATOUNITPRICE AS TRADED_PRICE, GOATOUNITPRICE AS ACTUAL_TRADED_PRI  
CE, GOATOQTY AS TOTAL_TRADED_QTY, GOATOUNSETTLEDAMT AS UNSETTLED_AMT, GOATOALLOR  
NONE AS IS_ALL_OR_NONE, GOATOTIMEINFORCE AS TIME_IN_FORCE, GOATOTRADETYPE AS TRA  
DE_TYPE, GOATOTRADEAEID AS AE_ID, 'N' AS IS_INDIRECT_TRADE, SYSDATE AS SYN_TIME,  
  NULL AS PROCESS_TIME, NULL AS PROCESS_M  
 
-->进一步观察Session的详细情况   
-->发现该session的MODULE为DBMS_SCHEDULER,即为一Oracle job,且ACTION与STATE均有描述   
-->由此推论,编译包时的Hang住应该是由该job引起的   
SQL> SELECT username  
              ,command  
              ,status  
              ,osuser  
              ,terminal  
              ,program  
              ,module  
              ,action  
              ,state  
  10  FROM    v$session  
  11  WHERE  sid = 1086;  
 
USERNAME          COMMAND STATUS    OSUSER        TERMINAL              PROGRAM                MODULE                  ACTION                            STATE  
---------- ---------- -------- ---------- --------------- --------------- --------------- -------------------- ----------   
GOEX_ADMIN                  3 ACTIVE    oracle        UNKNOWN                oracle@Dev-DB-0 DBMS_SCHEDULER  STP1_PERFORM_SYNC_DA WAITING  
                                                                                                                  4 (J000)                                              TA  
 
-->查看job中定义的情况,该job正好调用了该包   
SQL> select job_name,job_type,enabled,state,job_action from dba_scheduler_jobs where job_name like 'STP1%';  
 
JOB_NAME                                            JOB_TYPE                ENABL STATE  
------------------------------ ---------------- ----- ----------   
JOB_ACTION  
------------------------------------------------------------------------------------------------------------------   
STP1_PERFORM_SYNC_DATA                PLSQL_BLOCK          TRUE  RUNNING  
                                                                                                                                                                                                                                                        DECLARE  
                                                                                                                                  err_num NUMBER;  
                                                                                                                                  err_msg VARCHAR2(32767);  
 
                                                                                                                              BEGIN  
                                                                                                                                  err_num := NULL;  
                                                                                                                                  err_msg := NULL;  
 
                                                                                                                                  BO_SYN_DATA_PKG.perform_sync_data ( err_num, err_msg );  
                                                                                                                                  COMMIT;  
                                                                                                                              END;   
 
-->下面是该job运行的详细情况   
SQL> SELECT job_name  
              ,session_id  
              ,slave_process_id sl_pid  
              ,elapsed_time  
              ,slave_os_process_id sl_os_id  
  FROM    dba_scheduler_running_jobs;  
 
JOB_NAME                                            SESSION_ID        SL_PID ELAPSED_TIME                                    SL_OS_ID  
------------------------------ ---------- ---------- ------------------------------ ------------   
STP1_PERFORM_SYNC_DATA                            1086                20 009 00:51:17.79                            5840  
RUN_CHAIN$MY_CHAIN2                                                                  075 19:55:03.52  
RUN_CHAIN$MY_CHAIN1                                                                  075 19:57:45.91  
 
-->ELAPSED_TIME列, Elapsed time since the Scheduler job was started     
-->即该job一直处于运行状态,导致包编译失败   
 
3、解决  
-->将job对应的session kill掉   
SQL> alter system kill session '1086,59678';  
alter system kill session '1086,59678'  
*  
ERROR at line 1:  
ORA-00031: session marked for kill  
 
Elapsed: 00:01:00.03  
 
SQL> SELECT username  
              ,command  
              ,status  
              ,osuser  
              ,terminal  
              ,program  
              ,module  
              ,action  
              ,state  
  10  FROM    v$session  
  11  WHERE  sid = 1086;  
 
USERNAME          COMMAND STATUS    OSUSER        TERMINAL              PROGRAM                MODULE                  ACTION                            STATE  
---------- ---------- -------- ---------- --------------- --------------- --------------- -------------------- ----------   
GOEX_ADMIN                  3 KILLED    oracle        UNKNOWN                oracle@Dev-DB-0 DBMS_SCHEDULER  STP1_PERFORM_SYNC_DA WAITING  
                                                                                                                  4 (J000)                                              TA  
 
-->再次编译时还是被hang住,应该是session还没有被彻底kill   
SQL> alter package bo_syn_data_pkg compile;  
alter package bo_syn_data_pkg compile  
*  
ERROR at line 1:  
ORA-01013: user requested cancel of current operation  
 
-->再次kill session   
SQL> alter system kill session '1086,59678' immediate;  
 
System altered.  
 
-->此时包编译通过   
SQL> alter package bo_syn_data_pkg compile;  
 
Package altered.  
 
Elapsed: 00:00:00.32  
 
SQL> alter package bo_syn_data_pkg compile body;  
 
Package body altered.  
 
Elapsed: 00:00:00.18                 
 
 
4、总结  

-->包编译时被hang住,在排除代码自身编写出错的情形下,应考虑是否有对象或依赖对象被其它session所持有   
-->其次,包的编译需要将包pin到library cache,会产生library cahce pin等待事件   
-->对于引起异常的session将其kill之后再编译  

-->Author: Robinson Cheng     
-->Blog  : http://blog.csdn.net/robinson_0612 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 PL/SQL 中调用 Java 类或方法,需要按照以下步骤进行操作: 1. 使用 CREATE OR REPLACE JAVA SOURCE 创建 Java 源代码,然后使用 loadjava 工具将其加载到数据库中。 2. 创建 Java 存储过程或函数并将其编译为 class 文件。 3. 在 PL/SQL 中创建一个含外部过程和函数的,并将其与 Java 存储过程或函数进行映射。 4. 在 PL/SQL 中调用中的外部过程和函数,以调用 Java 存储过程或函数。 下面是一个简单的示例代码,演示如何在 PL/SQL 中调用 Java 存储过程: 1. 首先,创建一个名为 TestJava 的 Java 类,该类含一个名为 add 的方法,该方法接受两个整数参数并返回它们的和。 CREATE OR REPLACE JAVA SOURCE NAMED "TestJava" AS public class TestJava { public static int add(int a, int b) { return a + b; } }; / 2. 接下来,创建一个名为 addNumbers 的 Java 存储过程,该过程调用 TestJava 类的 add 方法,并将结果存储在一个 OUT 参数中。 CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "AddNumbers" AS import java.sql.*; public class AddNumbers { public static void add(int a, int b, int[] result) throws SQLException { result[0] = TestJava.add(a, b); } }; / 3. 然后,创建一个名为 MyPackage 的 PL/SQL ,该含一个名为 add 的过程,该过程调用 addNumbers 存储过程,并将结果返回给调用者。 CREATE OR REPLACE PACKAGE MyPackage AS PROCEDURE add(a IN NUMBER, b IN NUMBER, result OUT NUMBER); END; / CREATE OR REPLACE PACKAGE BODY MyPackage AS PROCEDURE add(a IN NUMBER, b IN NUMBER, result OUT NUMBER) AS LANGUAGE JAVA NAME 'AddNumbers.add(int, int, int[])'; END; / 4. 最后,可以在 PL/SQL 中调用 MyPackage 中的 add 过程,以调用 Java 存储过程,并将结果返回给调用者。 DECLARE result NUMBER; BEGIN MyPackage.add(1, 2, result); DBMS_OUTPUT.PUT_LINE(result); END; / 这就是在 PL/SQL 中调用 Java 存储过程的基本过程。注意,为了使 PL/SQL 能够调用 Java 存储过程,需要在数据库中安装 JDK,并将相关的 JAR 文件加载到数据库中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值