В однопользовательской системе с данными работает только один человек, и ему нет необходимости думать о разделении доступа к файлам. Однако, с появлением пользователей, желающих получить доступ к одним и тем же данным, планирование разделения доступа к базе становится актуальным.
В многопользовательских приложениях необходимо обеспечить доступ к данным тем пользователям, которым он действительно нужен. При разработке сетевых приложений по управлению базами данных необходимо предусмотреть разрешение конфликтов, возникающих при попытке двух и более пользователей одновременно изменить одни и те же данные. Visual FoxPro предлагает несколько вариантов решения этой проблемы, позволяя пользователю использовать перед изменением таблиц или записей автоматические или ручные методы их блокировки. При доступе к записям таблицы блокировка запрещает кому-либо изменять заблокированную область, пока пользователь не завершит свои изменения и не разблокирует эти данные.
Эта глава ознакомит вас с концепциями разделения данных в сетевой среде и организацией интерфейса при совместной работе нескольких пользователей.
В Vi&ual FoxPro вы можете использовать два типа блокировок: блокировку таблицы и записи. Блокировка таблицы запрещает доступ другим пользователям ко всей таблице, пока вы редактируете одну или несколько записей. Применение блокировки записи не допускает изменения записи кем-либо, кроме пользователя, установившего блокировку.
По возможности следует использовать блокировку записи, потому что она запрещает изменение только одной записи, а не всей таблицы. Например, пока вы редактируете запись о покупателе Иванове, кто-нибудь может работать с записью о покупателе Петрове. И вы оба можете совершать изменения, не мешая друг другу и не беспокоясь за действия другого.
В Visual FoxPro может осуществляться автоматическая или ручная блокировка данных. При использовании определенных команд FoxPro попытается автоматически заблокировать записи или всю таблицу (табл. 20.1).
Таблица 20.1. Команды, автоматически блокирующие таблицу или записи
Команда | Что блокируется |
ALTER TABLE | Вся таблица |
APPEND | Вся таблица |
APPEND BLANK | Заголовок таблицы |
APPEND FROM | Вся таблица |
APPEND FROM ARRAY | Заголовок таблицы |
APPEND MEMO | Текущая запись |
BLANK | Текущая запись |
BROWSE | Текущая запись и все записи из одноименных полей в связанных таблицах |
CHANGE | Текущая запись и все записи из одноименных полей в связанных таблицах |
DELETE | Текущая запись |
DELETE NEXT 1 | Текущая запись |
DELETE <n> | Если л больше 1 , автоматически блокируется вся таблица |
DELETE RECORD <n> | Автоматически блокирует п записей |
DELETE SQL | Текущая запись |
EDIT | Текущая запись и все записи из одноименных полей в связанных таблицах |
GATHER | Текущая запись |
INSERT | Вся таблица |
INSERT SQL | Заголовок таблицы |
MODIFY MEMO | Когда начинается редактирование записи, автоматически блокирует ее |
READ | Текущая запись |
RECALL | Текущая запись |
RECALL NEXT 1 | Автоматически блокирует указанную запись |
RECALL RECORD <n> | Блокирует п записей |
RECALL <n> | Если п больше 1 , автоматически блокируется вся таблица |
REPLACE | Текущая запись |
REPLACE NEXT 1 | Автоматически блокирует указанную запись |
REPLACE RECORD <n> | Блокирует п записей |
SHOW GETS | Текущая запись |
TABLEUPDATEO | Вся таблица |
UPDATE | Вся таблица |
UPDATE SQL | Вся таблица |
Замечание
Все команды с автоматической блокировкой снимают ее после выполнения.
Полная блокировка таблицы и блокировка изменений
В некоторых случаях, например, при изменении структуры данных, вам необходимо осуществить полную блокировку таблицы для получения исключительных прав на нее. В этом случае другим пользователям запрещается чтение, запись и изменение структуры указанной таблицы, и они не смогут получить к ней доступ. Вы не можете установить полную блокировку, если эта таблица уже открыта или для нее уже установлена блокировка.
В большинстве случаев вам достаточно ограничить изменение данных таблицы, т. е. установить блокировку изменений, которая запрещает запись, изменение структуры указанной таблицы, наложение блокировки изменений другими пользователями.
Для открытия таблицы в режиме полной блокировки используется команда SET EXCLUSIVE ON. После выполнения данной команды все открываемые таблицы будут находиться в режиме полной блокировки. Для снятия режима полной блокировки используйте команду SET EXCLUSIVE OFF. При этом полная блокировка открытых таблиц будет снята только после их закрытия. Для установки полной блокировки отдельной таблицы может быть использована опция EXCLUSIVE в команде открытия таблицы USE. Если таблица открыта в монопольном режиме, необходимость блокировки таблицы или ее записей отсутствует. После закрытия таблицы блокировка автоматически снимается.
Ниже приведены два примера установки полной блокировки таблицы. В первом примере используются две команды, а во втором — таблица открывается в режиме исключительного использования одной командой:
SET EXLUSIVE ON
USE CUSTOMER
или
USE CUSTOMER EXCLUSIVE
Некоторые команды, список которых приведен ниже, могут использоваться только в режиме полной блокировки:
Если вы попробуете применить одну из этих команд, не открыв таблицу для исключительного использования, 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 приводит к снятию блокировки со всех записей во всех открытых таблицах.
Установка режима повторных попыток блокировки данных
Если запись или таблица уже заблокированы, вам не удастся с первого раза установить блокировку. В этом случае вы можете использовать команду SET REPROCESS, которая задает количество дополнительных попыток заблокировать таблицу (или запись) или время, на протяжении которого будут выполняться дополнительные попытки блокировки.
Команда SET REPROCESS имеет следующий синтаксис:
SET REPROCESS ТО числоПопьггок [SECONDS] I TO AUTOMATIC
Если команда содержит опцию SECONDS, аргумент число попыток задает время в секундах, иначе — количество попыток. Аргумент число попыток может принимать целые значения в диапазоне от 1 до 32 000, по умолчанию его значение равно 0.
При использовании параметра то AUTOMATIC, а также, если значение аргумента число попыток равно 0, Visual FoxPro будет пытаться выполнить блокировку записи или таблицы до бесконечности. Во время выполнения попыток блокировки будет выводиться сообщение о том, что идет процесс блокировки. Пользователь может прервать процесс установки блокировки нажатием клавиши <Esc>.
При установке SET REPROCESS то -i Visual FoxPro также будет пытаться выполнить блокировку записи или таблицы до бесконечности. Но в этом случае пользователь не может прервать попытки заблокировать запись или таблицу.
Замечание
Успешная блокировка записи или таблицы, уже заблокированной другим пользователем, возможна только после того, как пользователь, установивший блокировку, снимет ее. Поэтому рекомендуется снимать блокировку сразу же после завершения операции, для выполнения которой требовалась блокировка.
Снятие блокировок таблиц и записей
В большинстве случаев при переходе от одной записи к другой блокировка снимается. Однако, если вы заблокировали запись командами блокировки, ее необходимо разблокировать, чтобы к ней могли получить доступ другие пользователи. В табл. 20.2 описаны команды, используемые для снятия блокировок.
Таблица 20.2. Команды снятия блокировки с записей и таблиц
Команда | Описание |
CLOSE | Снимает асе блокировки с записей и таблиц |
CLOSE ALL | Снимает все блокировки с записей и таблиц |
END TRANSACTION | Снимает все автоматически установленные блокировки |
QUIT | Снимает все блокировки с записей и таблиц |
UNLOCK | Снимает все блокировки с записей и таблиц в текущей рабочей области |
UNLOCK ALL | Снимает все блокировки с записей и таблиц во всех рабочих областях |
USE | Снимает все блокировки с записей и таблицы |
SET MULTILOCKS OFF | Позволяет автоматическое снятие текущей блокировки при создании новой |
FLOCK ( ) | Перед блокировкой файла снимает все блокировки находящихся в нем записей |
TABLEUPDATE ( ) | Прежде чем обновить таблицу, снимает все блокировки |
Наиболее часто для снятия блокировок с таблиц и записей используется команда UNLOCK, которая имеет следующий синтаксис:
UNLOCK [RECORD номерЗаписи] [IN < псевдонимТаблицы >] [ALL]
Команда UNLOCK без параметров сбрасывает блокировку с текущей записи или таблицы.
При снятии блокировки с таблицы опция RECORD не используется, задается только псевдоним таблицы. Если псевдоним не указан, снимается блокировка с текущей таблицы. Для разблокировки всех открытых таблиц используется параметр ALL. Для снятия блокировки с записи укажите параметр RECORD и номер записи.
Замечание
Блокировка записи или таблицы может сниматься только пользователем, установившим данную блокировку. Таблицы, открытые в режиме полной блокировки, с помощью команды UNLOCK разблокировать нельзя.
В Visual FoxPro для многопользовательской работы вы можете использовать сеансы работы с данными, которые представляют из себя среду окружения, связанную с формой или набором форм. С помощью сеансов работы с данными вы можете открывать одну и ту же форму на разных рабочих станциях или даже на одном компьютере (рис. 20.1), при этом каждая из них будет использовать отдельную копию данных.
Для управления сеансом работы с данными предназначено свойство DataSession (Окно данных) формы, которое можно установить равным 1 или 2. Если вы установите свойство DataSession равным 1, любые изменения, выполненные вами в форме, будут отображаться во всех остальных открытых формах. Это обычный режим работы. Дня открытия копии среды окружения установите значение 2, при этом изменения в данной форме не будут отображаться в других формах. Количество открытых сеансов ограничивается только доступной оперативной памятью и местом на жестком диске.
Рис. 20.1. Открытие сеансов работы на одном компьютере
Рис. 20.2. Выбор сеанса работы
Для выбора сеанса работы вы можете выполнить любое из следующих действий.
Одним из мощных средств организации многопользовательской работы в Visual FoxPro является буферизация данных, которая позволяет лучше использовать локальные ресурсы и снижает нагрузку на сеть. При буферизации все сделанные вами изменения хранятся в оперативной памяти на рабочей станции и не обновляются на файл-сервере, пока вы не выполните соответствующую команду.
В Visual FoxPro используются два типа буферизации: буферизация таблиц и записей. При буферизации записей после завершения редактирования записи (при изменении позиции указателя записи или при вызове функции TABLEUPDATE), все изменения записываются в базу данных. При буферизации таблиц измененные данные' сохраняются в базе данных только при закрытии таблицы или вызове функции TABLEUPDATE (}.
В Visual FoxPro вы можете выбрать пессимистический и оптимистический режимы буферизации, которые определяют, как и когда будет осуществляться блокировка данных. В зависимости от типа решаемых задач, вы можете выбрать один из типов буферизации данных (табл. 20.3).
Таблица 20.3. Типы буферизации данных
Значение | Описание |
1 | Буферы не используются |
2 | Пессимистическая блокировка записей. Visual FoxPro блокирует запись сразу же после начала редактирования данных и освобождает блокировку только после перехода на следующую запись или при выполнении фуНКЦИИ TABLEUPDATE ( ) |
3 | Оптимистическая блокировка записей. Позволяет редактировать текущую запись в других сеансах работы и блокирует запись только при переходе на следующую запись или выполнении функции TABLEUPDATE ( } |
4 | Пессимистическая блокировка таблицы. Блокируются все редактируемые записи, но их обновление в базе данных осуществляется только при вызове функции TABLEUPDATE ( ) |
5 | Оптимистическая блокировка таблицы. Позволяет редактировать записи в других сеансах работы и блокирует записи только при обновлении записей в базе данных с помощью функции TABLEUPDATE ( ) |
При выборе любого типа буферизации данных вы можете отказаться от выполненных изменений с помощью функции TABLEREVERT ().
Для установки типа буферизации вы можете использовать функцию CURSORSETPROPO, свойство BufferMode формы и свойство BufferModeOverride курсора, используемого в среде окружения формы.
Свойство BufferMode формы может принимать одно из значений, описанных в табл. 20.4.
Таблица 20.4. Значения свойства BufferMode
Значение | Описание |
0 | Записи блокируются с момента начала редактирования, и значения полей записываются в базу данных при переходе к следующей записи |
1 | Пессимистическая блокировка записей |
2 | Оптимистическая блокировка записей |
Для определения свойства Buf ferModeOverride откройте окно конструктора формы, выполните команду Data Environment (Среда окружения) из меню View (Вид). Далее в окне Data Environment (Среда окружения) выберите таблицу, нажмите правую кнопку мыши и из контекстного меню выберите команду Properties (Свойства). Откроется окно свойств, в котором выберите свойство BufferModeOverride (рис. 20.3) и установите одно из возможных значений (табл. 20.5).
Таблица 20.5. Значения свойства BufferModeOverride
Значение | Описание |
0 | Буферы не используются |
1 | Использует тип блокировки, заданный свойством BufferMode формы |
2 | Пессимистическая блокировка записей |
3 | Оптимистическая блокировка записей |
4 | Пессимистическая блокировка таблицы |
5 | Оптимистическая блокировка таблицы |
Рис. 20.3. Определение значения свойства BufferModeOverride курсора
Рис. 20.4. Определение типа блокировки в диалоговом окне Work Area Properties
Функция CURSORSETPROP (), используемая для определения типа буферизации курсора, имеет следующий синтаксис:
CURSORSETPROP(Buffaring, типБуферизации,
псевдонимТаблицы | номерРабочейОбласти])
Для определения текущего типа буферизации воспользуйтесь свойством BufferModeOverride курсора или функцией CURSORGETPROP() .
При работе в интерактивном режиме вы можете установить тип блокировки в диалоговом окне Work Area Properies (Свойства рабочего пространства) (рис. 20.4), которое открывается при нажатии кнопки Properties (Свойства) в диалоговом окне Data Session (Данные сеанса),
Обнаружение и устранение конфликтов
При совместной работе с базой данных возможны конфликты, когда один или более пользователей пытаются заблокировать уже заблокированную другим пользователем запись. Возможны и взаимоблокировки, когда пользователь заблокировал одну запись или таблицу и пытается заблокировать вторую, которая уже заблокирована вторым пользователем. В то же время второй пользователь пытается заблокировать запись, заблокированную первым пользователем. Система буферизации записей и таблиц FoxPro упрощает разработку многопользовательских приложений и устранение возникающих конфликтов.
При попытке заблокировать уже заблокированную запись FoxPro выдает сообщение об ошибке. Для определения возникновения ошибки вы можете воспользоваться функцией TABLEUPDATE (), которая возвращает значение . F. (Ложь) при неудачной попытке сохранения данных. Кроме того, вы можете написать программу обработки ошибок и указать ее в команде ON ERROR. Для определения причины, по которой не удалось записать данные в базу данных, вы можете использовать значения кодов ошибок. Для определения кодов ошибок используется функция ERROR () или AERROR () .
При использовании буферизации данных в программе обработки ошибок вы можете определить, какие поля были изменены, каким было исходное значение поля и каким оно стало. Для определения изменения поля используется функция GETFLDSTATE (), которая по заданному номеру поля возвращает одно из значений, описанных в табл. 20.6.
Таблица 20.6. Значения, возвращаемые функцией GETFLDSTATE ()
Значение | Состояние |
1 | Значение поля не изменялось |
2 | Значение поля было изменено или поле было удалено |
3 | Значение поля во вновь добавленной записи не изменялось |
4 | Значение поля во вновь добавленной записи было изменено или поле было удалено |
Под транзакцией в системах управления базами данных понимают логическую единицу работы, которая представляет собой последовательность нескольких операций, в процессе выполнения которых сохраняется целостное состояние базы данных. В процессе выполнения транзакции обновляемые данные временно хранятся в памяти или на локальном диске. Действительные изменения совершаются только после завершения транзакции. Если что-либо препятствует обновлению данных, все изменения отменяются и поэтому ваши данные остаются без изменения.
Для управления транзакциями используется три команды, представленные в табл. 20.7.
Таблица. 20.7. Команды, используемые для управления транзакциями
Команда | Назначение |
BEGIN TRANSACTION | Инициирует транзакцию |
ROLLBACK | Осуществляет откат, т. е. аннулирует все выполненные в течение транзакции действия |
END TRANSACTION | Завершает транзакцию и сохраняет все выполненные действия в базе данных |
В некоторых случаях вам может понадобиться использовать вложенные транзакции, при этом каждая из них должна начинаться командой BEGIN TRANSACTION и завершаться командой END TRANSACTION. Выполнение команды ROLLBACK действует только на транзакцию, внутри которой она выполняется. Команды BEGIN и END TRANSACTION могут находиться в разных функциях или процедурах.
Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.
Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").
Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.
Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.
Понятие "мысленный эксперимент" придумано специально спекулянтами - релятивистами для шулерской подмены реальной проверки мысли на практике (эксперимента) своим "честным словом". Подробнее читайте в FAQ по эфирной физике.
|
![]() |