Skip to content

Файловая база данных

Roman TSovanyan edited this page Oct 31, 2017 · 3 revisions

Работа со встроенной файловой базой данных BoltDB

Работа с файловой базой данных в Гонце реализована с помощью библиотеки BoltDB.

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

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

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

Открытие базы данных

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

база = Новый ФайловаяБазаДанных
база.Открыть("test.db") // путь к файлу базы данных

Если файла еще не существует, то он создается, в противном случае, он открывается и блокируется платформой от изменения другими процессами. Если в пути к файлу не указана папка, то файл создается/открывается в рабочей папке работающего экземпляра платформы Гонец.

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

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

Транзакции

Любая работа с базой данных производится в транзакциях. Транзакции должны создаваться в тех горутинах, в которых они планируют использоваться. Нельзя передавать транзакции между горутинами. Одновременно можно открывать только одну транзакцию, в противном случае может возникнуть deadlock.

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

Начало транзакции гарантирует неизменность данных со стороны других горутин, в течение выполнения транзакции вплоть до отката или фиксации.

Открытие транзакции производится с помощью конструкции:

тран = база.НачатьТранзакцию(Истина) // Истина - для вида Чтение-Запись, Ложь - для вида Чтение

Транзакции всегда должны быть либо зафиксированы, либо отменены. В противном случае, база заблокируется для других горутин. Транзакции на чтение всегда только отменяются (при попытке зафиксировать будет выдаваться ошибка). Предпочтительно далее в коде использовать конструкцию Попытка-Исключение, чтобы отлавливать ошибки и откатывать транзакцию в этом случае:

тран = база.НачатьТранзакцию(Истина)
Попытка
  //...
  тран.ЗафиксироватьТранзакцию()
Исключение
  тран.ОтменитьТранзакцию()
  //...
КонецПопытки

Каждая транзакция обладает методами для работы с данными в базе данных:

  • таб = тран.Таблица("имя") - возвращает объект "Таблица", внутри которого производится работа с данными этой таблицы. Если таблицы нет в базе, то для транзакции вида Чтение-Запись она создается, а для вида Чтение - возникает ошибка-исключение. Поэтому, предпочтительным вариантом является ранний запуск транзакций Чтения-Записи и получение всех таблиц (своеобразная миграция), которые будут в дальнейшем исползованы в транзакциях Чтения.
  • тран.УдалитьТаблицу("имя") - полностью удаляет таблицу из базы данных
  • тран.ПолныйБэкап("имя файла") - делает полный бэкап базы данных в указанный файл

Работа с данными в таблицах

Каждая открытая таблица имеет методы:

  • значение, ok = таб.Получить(ключ) - получает значение по ключу (с учетом регистра). Если значение по ключу не найдено, то ok = Ложь, иначе Истина.
  • таб.Установить(ключ, значение) - устанавливает значение по ключу в таблице. Значение может быть структурой (со вложенными массивами и структурами), массивом (со вложенными массивами и структурами), числом, целым числом, строкой.
  • таб.Удалить(ключ) - удаляет значение по ключу из таблицы
  • ид = таб.СледующийИдентификатор() - получает следующий уникальный идентификатор для таблицы в виде числа. Его можно использовать в качестве ключа (дополнив нулями слева, через функцию Формат) или значения.
  • структ = таб.ПолучитьДиапазон(мин,макс) - находит и возвращает в виде структуры диапазон записей по ключам, расположенным между мин и макс значениями. Не забываем, что сравнение производится в виде стравнения ключей как строк UTF-8.
  • структ = таб.ПолучитьПрефикс(префикс) - находит и возвращает в виде структуры диапазон записей по ключам, имеющим префикс (левую часть), равный значению параметра префикс
  • структ = таб.ПолучитьВсе() - получает всю таблицу как структуру языка Гонец
  • таб.УстановитьСтруктуру(структ) - записывает содержимое структуры в таблицу (каждую пару ключ-значение). Отсутствующие в структуре, но, при этом, присутствующие в таблице пары ключ-значение, не удаляются.