Блокировка записи

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Блокировка записи — это метод предотвращения одновременного доступа к данным в базе данных, чтобы предотвратить противоречивые результаты.

Классический пример демонстрируют два банковских служащих, пытающихся обновить одну и ту же банковскую учетную запись для двух разных транзакций. Служащие 1 и 2 извлекают (то есть копируют) запись учетной записи. Клерк 1 применяет и сохраняет транзакцию. Клерк 2 применяет другую транзакцию к своей сохраненной копии и сохраняет результат на основе исходной записи и его изменений, перезаписывая транзакцию, введенную клерком 1. Запись больше не отражает первую транзакцию, как если бы она никогда не существовала.

Простой способ предотвратить это — заблокировать файл всякий раз, когда запись изменяется любым пользователем, чтобы никакой другой пользователь не мог сохранить данные. Это предотвращает неправильную запись записей, но позволяет обрабатывать только одну запись за один раз, блокируя других пользователей, которым необходимо одновременно редактировать записи.

Чтобы разрешить нескольким пользователям одновременно редактировать таблицу базы данных, а также предотвращать несоответствия, созданные неограниченным доступом, можно восстановить одну запись при её извлечении для редактирования или обновления. Любому, кто пытается получить одну и ту же запись для редактирования, запрещается доступ на запись из-за блокировки (хотя, в зависимости от реализации, они могут просматривать запись, не редактируя её). Когда запись сохранена или изменения отменены, блокировка будет отпущена. Записи могут быть не сохранены, чтобы перезаписывать другие изменения, сохраняя целостность данных.

В теории управления базами данных блокировка используется для реализации изоляции между несколькими пользователями базы данных. Это «I» в сокращенном ACID.

Подробное и авторитетное описание блокировки. было написано Джимом Грей.[1]

Гранулярность блокировок[править | править код]

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

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

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

В базе данных SQL, запись обычно называется «строка».

Введение гранулированных (подмножеств) замков создает возможность возникновения ситуации, называемой «мертвая блокировка». Тупик возможен, когда используется инкрементная блокировка (блокировка одного объекта, затем блокировка одного или нескольких дополнительных объектов). Чтобы проиллюстрировать, если два клиента банка попросили двух клерков получить информацию об учетной записи, чтобы они могли перевести некоторые деньги на другие счета, эти два счета были бы по существу заблокированы. Затем, если клиенты сказали своим клеркам, что деньги должны были быть переведены на счета друг друга, клерки будут искать другие счета, но находят их «активными» и ждут их возвращения. Не зная, два клерка ждут друг друга, и ни один из них не может завершить свою транзакцию, пока другой не сдастся и не вернет счет. Для избежания таких проблем используются различные методы.

Использование блокировок[править | править код]

Блокировки записи должны управляться между объектами, запрашивающими записи, таким образом, чтобы ни один объект не получал слишком много услуг через последовательные гранты, и ни один другой объект не блокировался эффективно. Объекты, запрашивающие блокировку, могут быть как отдельными приложениями (программами), так и целым процессором.

Приложение или система должны быть спроектированы так, чтобы любая блокировка удерживалась в течение кратчайшего времени. Чтение данных без средств редактирования — не требует блокировки, и чтение заблокированных записей обычно допустимо.

Может быть предложено два основных вида блокировок:

Исключительные блокировки[править | править код]

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

  • Обеспечить фиксацию замка нужно в как можно более короткий промежуток времени;
  • Не удерживать блокировку в системных или функциональных вызовах, когда объект больше не работает на процессоре — это может привести к взаимо-блокировке;
  • Убедитесь, что если объект неожиданно завершает работу по какой-либо причине, блокировка будет освобождена.

Номера держателей блокировки (иначе называемые «держателями») могут храниться в списке, обслуживаемом циклически или в очереди FIFO. Это гарантирует, что любой возможный держатель будет иметь равную возможность получить блокировку и не будет заблокирован. Чтобы ещё больше ускорить процесс, если сущность в ожидании блокировки, субъект уведомляется о гранте это увеличит производительность, вместо того, чтобы обнаружить его на каком-то системном тайм-ауте, управляемом пробуждением.

Общие блокировки[править | править код]

Общие блокировки отличаются от «эксклюзивных» блокировок тем, что список держателей может содержать несколько записей. Общие блокировки позволяют всем держателям читать содержимое записи, зная, что запись не может быть изменена до тех пор, пока блокировка не будет освобождена всеми держателями. Исключительные блокировки не могут быть получены, когда запись уже заблокирована (исключительно или совместно) другим объектом.

Если запросы блокировки для одного и того же объекта поставлены в очередь, то после предоставления общей блокировки также могут быть предоставлены любые заблокированные в очереди блокировки. Если в очереди находится исключительная блокировка, она должна дождаться освобождения всех разделяемых блокировок. Как и в случае с исключительными блокировками, эти общие блокировки следует удерживать в течение как можно меньшего времени.

Примечания[править | править код]

  1. Gray, Jim & Reuter, Andreas (1993), Distributed Transaction Processing: Concepts and Techniques, Morgan Kaufmann, с. 375–437, ISBN 1-55860-190-2