Вопрос параллелизма / синхронизации - PullRequest
1 голос
/ 27 ноября 2009

У меня 2 программы, запущенные на 2 разных машинах.
В каждой программе есть метод updateRecord, который выполняет следующие 2 вещи:
1. Сделайте запрос SELECT для конкретной записи Z
2. Выполните запрос UPDATE для той же записи.

Если эти 2 запроса находятся в одной транзакции (между beginTransaction и commitTransaction), это гарантирует правильное выполнение?

Т.е. следующая последовательность операций не сможет успешно выполнить?

  1. Prog-1 SELECT
  2. Prog-2 SELECT
  3. ОБНОВЛЕНИЕ Prog-1
  4. ОБНОВЛЕНИЕ Prog-2

OR

  1. Prog-1 SELECT
  2. ОБНОВЛЕНИЕ Prog-1
  3. Prog-1 SELECT
  4. ПРОГ-2 ОБНОВЛЕНИЕ
  5. Prog-1 COMMIT
  6. Prog-2 COMMIT

Ответы [ 3 ]

3 голосов
/ 27 ноября 2009

Ваша программа должна заблокировать запись, когда она ее выбирает - например, используйте синтаксис SELECT FOR UPDATE. Таким образом, запись будет заблокирована, пока не будет выполнено ОБНОВЛЕНИЕ.

2 голосов
/ 27 ноября 2009

Как уже отмечалось, использование SELECT ... FOR UPDATE помогает, так как блокирует строку, пока транзакция не будет зафиксирована (или откатана).

Вам не нужны две машины, чтобы проверить это. Используя два разных сеанса (например, запустив два разных экземпляра SQL * Plus) и выполняя ваши запросы одновременно в определенном порядке в обоих сеансах, вы сможете воспроизвести проблему (ы) параллелизма, если они есть.

В этом случае вы можете запустить:

Session1: SELECT z AS sel_z -- sel_z = 0
Session1: UPDATE z = sel_z + 1
Session2: SELECT z AS sel_z -- (1) sel_z = 0 because Session1 is uncommitted
Session2: UPDATE z = sel_z + 1
Session1: COMMIT
Session2: COMMIT
Session1: SELECT z AS sel_z -- sel_z = 1
Session2: SELECT z AS sel_z -- sel_z = 1

Проблема в (1), Session2 не видит значения, измененные Session1, потому что они не зафиксированы.

Мое предложение - не думать об изменении уровня изоляции TX, а думать о блокировке надлежащих ресурсов.

1 голос
/ 27 ноября 2009

Две машины никогда не будут использовать одну и ту же транзакцию. Если SELECT & UPDATE выполняются в рамках хранимой процедуры, они будут в одной транзакции. Если запросы SELECT & UPDATE выполняются как отдельные операторы, возможно следующее:

  1. Prog-1 SELECT
  2. Prog-2 SELECT
  3. ОБНОВЛЕНИЕ Prog-1
  4. ОБНОВЛЕНИЕ Prog-2

В зависимости от уровня изоляции базы данных, выбор машины № 2 может просматривать данные перед запуском ОБНОВЛЕНИЯ для машины № 1. IIRC, это было бы по умолчанию в Oracle.

Вот 411 на уровнях изоляции Oracle, согласно AskTom .

Для MySQL используйте команду SET TRANSACTION. Для получения дополнительной информации о поддержке уровня изоляции MySQL см. эту ссылку .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...