Введение
Btrieve — это база данных, разработанная компанией Pervasive Software. Архитектура Btrieve была спроектирована с учетом управления записями. Это означает, что Btrieve оперирует только базовыми операциями создания записей, извлечения данных, обновления записей и удаления данных. Вместе с MicroKernel Database Engine он использует ISAM (метод индексированного последовательного доступа) в качестве базового механизма хранения. Btrieve по сути является базой данных, использующей ключи и индексы для организации данных. Однако структура файлов в значительной степени построена вокруг небольших блоков данных, называемых "страницами" в Btrieve. Хотя структура менялась в различных версиях Btrieve, организация файлов по-прежнему основана на записи управления файлом (FCR), определяющей конфигурацию страниц, и самих страницах в файле Btrieve, содержащих данные. Исторически Btrieve использовал "физические страницы", то есть страницы, расположенные в фиксированных позициях в файле. Начиная с версии 6.0, стали использоваться "логические страницы", которые отображались в таблицы распределения страниц (PAT). Это позволило Btrieve изменить метод обновления записей с техники, позже известной как "pre-image paging", на технику, называемую "shadow paging". Btrieve придерживается обратной совместимости: версии Btrieve до 6.15 используют стандартный формат файла и, до выпуска Btrieve 6.0, были полностью обратно совместимы. Btrieve 6.0 представил новые функции и вынужден был нарушить совместимость со старыми версиями программного обеспечения для реализации более продвинутых возможностей. API также оставался обратно совместимым, за исключением одной функции (разделение файлов на отдельные носители), которая была исключена. В свое время бывший генеральный директор Btrieve Рон Харрис заявил: "API версии 1.0 по-прежнему поддерживается в версии 6.15, и мы будем поддерживать его вечно!".
Терминология базы данных
Первизив первоначально использовал термин «навигационная база данных» для описания Btrieve, но позже изменил его на «транзакционную базу данных». Использование термина «навигационная база данных» было необычным, поскольку в навигационной базе данных для перемещения между записями данных используются «указатели» и «пути», при этом эти указатели содержатся непосредственно в записи; ISAM, являющаяся базовой структурой Btrieve, использует вторичную индексную таблицу для хранения этих указателей с целью сокращения времени поиска. Таким образом, эти два типа баз данных различны, и это может, а может и не объяснить, почему Pervasive начала использовать другую терминологию для классификации своей базы данных.
Двигатель базы данных микроядра
Начиная с версии 6.15, Pervasive начала использовать новый модульный подход к разделению серверной части базы данных от интерфейса, используемого разработчиками. Основные операции с базой данных (такие как обновление, запись и удаление записей) были отделены от модулей Btrieve и Scalable SQL. Разделение Micro Kernel Database Engine (MKDE) от других функций позволило программистам одновременно использовать несколько методов доступа к базе данных. Например, одно приложение может быть создано с использованием Btrieve API, а другое приложение, которому требуется доступ к тем же данным, может использовать совершенно другой метод, например Scalable SQL. Поскольку базовые операции с записями были отделены от этих методов, оба приложения могут использовать MKDE для доступа к одному и тому же файлу данных. Micro Kernel Database Engine не имеет отношения к микроядерным операционным системам.
Поиск
Формат файла Btrieve состоит полностью из страниц, которые являются данными, перемещаемыми между памятью и запоминающими устройствами при выполнении операций ввода-вывода движком. В версиях, предшествующих 6.0, использовались только страницы данных, индексные страницы и запись управления файлом (FCR). Файл содержал индекс для поиска, связанный с физическими страницами. Начиная с версии 6.0, стали использоваться логические страницы, которые отображаются на физические страницы (страницы с фиксированным расположением в файле) на диске посредством набора таблиц распределения страниц (PAT).
Запись управления файлом
Запись управления файлами (FCR) содержит важную информацию о файлах базы данных Btrieve. В ней содержится размер страницы, количество страниц, находящихся в текущем использовании, количество ключей, которые могут индексировать файл, количество записей в файле и другие сведения. Начиная с версии 6.0, для обеспечения надежности использовались два FCR. 32-битное поле счетчика использования, присутствующее в каждом FCR, используется для определения, какой FCR является действительным. Каждый раз, когда над файлом выполняется операция, значение этого поля увеличивается. FCR с наибольшим счетчиком использования становится действительным. Подробное описание FCR можно найти в примерах кода, предоставленных Джимом Кайлом. С появлением MKDE версии 8 структура страницы FCR была изменена. Размер страницы теперь хранится непосредственно в FCR и больше не является стандартным 32-битным полем. Начиная с версии 8, для вычисления размера страницы необходимо взять 32-битное поле со смещением 0x2A и умножить его на 256.
Пейджинг перед изображением против пейджинг теней
До версии 6.0 при обновлении записей использовалась предварительная постраничная запись. Этот процесс включал создание нового "файла предварительного образа" перед внесением изменений, а затем временное копирование страниц из исходного файла данных в этот новый файл предварительного образа. После этого система вносила изменения в исходный файл. Если обновление прерывалось и на страницу было записано только половина данных, то механизм отката копировал страницу из файла предварительного образа обратно на поврежденную страницу в исходном файле базы данных, после чего временный файл предварительного образа удалялся. Файлы предварительного образа имели расширение PRE, поэтому обнаружение таких файлов в системе обычно указывало на некорректное завершение транзакции и неудачное восстановление. Начиная с версии 6.0, вместо предварительной постраничной записи стала использоваться теневая постраничная запись, и она применяется до сих пор. Вместо копирования страницы во временный файл, в файле базы данных находилось следующее свободное физическое местоположение, и страница записывалась туда. Эта страница называется теневой, поскольку её местоположение ещё не было записано в PAT файла. После завершения обновления теневой страницы PAT обновлялся, и запись о ней добавлялась в PAT следующей доступной и текущей физической страницы в файле. Однако, если во время обновления теневой страницы происходила системная ошибка, PAT не обновлялся, и изменение отменялось, так как текущая и следующая записи в PAT оставались неизменными. Переход от предварительной постраничной записи к теневой привел к радикальным изменениям формата файла, что нарушило совместимость между предыдущими версиями Btrieve и версией 6.x продукта.
Страницы с альтернативной последовательностью сбора
Страницы с альтернативной последовательностью сортировки (ACS) — это страницы, позволяющие сортировать записи в другом порядке. Сортировка — это упорядочение письменной информации в соответствии со стандартным правилом. В обычном понимании это называется алфавитным упорядочиванием, хотя сортировка не ограничивается упорядочением только букв алфавита. Например, ACS может позволять сортировку с учетом и без учета регистра символов. До версии 6.0 в файле можно было хранить только один ACS, однако после выпуска версии 6.0 к файлу можно было одновременно привязать несколько страниц ACS.
Дополнительные страницы
В файлах версии 6.0 и более поздних версий может существовать больше физических страниц, чем фактически используются. Это происходит потому, что при использовании теневого копирования некоторые страницы в системе могут отсутствовать в PAT. Эти страницы помечаются как "свободные", и они используются до того, как выделяется место для новых страниц.
Таблицы распределения переменных по хвосту
В Btrieve каждая страница имеет фиксированный размер, но запись может превышать размер страницы. Это означает, что записи часто необходимо фрагментировать и распределять по множеству различных страниц. Для очень больших записей это может потребовать использования сотен страниц для их хранения. Подход, основанный на связном списке, позволил бы реализовать такую фрагментацию, но движку Btrieve было бы сложно последовательно считывать записи. Поэтому, начиная с версии 6.1, в файле используется таблица, хранящая указатели на каждую страницу, составляющую запись данных. Эта таблица называется таблицей переменного хвостового распределения (VAT).
Индексирование
Btrieve использует формат b-дерева для хранения индексов записей по определенным столбцам таблицы. Индекс сопоставляет каждый набор значений индексируемых столбцов с набором уникальных идентификаторов строк, имеющих эти значения столбцов, что обеспечивает быстрый способ поиска строк в таблице по индексированному столбцу. B-деревья – это древовидные структуры данных, которые очень эффективны как механизм быстрого извлечения данных. Недостатком b-дерева является необходимость постоянной балансировки данных при их вставке в дерево, поэтому Btrieve хранит индекс записи в формате b-дерева только для сокращения времени, необходимого для вставки и обновления записей. Для каждого индекса в системе поддерживается отдельное b-дерево, а информация о корневом узле хранится в FCR. В Btrieve 6.x новый индекс можно создать при создании файла, либо добавить и удалить после создания файла. Индексные страницы создаются по мере необходимости. До Btrieve 6.0 существующие ключевые индексы нельзя было удалить, хотя дополнительные индексы можно было создавать и удалять по мере необходимости. Btrieve допускает дублирование ключевых значений в индексе. Btrieve обрабатывает дубликаты ключей, используя либо метод связанных дубликатов, либо метод повторяющихся дубликатов (эта терминология начала использоваться с выпуском версии 6.0). Метод связанных дубликатов использовал пару указателей на записи непосредственно на индексной странице для указания на начало и конец двусвязного списка дубликатов ключей. Это означало, что порядок дубликатов ключей в списке соответствовал порядку их ввода. Метод повторяющихся дубликатов не использовал связанный список, а делал все ключи уникальными, создавая новый индексный ключ и добавляя адрес указателя на запись в конец ключа. Это означает, что ключ извлекается по его порядковому номеру.
Обмен файлами
Когда Btrieve требовалось обеспечить совместный доступ к файлам для получения доступа к записям, можно было использовать два различных режима совместного использования файлов: режим Single Engine File Sharing (SEFS) и режим Multi Engine File Sharing (MEFS). В режиме SEFS изменять базу данных могли только клиенты, обращающиеся к данному движку, в то время как другие клиенты, использующие другой движок, не имели к ней доступа. MEFS позволяет различным клиентам, работающим под управлением разных движков, получать доступ к базе данных.
Конкуренция
Btrieve поддерживал одновременные транзакции, начиная с версии 6.x. До Btrieve 6.0 движок мог выполнять только блокировку на уровне файла или исключительную блокировку; начиная с версии 6.0, записи могли блокироваться по отдельности. Блокировка на уровне записи (или страницы) называлась одновременной блокировкой. Преимущества были очевидны: несколько клиентов могли одновременно получать доступ к файлу, если они не пытались изменить одну и ту же запись, что повышало производительность. Кроме того, другие клиенты могли читать заблокированные страницы и не видели бы изменений в файле, участвующем в операции записи, выполняемой другим процессом, который заблокировал эту запись. Режим MEFS не обеспечивал полной поддержки одновременной блокировки. Если клиент начинал одновременную транзакцию, а затем пытался выполнить операцию записи в запись, движок Btrieve возвращал код состояния 85, указывающий на то, что файл заблокирован, даже несмотря на использование одновременной блокировки.
Система и пользовательские транзакции
Начиная с версии 6.15 Btrieve, был представлен новый тип транзакций базы данных – системные транзакции, которые отделены от пользовательских. Пользовательские транзакции являются эксклюзивными и выполняются параллельно, в то время как системные транзакции представляют собой набор не транзакционных операций и/или пользовательских транзакций. Системные транзакции использовались исключительно для восстановления данных MKDE. Если системный сбой приводит к повреждению данных, то при перезапуске MKDE обнаруживает все файлы, для которых системная транзакция не была завершена успешно, и пытается их восстановить. Однако, поскольку пользовательские транзакции могли быть потеряны при откате последней системной транзакции, можно было установить параметр, который при получении запроса "End Operation" заставлял MKDE принудительно завершать системные транзакции, содержащие пользовательские транзакции.