Блокировка транзакции JDBC: решение требуется? - PullRequest
3 голосов
/ 03 апреля 2010

Мой друг описал сценарий и предложил мне найти решение.Он использует базу данных Oracle и соединение JDBC с чтением, зафиксированным как уровень изоляции транзакции.В одной из транзакций он обновляет запись, выполняет оператор выбора и фиксирует транзакцию.Когда все происходит в одном потоке, все в порядке.Но когда обрабатывается несколько запросов, возникает тупик.

  1. Thread-A обновляет запись.
  2. Тема B обновляет другую запись.
  3. Thread-A выдает оператор выбора и ожидает транзакции Thread-B для завершения операции фиксации.
  4. Thread-B выдает оператор выбора и ожидает транзакции Thread-A для завершения операции фиксации.

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

Мой аргумент: Thread-A должен выбирать все записи, которые были зафиксированы и, следовательно, не должны выдаваться.Но он сказал, что Thread-A непременно подождет, пока Thread-B завершит запись.Это правда?

Какими способами можно избежать вышеуказанной проблемы?Можно ли изменить уровень изоляции (без изменения базового Java-фреймворка)?

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

Ответы [ 3 ]

4 голосов
/ 03 апреля 2010

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

Чтобы избежать этой проблемы, убедитесь, что вы выбираете обновление только в том случае, если оно действительно вам нужно, и в этом случае используйте опцию NOWAIT в списке выбора. Это приведет к возникновению ошибки, если операция заблокируется.

Oracle обнаружит взаимоблокировки и откатит одну из задействованных транзакций.

1 голос
/ 03 апреля 2010

С здесь

Oracle явно поддерживает READ СОВЕРШЕННАЯ и СЕРИАЛИЗИРУЕМАЯ изоляция уровни, как они определены в стандарт. Тем не менее, это не говорит вся история. Стандарт SQL был пытаясь установить уровни изоляции, которые позволит различные степени согласованность для запросов, выполняемых в каждый уровень. ПОВТОРЯЕМЫЙ ЧИТАТЬ уровень изоляции, что стандарт SQL претензии будут гарантировать непротиворечивый результат запроса. В определении стандарта SQL READ COMMITTED не дает вам последовательного результаты, и READ UNCOMMITTED является уровень, используемый для получения неблокирующих чтений.

Однако в Oracle Database READ COMMITTED имеет все атрибуты требуется для достижения последовательного чтения запросы. В других базах READ ЗАВЕРШЕННЫЕ запросы могут и будут возвращать ответы, которые никогда не существовали в база данных. Более того, база данных Oracle также поддерживает дух READ UNCOMMITTED. Цель предоставления грязное чтение, чтобы поставить неблокирующий читать, при этом запросы не блокируются и не блокировать обновления те же данные. Тем не менее, Oracle Database не нужно грязного чтения, чтобы достичь эта цель, и при этом это не поддерживает их. Грязные чтения являются реализацией другие базы данных должны использовать для обеспечения неблокирующие чтения.

READ COMMITTED. ЧИТАЙТЕ СОВЕРШЕНО уровень изоляции гласит, что транзакция может читать только данные, которые был зафиксирован в базе данных. Там нет грязных чтений (читает незафиксированные данные). Может быть неповторимые чтения (то есть перечитывает из той же строки может вернуть другой ответить в той же транзакции) и фантомное чтение (то есть вновь вставленный и зафиксированные строки становятся видимыми для запрос, который не был виден ранее в перевод). ЧИТАЙТЕ КОМИТЕТ пожалуй, наиболее часто используемый уровень изоляции в базе данных приложения везде, и это режим по умолчанию для базы данных Oracle. Это редко можно увидеть другую изоляцию уровень, используемый в базах данных Oracle.

В Oracle Database, используя мульти-версия и согласованность по чтению вопросы, ответ я получаю от Запрос СЧЕТА то же самое в READ СОВЕРШЕННЫЙ пример, как это было в ПРОЧИТАЙТЕ БЕЗУМНИТНЫЙ пример. оракул База данных реконструирует измененную данные, как это появилось, когда запрос начал, возвращая ответ, который был в базе данных, когда запрос начало.

0 голосов
/ 04 апреля 2010

Представленный сценарий не будет происходить в Oracle по той простой причине, что записи не блокируют чтения в этой базе данных.

Где мы можем получить тупик в этом сценарии:

  1. Сессия А обновляет запись, # 1234.
  2. Сессия B обновляет другую запись # 5678.
  3. Сессия А обновляет запись, # 5678.
  4. Сессия B обновляет запись # 1234.
  5. Сессия A выдает коммит.
  6. Сессия B выдает коммит.

Oracle обнаружит тупик и откатит одну из сессий. В традиционных клиент-серверных приложениях эту ситуацию избегают путем пессимистической блокировки (SELECT ... FOR UPDATE). В веб-приложениях эту ситуацию можно избежать, используя «столбец оптимистической блокировки», который фактически не является формой блокировки вообще (именно поэтому он избегает взаимных блокировок, хотя и за счет большого количества дополнительных операций чтения).

...