Как получить блокировку в DB2 с выбором для обновления без передачи данных? - PullRequest
0 голосов
/ 08 мая 2020

Путем множества экспериментов я обнаружил, что

(jdbcTemplate - это JdbcTemplate и используется только для упрощения выполнения запросов. У него нет реального отношение к вопросу)

jdbcTemplate.query(
    "select 0 from example where id = 23 for update with rs use and keep update locks", 
    rs -> {
        rs.next();
        return null;
});

получает блокировку выбранной строки, а эта - нет:

jdbcTemplate.query(
    "select 0 from example where id = 23 for update with rs use and keep update locks", 
    rs -> {
        return null;
});

Я предполагаю, по той же причине, что следующее не получить блокировку:

jdbcTemplate.execute(
    "select id from example where id = 23 for update with rs use and keep update locks"
);

У меня вопрос из двух частей:

  1. Что, черт возьми, происходит?
  2. Как я могу выполнить выбор для обновить в базе данных, чтобы она приводила к блокировке, но не возвращала данные для выбранной строки? Может быть, какой-то скрипт?

Есть репозиторий Github, тестирующий эти (и многие другие варианты) .

1 Ответ

1 голос
/ 11 мая 2020

Цитата из документации по Стабильность чтения (RS) Уровень изоляции:

Уровень изоляции стабильности чтения блокирует только те строки, которые приложение извлекает за единицу работы.

-- Rows are locked / accessed during "fetch"
select * from example where id = 23 with rs use and keep update locks;

-- Rows must be accessed either during "execute" / "open" or "fetch" to get the corresponding result
select count(1) from example where id = 23 with rs use and keep update locks;

Основное требование для достижения RS другими словами: если некоторая строка участвовала в результате 1-го вызова этого оператора, то она должны участвовать в результатах каждого последующего вызова того же оператора с теми же значениями.

Когда вы просто выбираете строки, они извлекаются (доступны) только в течение fetch. Они не будут доступны, пока вы их не загрузите. Для достижения логической цели, описанной выше, нет необходимости заранее блокировать эти строки. Зачем уменьшать параллелизм в системе, если вы можете «лениво» получать / блокировать необходимые строки?

Но когда вы производите агрегацию необходимых строк, к ним должен быть доступ либо во время execute / open, либо во время 1-го fetch (и единственного fetch, поскольку это агрегация ), чтобы заблокировать соответствующие строки. Я считаю, что такое поведение не задокументировано - это только текущее наблюдаемое поведение.

Я бы посоветовал вам сделать 1 fetch в операторе агрегирования в любом случае, чтобы быть в безопасности. Никто не может гарантировать (кроме случаев, когда вы обратитесь в службу поддержки IBM по этому поводу и получите соответствующее разъяснение), что такое поведение может не измениться в будущем.

...