Возможно, это тривиальный вопрос, но я хочу найти наилучшее из возможных решений.
Проблема:
У меня есть два или более рабочих, которые вставляют ключи в одну или несколько таблиц. Проблема возникает, когда два или более рабочих пытаются вставить один и тот же ключ в одну из этих таблиц ключей одновременно.
Типичная проблема.
- Рабочий A читает таблицу, если ключ существует (SELECT). Там нет ключа.
- Рабочий B читает таблицу, если ключ существует (SELECT). Там нет ключа.
- Рабочий А вставляет ключ.
- Рабочий B вставляет ключ.
- Работник А совершает.
- Работник Б фиксирует. Исключение составляют броски, так как уникальное ограничение нарушено
Таблицы ключей - это простые пары. Первый столбец представляет собой целое число автоинкремента, а второй - ключ varchar.
Как лучше всего решить проблему параллелизма? Я считаю, что это общая проблема. Одним из способов наверняка является обработка исключений, но почему-то я не верю, что это лучший способ решить эту проблему.
База данных, которую я использую, если Firebird 2.5
EDIT
Некоторая дополнительная информация, чтобы прояснить ситуацию.
- Синхронизация на стороне клиента не является хорошим подходом, потому что вставки происходят из разных процессов (рабочих). И когда-нибудь у меня будут рабочие на разных машинах, так что даже мьютексы не нужны.
- Первичным ключом и первыми столбцами такой таблицы является поле автоинкремента. Нет проблем там. Проблема заключается в поле varchar, так как оно вставляется клиентом.
Типичной такой таблицей является таблица пользователей. Например:
1 2056
2 1044
3 1896
4 5966
...
Каждый работник проверяет, существует ли пользователь "xxxx" и, если нет, вставляет его.
РЕДАКТИРОВАТЬ 2 :
Просто для справки, если кто-то пойдет по тому же маршруту. IB / FB возвращает пару кодов ошибок (я использую компоненты InterBase Express). Проверка на наличие дублирующихся значений выглядит следующим образом:
except
on E: EIBInterBaseError do
begin
if (E.SQLCode = -803) and (E.IBErrorCode = 335544349) then
begin
FKeysConnection.IBT.Rollback;
EnteredKeys := False;
end;
end;
end;