Полная блокировка таблицы и блокировка изменений

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

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

Для открытия таблицы в режиме полной блокировки используется команда SET EXCLUSIVE ON. После выполнения данной команды все открываемые таблицы будут находиться в режиме полной блокировки. Для снятия режима полной блокировки используйте команду SET EXCLUSIVE OFF. При этом полная блокировка открытых таблиц будет снята только после их закрытия. Для установки полной блокировки отдельной таблицы может быть использована опция EXCLUSIVE в команде открытия таблицы USE. Если таблица открыта в монопольном режиме, необходимость блокировки таблицы или ее записей отсутствует. После закрытия таблицы блокировка автоматически снимается.

Ниже приведены два примера установки полной блокировки таблицы. В первом примере используются две команды, а во втором — таблица открывается в режиме исключительного использования одной командой:

SET EXLUSIVE ON

USE CUSTOMER

или

USE CUSTOMER EXCLUSIVE

Некоторые команды, список которых приведен ниже, могут использоваться только в режиме полной блокировки:

  • ALTER TABLE
  • INDEX
  • INSERT [BLANK]
  • MODIFY STRUCURE
  • PACK
  • REINDEX
  • ZAP

Если вы попробуете применить одну из этих команд, не открыв таблицу для исключительного использования, FoxPro выдаст предупреждающее сообщение Exclusive Open of File Required.

Блокировка таблицы

Для установки блокировки изменений таблицы вы должны использовать функцию FLOCK, которая имеет следующий синтаксис:

FLOCK([псевдонимТаблицы])

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

В приведенном ниже примере для блокировки таблицы customer используется команда FLOCK (). Если таблица успешно заблокирована, команда REPLACE ALL обновляет все записи в ней. После этого команда UNLOCK снимает блокировку файла. Если файл невозможно заблокировать (такая ситуация возникает, если файл уже заблокирован другим пользователем), появится сообщение об ошибке.

SET EXCLUSIVE OFF

SET REPROCESS TO 0

USE Customer

IF FLOCK()

REPLACE ALL cLastName WITH UPPER(cLastName)

UNLOCK

ELSE

WAIT "Файл занят, подождите" WINDOW NOWAIT

ENDIF

Если вы редактируете две или более связанных командой SET RELATION таблиц, вам необходимо блокировать каждую связанную таблицу самостоятельно, т. к. блокировка одной из связанных таблиц не блокирует связанные с ней таблицы. Возможны ситуации, когда вы изменяете данные только в одной таблице, а другие используются для отображения дополнительной информации и их не требуется блокировать.

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

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

Для блокировки записей используются взаимозаменяемые функции LOCK и RLOCK, синтаксис которых отличается только наименованием функции:

RLOCK([ рабочаяОбласть | псевдонимТаблицы]

| [номераЗаписей, рабочаяОбласть

| псевдонимТаблицы])

Для указания таблицы, записи которой вы собираетесь блокировать, можно использовать номер рабочей области или псевдоним таблицы. Если не указаны ни рабочая область, ни псевдоним, функция LOCK будет блокировать текущую запись таблицы, открытой в рабочей области.

Для блокировки группы записей предварительно выполните команду SET MULTILOCKS ON и с помощью аргумента номера Записей укажите номера блокируемых записей. Номера записей задаются в символьном виде и разделяются запятыми. Например, для блокировки третьей и пятой записи таблицы необходимо указать "3, 5".

Замечание

Для определения номеров записей используйте функцию RECNO ().

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

Если запись или таблица уже заблокированы другим пользователем, блокировка не будет выполнена и функция возвратит значение . F. (Ложь).

Совет

Для блокировки группы записей вы можете поочередно устанавливать указатель записи на блокируемую запись и выполнять команду LOCK.

Для выбора режима блокировки одной или группы записей используется команда SET MULTiLOCKS, которая имеет следующий синтаксис:

SET MULTILOCKS ON | OFF

Параметр ON разрешает блокировку группы записей, а параметр OFF разрешает блокировку только одной записи.

Замечание

Переключение установки MULTILOCKS из ON в OFF, или из OFF в ON приводит к снятию блокировки со всех записей во всех открытых таблицах.