java - 将 ARRAY 传递给存储过程时发生死锁

标签 java database oracle stored-procedures ojdbc

在将 ARRAY 发送到 stord proc 时,我们遇到了 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)

最佳答案

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

使用 How to get current Connection object in Spring JDBC 中的答案获取当前连接,然后使用 https://stackoverflow.com/a/7879073/1395668 将其向下转换为 Oracle 连接.然后,您应该能够创建对当前连接有效的 ARRAY,并且不会出现死锁。

关于java - 将 ARRAY 传递给存储过程时发生死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13872561/

相关文章:

java - 多个复选框选中值

java - 从jsp调用方法并使用它

database - 数据库术语之间的差异

oracle - 如何导出/导入完整的 OracleDB 数据转储?

mysql - oracle表间关系的不同实现方式

java - 堆栈中的内存分配和局部变量的删除

java - 为我的游戏在 java 方法中运行一个方法?

asp.net - 网络应用程序的照片存储

php - 您可以用 case 指定要在 MySQL 中使用的连接吗?

JavaPreparedStatement设置NULL参数