Глава 16. Типовые решения для обработки задач автономного параллелизма 449
к простому наложению ограничения уникальности на столбец, содержащий иденти-
фикатор блокируемого элемента. Хранение в базе данных блокировок чтения/записи
более сложно. Такая стратегия блокирования подразумевает предоставление доступа к
таблице блокировки не только для вставки, но и для чтения, а потому требует специ-
альной обработки несогласованного чтения. Полную защиту от подобных ситуаций
может гарантировать уровень изоляции с поддержкой упорядочиваемых транзакций.
Разумеется, использование таких транзакций по всей системе значительно снизит ее
производительность. Впрочем, вы можете применять упорядочиваемые транзакции
только для наложения блокировок, а в остальных ситуациях использовать менее стро-
гие уровни изоляции. Кроме того, для управления блокировками можно воспользо-
ваться хранимыми процедурами. Обработка параллельных заданий — занятие далеко
не простое, поэтому в спорных моментах не бойтесь полагаться на средства базы данных.
Необходимость упорядочения доступа к таблице блокировки не может не отразиться
на скорости работы приложения. В связи с этим стоит подумать о снижении детализации
блокирования, поскольку меньшее количество блокировок позволит снизить нехватку
производительности. В частности, для устранения соперничества за право доступа к таб-
лице блокировки можно воспользоваться блокировкой с низкой степенью детализации
(Coarse-Grained Lock, 457).
Если необходимые данные окажутся заблокированными кем-то другим, пессимисти-
ческие схемы блокирования системных транзакций наподобие оператора SELECT FOR
UPDATE или компонентов сущностей EJB предполагают ожидание до тех пор, пока бло-
кировка не будет снята, а следовательно, допускают возникновение взаимоблокировок.
Для большей наглядности механизм возникновения взаимоблокировки можно предста-
вить следующим образом. Пусть двум пользователям одновременно понадобились ресур-
сы А и Б. Если первый пользователь заблокирует ресурс А, а второй заблокирует ре-
сурс Б, обе транзакции будут бесконечно ожидать высвобождения второго ресурса. По-
скольку бизнес-транзакция охватывает несколько системных транзакций, подобное
ожидание теряет всякий смысл, особенно если учесть, что выполнение бизнес-
транзакции может занять около 20 минут, а то и больше. Никто не захочет так долго
ждать предоставления блокировки. Это и хорошо, поскольку в противном случае раз-
работчику пришлось бы возиться с кодированием механизма времени ожидания, что
отнюдь не просто. Рекомендую придерживаться стандартной схемы, при которой в слу-
чае отказа предоставления блокировки диспетчер выдает исключение. Это позволит пол-
ностью избавиться от неприятностей, связанных с взаимоблокировками.
И наконец, при управлении блокировкой необходимо позаботиться о механизме
времени ожидания, необходимом для обработки утраченных транзакций. Если в про-
цессе выполнения транзакции машина клиента выйдет из строя, транзакция никогда
не будет завершена, а следовательно, блокировка не будет снята. Данная проблема
особенно критична для Web-приложений, которые слишком часто забывают закрывать
должным образом. В идеале обработкой времени ожидания должно заниматься не само
приложение, а сервер приложений. Для этого серверы Web-приложений применяют
HTTP-сеансы. Механизм времени ожидания может быть реализован путем регистра-
ции объекта, который автоматически высвобождает все блокировки, когда НТТР-
сеанс станет недействительным. Вместо этого каждой блокировке можно присвоить
временную метку и считать недействительными все блокировки, время жизни которых
больше определенного значения.