2011-05-16 151 views
3

我有一個web應用程序,它執行oracle存儲過程並在瀏覽器上顯示結果。 技術棧如下:瀏覽器< - > spring mvc < - > [(tomcat)jboss] < -jdbc-> oracle。 存儲過程具有結果的外部遊標,並且java代碼使用該遊標來檢索結果集。Oracle存儲過程在通過jdbc調用時掛起

一切都運行良好,直到添加了一個新的存儲過程,儘管在SQL Developer中足夠快地終止,但它從應用程序調用時會凍結。 java調試顯示代碼在OracleCallableStatement.execute處凍結。最初我以爲這個過程出了點問題,但是它在sql開發者上運行的很成功,所以我現在更多的指向了一個jdbc問題......

我想這與讀取一些死鎖有關out cursor,或者它可能是jdbc驅動程序中的錯誤(我使用的版本是:ojdbc6 - 11.1.0.7.0)? 任何想法?

謝謝

+0

你可以發佈存儲過程代碼和調用JDBC代碼嗎? – Nicholas 2011-05-17 13:39:02

+0

我可以給你一些代碼的提示; – ttr13p 2011-05-26 10:29:49

+0

不幸的是我不能打印代碼,但可以描述它。存儲過程非常複雜且效率不高。但它確實在sql開發人員中相對較快地終止; PROCEDURE stored_procedure(v_cur OUT SYS_REFCURSOR) IS BEGIN OPEN v_cur爲 WITH first_temp_table AS ( SELECT FROM <內部聯接但也有許多笛卡爾積> WHERE ) second_temp_table AS ( SELECT FROM <內連接,但也有很多笛卡爾產品> WHERE <使用first_temp_table>的子查詢> )<在臨時表上進行最終查詢選擇,具有非常複雜的不合理選擇和連接> – ttr13p 2011-05-26 10:53:39

回答

2

請確保您的會話沒有等待的行鎖。以下SQL * Plus腳本可以爲您提供有關如何執行此操作的提示。或者在Blocking Sessions下查看Oracle Enterprise Manager(Oracle Web GUI)。

BTW死鎖是不同的東西,數據庫會照顧殺死兩會的一個...

REM Purpose 
REM ------- 
REM Display locks currently held and requested. Displays which session a 
REM blocked lock is waiting for. 
REM 
REM Ver Who When  What 
REM --- --- ----  ---- 
REM 1.0 DrB 12-Dec-97 Initial version 
col uname  head "Username" form a12 
col sid  head "SID"  form 999 
col ltype  head "Type"  form a4 
col lmode  head "Mode"  form a10 
col blocked head "Wait"  form a4 
col details head "Details" form a40 
set verify off 
set pause on 
accept user prompt "Username [%]: " 
select SubStr('alter system kill session ''' || s.sid || ',' || s.serial# || ''';', 1, 40) as kill, s.username uname, 'DML' ltype, 
    decode (l.lmode,1,'Null', 
        2,'Row-S', 
        3,'Row-X', 
        4,'Share', 
        5,'S/Row-X', 
        6,'Exclusive') lmode, 
    decode (l.request,0,'No','Yes') blocked, 
    u.username||'.'||o.name details, 
    Nvl(s.Program, s.Module) What 
from v$session s, v$lock l, sys.obj$ o, all_users u 
where s.username like nvl(upper('&user'||'%'),'%') 
and s.sid = l.sid 
and l.id1 = o.obj# 
--and l.type = 'TM' 
and o.owner# = u.user_id(+) 
union all 
select SubStr('alter system kill session ''' || s.sid || ',' || s.serial# || ''';', 1, 40) as kill, s.username uname, 
    decode (l.type,'TX','TX', 
       'UL','USR', 
         'SYS') ltype, 
    decode (l.lmode,1,'Null', 
        2,'Row-S', 
        3,'Row-X', 
        4,'Share', 
        5,'S/Row-X', 
        6,'Exclusive') lmode, 
    decode (l.request,0,'No','Yes') blocked, 
    decode (l.request,0,null,'Waiting on session '||to_char(b.sid)) details, 
    Nvl(s.Program, s.Module) What 
from v$session s, v$lock l, v$lock b 
where s.username like nvl(upper('&user'||'%'),'%') 
and s.sid = l.sid 
and l.type != 'TM' 
and l.id1 = b.id1(+) 
and b.request(+) = 0 
order by 5 desc,3 desc,2,1; 
set verify on 
REM End of file 
+0

謝謝你的回答。在電話掛斷時看着oracle web gui,我看到有兩個相同的查詢互相阻塞。我還應該提到,只有當jboss在Unix下運行時纔會發生這種情況,而在Windows上運行正常。我嘗試使用最新的驅動程序11.2.0.2.0,但沒有改變。 – ttr13p 2011-05-17 09:12:43

+0

另外我正在使用oracle.jdbc.xa.client.OracleXADataSource – ttr13p 2011-05-17 09:35:27

0

酷。我轉載了這個設置(但沒有被凍結),所以這仍然是一個正在進行的工作。

我相當確定該問題與Java中的XA事務有關,因爲這是執行Java存儲過程和SQLDeveloper之間的顯着區別。由於通話凍結(無限期?),您是否可以重新生成JMXConsole,並從jboss.system中滑出一個線程轉儲:type = ServerInfo MBean?查看完整的堆棧跟蹤將更好地瞭解線程正在等待什麼。

==== ====編

是否有任何編譯指示,DDL或影響該存儲過程或任何其依賴條款的任何其他交易?

==== ====更新

線程可運行,所以我們知道客戶只是在等待來自服務器的響應。我想到DDL可能會影響事務,但是根據您的僞代碼,臨時表都是使用WITH語句隱式創建的,我通過驗證不會觸發提交。你能否確認沒有CREATE TEMPORARY TABLE陳述?

+0

謝謝尼古拉斯。這裏是線程轉儲的特定線程堆棧跟蹤: – ttr13p 2011-05-27 09:52:36

+0

線程:....優先級:5,demon:true,threadId:121,threadState:RUNNABLE java.net.SocketInputStream.socketRead0(本地方法) java.net。 SocketInputStream.read(SocketInputStream.java:129) oracle.net.ns.Packet.receive(Packet.java:240) oracle.net.ns.DataPacket.receive(DataPacket.java:92) oracle.net.ns .NetInputStream.getNextPacket(NetInputStream.java:172) oracle.net.ns.NetInputStream.read(NetInputStream.java:117) oracle.net.ns.NetInputStream.read(NetInputStream.java:92) oracle.net。 (NetInputStream.java:77)oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1034) – ttr13p 2011-05-27 09:54:52

+0

oracle.jdbc.driver.T4CMARE ngine.unmarshalSB1(T4CMAREngine.java:1010) oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:588) oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:191) oracle.jdbc.driver .T4CCallableStatement.executeForRows(T4CCallableStatement.java:950) oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1222) oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387) oracle.jdbc。 driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3488) – ttr13p 2011-05-27 09:56:03