2012-12-14 63 views
3

將ARRAY發送到stord proc時,我們得到java級別的死鎖。我正在附加線程轉儲。將ARRAY傳遞給存儲過程時發生死鎖

Found one Java-level deadlock: 
    ============================= 
    "http-bio-8080-exec-11": 
     waiting to lock monitor 0x00000000406fb2d8 (object 0x00000000fea1b130, a oracle.jdbc.driver.T4CConnection), 
     which is held by "http-bio-8080-exec-4" 
    "http-bio-8080-exec-4": 
     waiting to lock monitor 0x00000000407d6038 (object 0x00000000fe78b680, a oracle.jdbc.driver.T4CConnection), 
     which is held by "http-bio-8080-exec-11" 

    Java stack information for the threads listed above: 
    =================================================== 
    "http-bio-8080-exec-11": 
     at oracle.sql.TypeDescriptor.getName(TypeDescriptor.java:682) 
     - waiting to lock <0x00000000fea1b130> (a oracle.jdbc.driver.T4CConnection) 
     at oracle.jdbc.oracore.OracleTypeCOLLECTION.isInHierarchyOf(OracleTypeCOLLECTION.java:149) 
     at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2063) 
     at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3579) 
     at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3685) 
     - locked <0x00000000fe78b680> (a oracle.jdbc.driver.T4CConnection) 
     at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4714) 
     - locked <0x00000000fe78b680> (a oracle.jdbc.driver.T4CConnection) 
     at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1376) 
     at org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1066) 
     at org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1) 
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1014) 
     at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1064) 
     at org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:144) 

如何避免這些類型的死鎖。

代碼: 類擴展org.springframework.jdbc.object.StoredProcedure

Map result; 
       Map hashMap = new HashMap(); 
       hashMap.put(SOME_IDS_PARAM, getJdbcTemplate().execute(new ConnectionCallback() { 
        @Override 
        public Object doInConnection(Connection con) 
          throws SQLException, DataAccessException { 
         Connection connection = new SimpleNativeJdbcExtractor().getNativeConnection(con); 
         ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor(schema + ".ARRAY_OF_NUMBER" , connection); 
         return new oracle.sql.ARRAY(descriptor, connection, someIds); 
        } 
       })); 
       result = super.execute(hashMap); 

即使我試圖用這種方法:

OracleConnection connection = null; 
    DataSource datasource = null; 
    Map result; 
    try { 
     datasource = getJdbcTemplate().getDataSource(); 
     connection = (OracleConnection) DataSourceUtils.getConnection(datasource); 
     synchronized (connection) { 
      Map hashMap = new HashMap(); 
      hashMap.put(SOME_IDS_PARAM, getArrayOfNumberValue(someIds, schema, connection)); 
      result = super.execute(hashMap); 
     } 
    } finally { 
     if (null != connection) { 
      DataSourceUtils.releaseConnection(connection, datasource); 
     } 
    } 

陣:

public ARRAY getArrayOfNumberValue(Integer[] array, String schema, OracleConnection connection) throws DataAccessResourceFailureException { 
     String arrayOfNumberTypeName = schema + ARRAY_OF_NUMBER; 
     ARRAY oracleArray = null; 
     ArrayDescriptor descriptor = null; 
     try { 

      descriptor = (ArrayDescriptor) connection.getDescriptor(arrayOfNumberTypeName); 
      if (null == descriptor) { 
       descriptor = new ArrayDescriptor(arrayOfNumberTypeName, connection); 
       connection.putDescriptor(arrayOfNumberTypeName, descriptor); 
      } 
      oracleArray = new ARRAY(descriptor, connection, array); 

     } catch (SQLException ex) { 
      throw new DataAccessResourceFailureException("SQLException " + "encountered while attempting to retrieve Oracle ARRAY", ex); 
     } 

     return oracleArray; 
    } 

我懷疑,當我檢查了連接從「connection =(OracleConnection)DataSourceUtils.ge tConnection(數據源);」。它會給你邏輯上的連接,但是它會利用「T4Connection」,但它會釋放它。並再次尋找相同的連接。

java.lang.Thread.State: BLOCKED (on object monitor) 
    at oracle.sql.TypeDescriptor.getName(TypeDescriptor.java:682) 
    - waiting to lock <0x00000000c1356fc8> (a oracle.jdbc.driver.T4CConnection) 
    at oracle.jdbc.oracore.OracleTypeCOLLECTION.isInHierarchyOf(OracleTypeCOLLECTION.java:149) 
    at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2063) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3579) 
    at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3685) 
    - locked <0x00000000c14b34f0> (a oracle.jdbc.driver.T4CConnection) 
    at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:4714) 
    - locked <0x00000000c14b34f0> (a oracle.jdbc.driver.T4CConnection) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1376) 
    at org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1066) 
    at org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1014) 
    at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1064) 
    at org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:144) 
    at com.intuit.platform.integration.sdx.da.procedures.subscription.serviceSubscription.LookupRealmSubscriptions.execute(LookupRealmSubscriptions.java:55) 
    - locked <0x00000000fbd00bc0> (a oracle.jdbc.driver.LogicalConnection) 
    at com.intuit.platform.integration.sdx.da.ServiceSubscriptionDAOImpl.getRealmServiceSubscriptions(ServiceSubscriptionDAOImpl.java:153) 
    at com.intuit.platform.integration.sdx.ws.beans.ServiceSubscriptionResourceBean.filterRealmIds(ServiceSubscriptionResourceBean.java:84) 
+0

你是否在多個線程之間共享單個連接?如果是這樣,我建議每個線程連接。 – jtahlborn

+0

你爲什麼喊陣列? –

+0

你可以發佈正在做的代碼:1)創建/填充數組,2)撥打電話?謝謝 –

回答

1

ARRAY中的連接與正在執行存儲過程的連接不同。你可以看到這個,因爲正在等待一個鎖定(第3行堆棧跟蹤)的T4CConnection與先前鎖定的IF具有不同的IF。

使用How to get current Connection object in Spring JDBC中的答案獲取當前連接,然後使用https://stackoverflow.com/a/7879073/1395668向下轉換爲Oracle連接。然後,您應該能夠創建適用於當前連接的ARRAY,並且不應該發生死鎖。

+0

如果我們想傳遞數組到存儲過程。我們需要構建sql ARRAY對象。爲了構建相同的結構,我們需要傳遞連接。 –

+0

是的,你是對的。爲什麼它發生這樣的事情。這是oracle驅動程序的問題嗎? –

+0

太好了 - 明白你現在在做什麼,所以我已經更正了答案,並且(希望)提供了你需要的答案。 –