Взаимоблокировки при передаче ARRAY в хранимую процедуру

При отправке 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 (источник данных);». Это даст вам логическое соединение, но в его основе будет использоваться «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)

person shiva.n404    schedule 14.12.2012    source источник
comment
вы разделяете одно соединение между несколькими потоками? если это так, я бы порекомендовал соединение для каждого потока.   -  person jtahlborn    schedule 14.12.2012
comment
Почему ты кричишь массив?   -  person Steve Kuo    schedule 14.12.2012
comment
Можете ли вы опубликовать код, который выполняет 1) создание/заполнение массива и 2) выполнение вызова? Спасибо   -  person Andrew Alcock    schedule 14.12.2012
comment
Какую версию драйвера оракула вы используете? Мы наблюдаем подобное поведение с 11.2.0.3.   -  person BillMan    schedule 08.03.2013


Ответы (1)


Соединение в МАССИВЕ не совпадает с соединением, в котором выполняется хранимая процедура. Вы можете видеть это, потому что T4CConnection, ожидающий блокировки (строка 3 трассировки стека), имеет другой IF, чем тот, который был заблокирован ранее.

Используйте ответ в Как получить текущий объект Connection в Spring JDBC чтобы получить текущее соединение, а затем понизить его до соединения Oracle, используя https://stackoverflow.com/a/7879073/1395668< /а>. Затем вы сможете создать МАССИВ, действительный для вашего текущего соединения, и вы не должны получить тупик.

person Andrew Alcock    schedule 14.12.2012
comment
Если мы хотим передать массив хранимой процедуре. Нам нужно построить объект sql ARRAY. Чтобы построить то же самое, нам нужно передать соединение. - person shiva.n404; 14.12.2012
comment
да ты прав. Почему так происходит. Это проблема с драйвером оракула? - person shiva.n404; 14.12.2012
comment
Отлично - понимаете, что вы сейчас делаете, поэтому я исправил ответ и (надеюсь) предоставил нужный вам ответ. - person Andrew Alcock; 14.12.2012
comment
Спасибо, Эндрю. Я попробовал предложенный вами подход, но все равно не сработало. - person shiva.n404; 14.12.2012
comment
Каким образом это не работает? Тот же тупик, что и раньше (в этом случае соединение неправильное) или по-другому? - person Andrew Alcock; 14.12.2012
comment
в обе стороны :( ..опять тупиковые замки - person shiva.n404; 14.12.2012
comment
Можете ли вы проверить свою новую трассировку стека взаимоблокировок. Возникла ли тупиковая ситуация снова на других соединениях T4CConnections? Если да, то каким-то образом ваша StoredProcedure все еще передает неправильное соединение с getArrayOfNumberValue(). Вам нужно будет отладить, почему соединение отличается - я в недоумении. - person Andrew Alcock; 16.12.2012
comment
Я подозреваю, что когда я проверяю соединение из connection = (OracleConnection) DataSourceUtils.getConnection(datasource);. Это даст вам логическое соединение, но в его основе будет использоваться T4Connection, но он его освобождает. - person shiva.n404; 17.12.2012