2012-12-14 27 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

太好了 - 明白你现在在做什么,所以我已经更正了答案,并且(希望)提供了你需要的答案。 –