Значения результирующего набора обновляются в другой транзакции - PullRequest
0 голосов
/ 06 апреля 2020

Я наблюдал странное поведение с SQL Сервером и JDB C - связанное с большими отдельными запросами и пакетными обновлениями.

То, что у нас есть, не очень большое (около 2 миллионов строк) ) таблица, которая состоит из большого количества хранимых чисел nvarchar. В этом столбце есть некластеризованный индекс. Я выбираю все отличительные значения и выполняю обновления этих значений в пакетных пакетах.

Однако иногда кажется, что обновленные значения отражаются в возвращаемом наборе результатов.

Пример кода:

    config.setMaximumPoolSize(3);
    config.setAutoCommit(false);
    final HikariDataSource hikariDataSource = new HikariDataSource(config);
    final Connection selectConn = hikariDataSource.getConnection();
    final PreparedStatement selectStmt = selectConn.prepareStatement("SELECT DISTINCT A FROM EXAMPLE_TABLE WHERE A IS NOT NULL", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    final ResultSet resultSet = selectStmt.executeQuery();
    do {
        List<String> valuesToUpdate = new ArrayList<>();
        for (int i = 0; i < 10000 && resultSet.next(); i++) {
            final String valueToUpdate = resultSet.getString(1);
            valuesToUpdate.add(valueToUpdate);
            if (valueToUpdate.equals("31081273963")) {
                throw new IllegalArgumentException("This should be never thrown.");
            }
        }

        if (valuesToUpdate.isEmpty()) {
            return;
        }
        Connection updateConn = hikariDataSource.getConnection();
        final PreparedStatement batchStatement = updateConn.prepareStatement("UPDATE EXAMPLE_TABLE SET A = '31081273963' WHERE A = ?");
        for (String str: valuesToUpdate) {
            batchStatement.setObject(1, str);
            batchStatement.addBatch();
        }
        batchStatement.executeBatch();
        updateConn.commit();
        updateConn.close();
    } while (true);

В вышеприведенном примере "31081273963" гарантированно не находится в базе данных до выполнения кода на 100%. Я устанавливаю все полученные значения в это значение "31081273963". Но иногда я сталкиваюсь с этим if (valueToUpdate.equals("31081273963")) условием.

Самым странным является то, что я могу получить это исключение с примером значения «31081273963», который находится в середине упорядоченного запроса (когда он будет в таблица), но когда я выбираю значение ближе к началу, не исключение. (Конечно, я не говорю, что это значение «специальное», но я имею в виду, что мне нужно выбрать значение, которое не находится в начале набора результатов, чтобы вызвать это исключение.

Является ли это поведение в некоторой степени задокументированным или зависит от какого-то параметра? * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1019*. (Реальная проблема XY - сделать resultSet нетронутым для полной прокрутки, с обновлениями в фоновом режиме, но без блокировки таблицы - но мне просто любопытно, почему и когда эта проблема возникает.)

...