436 Часть II. Типовые решения
другим. В этом случае бизнес-транзакция должна осуществить откат системной транзак-
ции, чтобы аннулировать все изменения, выполненные в ходе последней, а затем ава-
рийно завершить выполнение или же попытаться разрешить конфликт и произвести об-
новление еще раз (рис. 16.1).
Для разрешения конфликтов, возникающих при параллельной обработке данных,
удобно сохранять не только номер версии, но и сведения о том, кто провел последнее об-
новление записи. При выдаче уведомления об ошибке, связанной с наличием параллель-
ных сеансов, хорошее приложение всегда сообщит пользователю, кем и когда было вы-
полнено последнее обновление. Не стоит, однако, заменять номер версии временной
меткой — системные часы слишком ненадежны, особенно если речь идет о координации
работы нескольких пользователей.
Вместо сравнения номера версии в выражении WHERE оператора UPDATE МОЖНО ВЫ-
ПОЛНИТЬ сравнение по всем полям текущей строки, что позволяет обойтись без специаль-
ного поля версии. Это особенно удобно тогда, когда изменить таблицы базы данных для
добавления в них нового поля невозможно. К сожалению, данный прием требует мани-
пулирования потенциально большими выражениями WHERE, ЧТО может негативно ска-
заться на производительности всего приложения (в зависимости от того, насколько уме-
ло СУБД использует индекс по первичному ключу).
Зачастую реализация оптимистической автономной блокировки ограничивается про-
веркой номера версии в каждом операторе UPDATE ИЛИ DELETE. К сожалению, это не ре-
шает проблемы несогласованности чтения. Представьте себе расчетную систему, которая
определяет стоимость заказа и вычисляет сумму налога с продажи. Сеанс подсчитывает
суммарную стоимость заказа и затем проверяет место проживания покупателя, чтобы
подсчитать величину налога на сумму заказа
1
. Что произойдет, если в это же время другой
сеанс, относящийся к службе работы с клиентами, изменит адрес покупателя? Так как
величина налога зависит от места проживания, значение, подсчитанное первым сеансом,
может оказаться неправильным, однако, поскольку первый сеанс не пытался вносить
изменения в адрес покупателя, а только его считывал, конфликт не будет обнаружен.
Несмотря на изложенное, оптимистическая автономная блокировка вполне применима
и для обнаружения несогласованного чтения. В рассмотренном примере сеанс подсчета
суммы заказа должен определить, что правильность его действий зависит от значения ад-
реса соответствующего покупателя. Таким образом, проверка номера версии должна
применяться и к записи, содержащей адрес покупателя, возможно, путем искусственного
добавления адреса в набор изменений или поддержки специального списка элементов,
для которых нужно проверить номер версии. Последнее немного сложнее реализовать,
однако назначение полученного при этом кода будет более понятным. Если вместо ис-
кусственного обновления вы собираетесь просто перепроверить номер версии, обратите
особое внимание на используемый в системе уровень изоляции транзакций. Повторное
считывание номера версии можно проводить только при уровне изоляции "повторяемое
чтение" или выше. В противном случае номер версии придется искусственно увеличить.
1
В США величина налога с продажи зависит от штата, а иногда и от города, в котором живет покупа-
тель. — Прим. пер.