2015-03-04 4 views
3

У меня проблема, и я подумываю об использовании метода изоляции базы данных == Сериализуемый для этой ситуации, но после прочтения кучки статей я все еще не уверен, что это решение для моего проблема ниже.Проблема параллелизма в заявлении о выборе базы данных

Настройка:

Weblogic cluster > 2 servers 
Simple Java JDBC 
Servlets, EJB Session beans 2.0 

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

LAN

lan_id | name | some_values | is_available 
------------------------------------- 
13  | ss | 3234  | yes 
12  | sssd| 3234  | yes 
14  | sssd| 3234  | yes 
15  | ssaa| 3234  | yes 

В настоящее время в бизнес-логике, мне нужно выбрать соответствующий ряд из локальной сети и сохранить еще одну таблицу LAN_Assignment

LAN_Assignment

lan_id | lan_assg_id | some other columns 
------------------------------------------- 

Когда запустив оператор select, я получаю соответствующую строку из таблицы LAN и назначьте его таблице lan_assignment.

Теперь Если из клиента поступило 5 запросов (может быть любой сервер в кластере), все они выбирают первую доступную локальную сеть и сохраняют ее в другой таблице.

Как я могу убедиться, что первый запрос, который взял LAN, не выбран вторым запросом от клиента?

PS: заявления выбора и бизнес-логика не так прямолинейны, как описано здесь. Есть много условий, чтобы выбрать LAN и сохранить его Lan_assignment и т.д.,

спасибо

+0

Не может ли одна функция атомной выборки и блокировки (как в хранимой процедуре) гарантировать, что этого не произойдет? –

+0

Запустите SQL-запросы в транзакции * и * заблокируйте выбранную строку для обновления, чтобы другие запросы не продвигались до тех пор, пока они не получат блокировку, если они закончат выбор одной и той же строки - убедитесь, что ваша логика работает как можно быстрее не ухудшать производительность. – watery

+0

Какая база данных вы используете и версию? –

ответ

1

Oracle 10g имеет недокументированный SKIP LOCKED, доступный для обновления, я использую его как решение (см. Вариант 3 ниже).

Как бы я ни прошел другие варианты обработки этого сценария.

Option 1: Этот параметр будет просто блокировать строки до завершения транзакции. Все остальные транзакции будут продолжать ждать, когда блокировка будет выпущена первой транзакцией. Это немного рискованно, так как транзакции могут оставаться в ожидании очень долгого времени и могут привести к тупиковой ситуации.

select .. where .. for update 

Option 2: (NOWAIT) Это не будет ждать, если строки будут заблокированы какой-то другой сделки. Он вернет ошибку оракула. Я могу поймать исключение, подождите 10 секунд и попробуйте еще 4-5 попыток, прежде чем показывать ошибку пользователю.

select .. where... for update nowait 

Вариант 3: (пропуск заблокирован), это будет пропускать строки, которые фиксируются с помощью других сделок, служит цели, для меня, как я не хочу, чтобы использовать те, которые заблокированы другими транзакциями.

select...where ... for update skip locked 
1

сериализуемая изоляция не является решение вашей проблемы (но, пожалуйста, оставьте его там!)

You имеют несколько альтернатив для обработки этих 5 одновременных запросов (согласно вашему сценарию). Один из них - провалить 4 из этих транзакций, и только 1 удастся. Вы можете сделать это с помощью уникальных ограничений или с помощью оптимистической блокировки и повторных операций, которые не выполняются из-за этого (но не забудьте после нескольких попыток).

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

+0

Не могли бы вы немного рассказать о строках? – Zeus

2

Вы можете использовать SKIP LOCKED для своей цели. С этим, когда сеанс 1 блокирует строку, сеанс 2 может пропустить его и обработать следующий. Я считаю, что он был там и в 10g, но никогда не документирован.

+0

Конечно, посмотрим. – Zeus

Смежные вопросы