2014-06-08 2 views
3

У нас есть транзакция, которая модифицирует запись. Транзакция должна вызывать веб-службу, откатывая транзакцию, если служба завершается с ошибкой (поэтому она не может передать ее в руки). Поскольку запись изменена, клиентское приложение имеет блокировку. Тем не менее, веб-служба должна получить эту запись, чтобы получить информацию от нее как часть ее обработки. Бам, тупик.DB2 Чтение выполнено без блокировки?

Мы используем websphere, которая по причинам, которые пугают мой разум, по умолчанию имеет повторяемый уровень изоляции чтения. Мы сбили его до read_committed, думая, что это будет извлекать строку без поиска блокировки. В нашей среде разработчиков, похоже, это сработало, но при постановке мы получаем взаимоблокировки.

Я не спрашиваю, почему это ведет себя по-другому, мы, вероятно, где-то совершили ошибку. Я также не спрашиваю о специфике примера веб-службы выше, потому что, очевидно, это то же самое может произойти в другом месте.

Но, основываясь на чтении документов, кажется, что read_committed DOES получает общую блокировку во время чтения, и в результате будет ждать эксклюзивной блокировки, удерживаемой другой транзакцией (в данном случае клиентским приложением). Но я не хочу идти на уровень read_uncommitted изоляции, потому что я не хочу, чтобы грязные чтения. Существует ли менее экстремальное решение? Мне нужна промежуточная площадка, где я могу выполнять чтение без ожидания блокировки и извлекать только зафиксированные данные.

Есть ли такое решение? Не слишком тупик, не слишком грязный-читал-у? Если не на уровне siolation, может быть, какой-то модификатор я могу применить к моему SQL? Что-нибудь?

+0

Точка блокировки, чтобы предотвратить что-то другое от изменения строки, не так ли? Не так, чтобы вы могли обновить его позже?Или можно ли разрешить другим процессам обновлять строку, ваш процесс просто должен обработать это потом? Можете ли вы назвать веб-сервис «локально»? Я знаю, что db2 поддерживает совместное использование блокировок для одного и того же сеанса, но это, вероятно, не происходит, если вы сначала отправляете off-box. Каков уровень блокировки другого веб-сервиса? –

+0

@ Clockwork-Muse - Нет, клиент действительно блокируется при подготовке к обновлению. Webservice реализует специальную схему уведомлений рабочего процесса, которая должна запрашивать соответствующую запись для создания уведомления (хотя она считывает разные поля, чем обновляется, что ничего не меняет). Веб-сервис и клиент в настоящее время работают с прочитанными. Я боюсь, что самое простое исправление (поддерживаемое нашим руководством по DB) заключается в том, чтобы перейти на чтение uncommitted для службы, но я пытаюсь найти альтернативный b/c, я ненавижу этот ответ. – user1187719

+0

Вам все равно, если кто-нибудь еще обновляет строку тем временем? Значения, которые вы могли бы обновить после разницы, независимо от того, какие другие манипуляции произошли? Или просто не волнует, если кто-то еще обновил записи за это время и перезаписал изменения? Вы уверены, что не можете запустить это в том же поле, что и сервис, возможно, чтобы он был частью одного сеанса? –

ответ

1

Я полагаю, вы говорите JDBC уровни изоляции, а не db2. Разница между read_committed (стабильность курсора в db2) и repeatable_read (стабильность чтения) заключается в том, как долго сохраняются блокировки доступа. repeatable_read сохраняет каждую блокировку, которая удовлетворяет предикатам, read_committed, с другой стороны, сохраняет блокировку только до тех пор, пока не будет найдена другая строка, соответствующая предикату.

Вы сравнили планы? Если планы разные, вы можете столкнуться с другим поведением.

Возникли ли какие-либо эскалации?

Вы пробовали CURRENTLY_COMMITTED (при условии, что вы на 9.7+)?

Pre currently_committed там, где следующие параметры, DB2_SKIPINSERTED, DB2_EVALUNCOMMITTED и DB2_SKIPDELETED

+0

Нет, этот тупик не основан на эскалации, хотя у нас были те, что были в прошлом. Я никогда не слышал о CURRENTLY_COMMITTED. Я пойду прочитаю об этом. – user1187719

+0

Я прочитал об этом, и это ТОЧНО, что мы хотим. Cur_commit - это зона золотых зазоров, которая не является взаимоблокировкой, а не грязным чтением. К сожалению, мы находимся на версии 9.5, но у нас уже есть усилия по конверсии для развертывания версии 10.5, поэтому нам остается только немного подождать. Благодарю. – user1187719

0

Самый низкий уровень изоляции, который считывает зафиксированные строки, считается прочитанным.

Обычно вы обрабатываете строки в базе данных DB2 так:

  1. Строка база данных Чтение без каких-либо блокировок чтения (обычной ВЫБРАТЬ с чтением, совершенным).
  2. Данные процесса, поэтому у вас есть строка с измененными значениями.
  3. Снова прочитайте строку базы данных с блокировкой чтения. (SELECT for UPDATE)
  4. Проверьте, чтобы строка базы данных в 1. соответствует строке базы данных в 3.
  5. Если строки соответствуют, обновите строку базы данных.
  6. Если строки не совпадают, отпустить блокировку обновления и вернуться к 2.
+0

Кроме того, я думаю, что OP хочет предотвратить любые изменения в строке во время обработки. Это позволит сообщать, но не будет препятствовать изменениям. –

+0

@GilbertLeBlanc Я думаю, вы неправильно поняли вопрос. Проблема в том, что операция чтения при чтении зафиксировала, что DOES блокирует запись, хотя и ненадолго и не исключительно. Но поскольку он хочет получить блокировку, если другая транзакция заблокирована, чтение будет WAIT вместо завершения. Обычно это не очень важно, но в сценариях, описанных в моем первом абзаце, это создает взаимоблокировки. B/c служба и клиент находятся на разных соединениях, хотя они работают вместе. – user1187719