Буферизация на уровне записи означает, что перед началом редактирования содержимое текущей записи будет сохранено во внутреннем буфере СУБД. Буферизация нв уровне таблицы сохраняет в буфере содержание всех отобранных для редактирования записей. Оптимистическая буферизация обеспечивает блокировку записей только на время сохранения содержимого буфера в файле, что соответствует приведенному выше случаю 2. Пессимистическая буферизация работает как в случае 1, то есть блокирует запись перед копированием ее содержимого в буфер.
Использование буферизации позволяет автоматизировать процесс переноса данных из полей БД в переменные и обратно. При этом группа функций позволяет получить исчерпывающую информацию о состоянии буферизованной таблицы, что дает возможность организовать очень эффективный алгоритм разрешения возможных конфликтов при изменении данных (схема их взаимодействия приведена на рисунке 1).
OLDVAL() – возвращает первоначальное значение поля, которое было модифицировано, но не обновлялось.
CURVAL() – возвращает значение поля непосредственно с диска или из удаженного источника.
TABLEUPDATE() – фиксирует изменения, внесенные в буферизованную запись либо в буферизованную таблицу или курсор.
TABLEREVERT() – сбрасывает изменения, внесенные в буферизованную запись либо в буферизованную таблицу или курсор и восстанавливает содержимое по данным OLDVAL().
При буферизации таблицы мы имеем возможность добавлять и удалять записи в буфере. При добавлении новая запись помещается в конец буфера и получает номер с отрицательным значением. Доступ к этой записи может быть выполнен с помощью функции RECNO() с отрицательным параметром, например –1.
RECNO() - возвращает номер текущей записи в текущей или заданной таблице
При написании многопользовательских приложений необходимо учитывать, что целый ряд команд при их использовании выполняет автоматическую блокировку.
Если вы решили управлять блокировкой вручную, то придерживайтесь следующего алгоритма:
проверьте состояние блокировки записи или таблицы; если блокировки нет, то требуемые ресурсы можно заблокировать; если ресурсы блокированы, попробуйте еще раз, но при этом следует избегать слишком частых попыток. Кроме чрезмерной загрузки сети это ни к чему не приведет.При разработке алгоритма блокировки старайтесь придерживаться четкой последовательности событий. Например, в следующем примере при борьбе за несколько ресурсов будет наблюдаться патовая ситуация (тупик):
Пользователь 1 | Пользователь 2 |
Попытка блокировать запись 1 | Попытка блокировать запись 4 |
Попытка блокировать запись 4 | Попытка блокировать запись 1 |
Если попытка неудачна, ждлем освобождения ресурсов | Если попытка неудачна, ждлем освобождения ресурсов |
Ждем, ждем, ждем … | Ждем, ждем, ждем … |
Существуют два простых правила, помогающих избежать данной ситуации. Во-первых, необходимо выполнять все действия в одинаковой последовательности, т.е. 2-й пользователь должен пытаться блокировать записи, также начиная с первой. Во-вторых, всегда необходимо ставить ограничения по времени на попытки блокировки, чтобы дать возможность хотя бы одному пользователю закончить работу.
Ряд команд и функций автоматически обеспечивают снятие блокировки:
Закрытие таблицы Завершение транзакции Завершение сеанса работы с СУБД Фиксация изменений, внесенных в буферизованную запись или таблицуЕсли вы хотите обеспечить защиту изменяемых данных и возможность восстановления первоначальных значений на протяжении определенного периода испольнения программы, используйте механизм встроенных транзакций. При использовании транзакций с момента выдачи команды «Начать транзакцию» все изменения сначала сохраняются в памяти компьютера или на диске и только при завершении транзакции переносятся в таблицу. При этом таблица обязательно должна быть включена в базу данных. Если в процессе работы выяснилась нецелесообразность использования сделанных изменений, до выполнения команды «Завершить транзакцию» всегда остается возможность вернуться к первоначальному состоянию таблицы, выдав команду «Отменить изменения, внесенные в ходе текущей транзакции». Для организации логических групп по обновлению данных можно использовать вложенные транзакции.
В общем случае при использовании транзакций предпочтительной является буферизация записи по сравнению с буферизацией таблицы.
Использование транзакций не может гарантировать сохранение измененных данных, например, при выключении компьютера. В этом случае автоматически выполнится откат к состоянию таблицы до начала транзакции.
Интерфейс прикладного программирования ODBC API предоставляет общие методы доступа SQL как к реляционным, так и к нереляционным (ISAM) источникам данных.
В ANSI SQL входит интерфейс на уровне вызовов (CLI - call-level interface), который используется ODBC для обеспечения доступа и работы с данными во многих системах управления базами данных. Интерфейс CLI соответствует требованиям, установленным в 1991 году группой SQL Access Group, которые определяют общий синтаксис SQL и интерфейса API. Иметь общий метод доступа к источникам данных удобно потому, что тогда база данных на сервере становится прозрачной для приложений, которые написаны в соответствии с некоторым заданным уровнем совместимости ODBC.
Интерфейс ODBC API реализован как набор расслоенных DLL-функций для Windows. Динамическая библиотека ODBC.DLL - это основная библиотека управления драйверами ODBC, которая вызывает специализированные драйверы для разных поддерживаемых системой баз данных. Каждый драйвер совместим со своим уровнем CLI и относится к одной из двух категорий: одноуровневые или многоуровневые драйверы.
Одноуровневые драйверы предназначены для использования при работе с теми источниками данных, которые не могут быть обработаны ANSI SQL. Обычно это локальные базы данных на персональных компьютерах, такие как dBase, Paradox, FoxPro и др. Драйверы, соответствующие этим базам данных, переводят грамматику ANSI SQL в инструкции низкого уровня, которые непосредственно обрабатывают составляющие базу данных файлы.
Многоуровневые драйверы используют сервер СУРБД для обработки SQL-предложений и предназначены для работы в среде клиент-сервер. Помимо обработки ANSI SQL, они также могут поддерживать и собственную грамматику конкретной СУРБД, поскольку ODBC может без трансляции передавать SQL-предложения источникам данных (механизм "passthrough").
Драйверы ODBC для баз данных типа клиент-сервер реализованы для Oracle, Informix, Microsoft и Sybase SQL Server, Rdb, DB2, Ingres, HP/Image и Any SQL.
Существует 4 важных этапа (шага) процедуры запроса данных через API.
Шаг 1 - установление соединения. Первый шаг состоит в размещении указателей (handle) среды ODBC, которые выделяют оперативную память под ODBC драйверы и библиотеки. Затем происходит выделение памяти для указателей соединения, и соединение устанавливается.
Шаг 2 - выполнение предложения SQL. Выделяется указатель предложения, локальные переменные связываются со столбцами в SQL-выражении (это необязате~ьное действие), и выражение представляется на разбор главному ODBC драйверу для обработки.
Шаг 3 - извлечение данных. Перед извлечением данных возвращается информация о результирующем наборе, такая как число столбцов в наборе. Исходя из этого числа, результирующий набор помещается в буфер записей, выполняется цикл по нему и извлекается по одному столбцу в локальные переменные. Этот шаг необязателен, если используется связывание столбцов.
Шаг 4 - освобождение ресурсов. После того, как данные получены, освобождаются ресурсы вызовом функций освобождения указателей предложения, соединения и среды. Указатели предложения и соединения могут быть использованы в процессе обработки.
Технология ODBC разрабатывалась как общий, независимый от источников данных, способ доступа к данным. Также ее применение должно было обеспечить переносимость приложений на различные базы данных без переработки самих приложений. В этом смысле технология ODBC уже стала промышленным стандартом, ее поддерживают практически все производители СУБД и средств разработки.
Однако универсальность стоит дорого. Если при разработке приложений одним из основных критериев является переносимость на различные СУБД, то использование ODBC является оправданным. Для увеличения производительности и эффективности приложения активно применяют специфические для данной СУБД расширения языка SQL, используют хранимые на сервере процедуры и функции. В этом случае теряется роль ODBC как общего метода доступа к данным. Тем более, что для разных СУБД драйверы ODBC поддерживают разные уровни совместимости. Поэтому многие производители средств разработки помимо поддержки ODBC поставляют "прямые" драйверы к основным СУБД.