将ARRAY传递给存储过程时出现死锁

时间:2012-12-14 04:16:35

标签: java database oracle stored-procedures ojdbc

在向stord proc发送ARRAY时,我们正在获得java级死锁。我正在附加线程转储。

    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.getConnection(datasource);”中检出连接时。它将为您提供逻辑连接但底层它将使用“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)

1 个答案:

答案 0 :(得分:1)

ARRAY中的连接与正在执行存储过程的连接不同。您可以看到这一点,因为等待锁定的T4CConnection(堆栈跟踪的第3行)与先前锁定的IF具有不同的IF。

使用How to get current Connection object in Spring JDBC中的答案获取当前连接,然后使用https://stackoverflow.com/a/7879073/1395668将其转发到Oracle连接。然后,您应该能够为当前连接创建有效的ARRAY,并且您不应该陷入僵局。