Изоляция транзакций ANSI REPEATABLE_READ в DB2 не блокирует строки, как ожидалось

У меня возникла ситуация с уровнями изоляции DB2, которую я не могу объяснить.

У меня есть транзакция с уровнем изоляции REPEATABLE_READ, который в DB2 соответствует READ_STABILITY.

У меня есть базовые знания о S-, U- и X-блокировках DB2.

Когда я параллельно выполняю следующую транзакцию Spring, я могу вызвать взаимоблокировку (ошибка DB2 — FILE IN USE):

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public long getNext(int x) {
    final Stuff stuff = entityManager
            .createQuery("from Stuff where type = :type", Stuff.class)
            .setParameter("cardType", cardType)
            .getSingleResult();

    stuff.setData(stuff.getData() + x);
    return stuff.getData()+1;
}

Я ожидаю, что изоляция REPEATABLE_READ установит U-блокировку DB2 для возвращаемой строки, поэтому параллельная транзакция будет поставлена ​​в очередь.

Вместо этого, чтобы заставить его работать, мне нужно добавить пессимистическую блокировку записи:

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public long getNext(int x) {
    final Stuff stuff = entityManager
            .createQuery("from Stuff where type = :type", Stuff.class)
            .setParameter("cardType", cardType)
            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
            .getSingleResult();


    stuff.setData(stuff.getData() + x);
    return stuff.getData()+1;
}

Вышеупомянутый запрос генерирует правильный блокирующий SQL, и транзакции работают без взаимоблокировок:

select * from .... for update with rs;

Вопрос в том, зачем использовать REPEATABLE_READ, когда мне все еще нужно делать ручную блокировку? Насколько я понимаю, REPEATABLE_READ должен самостоятельно обрабатывать необходимую блокировку строк, чтобы обеспечить повторяемость чтения.


person Daniel    schedule 15.06.2018    source источник
comment
Какая у вас операционная система на сервере Db2? (Z/OS, i-series, Linux/Unix/Windows) и версию вашего Db2-сервера?   -  person mao    schedule 15.06.2018
comment
Это iSeries версии 7 Release2 (V7R2).   -  person Daniel    schedule 15.06.2018
comment
повторяемое чтение звучит так, будто никто не может изменить таблицу, пока вы ее читаете. Похоже, IBM тоже просто блокирует таблицу.   -  person danny117    schedule 15.06.2018


Ответы (1)


Db2 for i поддерживает повторяемое чтение (RR) и стабильность чтения (RS).

Повторяемое чтение

В стандарте SQL 2003 Core Repeatable Read называется Serializable.
Db2® for i поддерживает повторяющееся чтение через COMMIT(*RR). Уровень изоляции повторяющегося чтения поддерживается за счет блокировки таблиц, содержащих любые прочитанные или обновленные строки.

Repeatable Read — это самый высокий уровень изоляции.

Если вы просто хотите заблокировать строки, к которым вы прикасаетесь, я думаю, вам нужна стабильность чтения (RS). Что является шагом вниз. Разница в том, что RS допускает фантомное чтение

Фантом. Единица работы UW1 считывает набор из n строк, удовлетворяющих некоторому условию поиска. Затем единица работы UW2 вставляет одну или несколько строк, удовлетворяющих условию поиска. Затем UW1 повторяет начальное чтение с тем же условием поиска и получает исходные строки плюс вставленные строки.

person Charles    schedule 15.06.2018
comment
Я использую RS выше, как указано в аннотации, связанной с Spring, но запрос, похоже, фактически не блокирует строки, возвращаемые в первом операторе выбора. Вот почему я все еще получаю проблемы с взаимоблокировкой при одновременном выполнении транзакции. - person Daniel; 15.06.2018