Техническое описание СУБД databasetopit
Архитектура, функциональные возможности и внутреннее устройство
Данный документ описывает архитектуру, функциональные возможности и внутреннее устройство реляционной системы управления базами данных databasetopit. Разделы выстроены в хронологическом порядке, отражающем жизненный цикл обработки запроса: от сетевого взаимодействия до физической записи на диск.
1. Взаимодействие с сервером и API
Жизненный цикл любого запроса начинается на сетевом уровне. Система спроектирована по клиент-серверной архитектуре на основе протокола HTTP:
- REST API и JSON: HTTP-сервер (реализованный на базе
cpp-httplib) общается с клиентами, принимая и отправляя данные в формате JSON. Запросы маршрутизируются через эндпоинты/query,/login,/register,/text2sqlи др. - Сетевые настройки и IP-адресация: Сервер может быть запущен как локально (на
localhost/127.0.0.1с портом по умолчанию8080), так и на внешнем IP-адресе (например,0.0.0.0или публичном IP) для обслуживания удаленных клиентов по локальной сети или интернету. - Управление сессиями (State Management): Несмотря на то что HTTP является протоколом без сохранения состояния (stateless), сервер поддерживает строгий механизм сессий. При успешном логине клиенту возвращается уникальный
session_id, который кэшируется вunordered_mapв связке с текущим контекстом (current_user,current_db). Этот токен используется во всех последующих вызовах для прозрачной идентификации состояния.
2. Интеллектуальный транслятор Text2SQL
Если пользователь формулирует запрос на естественном языке, он перехватывается ИИ-модулем до этапа классического парсинга:
- Сбор контекста: Клиент отправляет текстовый запрос на специализированный эндпоинт
/text2sql. Сервер динамически агрегирует схему текущей базы данных пользователя (состав таблиц, связи и типы колонок) и формирует структурированный промпт. - Взаимодействие с ИИ: Сформированный промпт отправляется по защищенному каналу HTTPS к Mistral AI API (модель
mistral-small-latest). В ответ система получает JSON с готовым SQL-запросом, адаптированным под конкретную структуру БД. - Безопасность конфигурации: Ключ авторизации API (
MISTRAL_API_KEY) инжектируется строго через переменные окружения на стороне сервера. Это исключает компрометацию ключей на стороне клиентов (GUI).
3. Парсинг и синтаксис SQL (AST)
Полученный SQL-запрос проходит стадию лексического и синтаксического анализа:
- Абстрактное синтаксическое дерево (AST): Модуль синтаксического анализа четко разделен на
Lexer(разбиение запроса на токены) иParser. Парсер не выполняет запросы на лету, а строит AST (дерево выражений, напримерSelectStatement,BinaryExpression). Это архитектурно отделяет этап парсинга от этапа выполнения (в подсистемеExecutor). - Рекурсивный вычислитель выражений (Evaluation Engine): Движок
Executorсодержит встроенный рекурсивный интерпретатор, способный вычислять ветви AST любой степени вложенности. Он поддерживает ленивое вычисление (short-circuiting) для логических операторовANDиORи позволяет комбинировать математику, подзапросы и агрегации в сложных конструкциях (например,WHERE (a + b * 2) > (SELECT COUNT(*) FROM X)). - DDL: Поддержка создания таблиц с ограничениями
PRIMARY KEY,NOT NULL,UNIQUE,DEFAULT,FOREIGN KEY (REFERENCES ... ON DELETE/UPDATE CASCADE/SET NULL). Реализован механизм генерации суррогатных ключейAUTOINCREMENT. Поддержка изменения структуры черезALTER TABLE (ADD/DROP COLUMN). - Инспекция метаданных (SHOW): Реализовано семейство команд
SHOW(DATABASES,TABLES,COLUMNS,INDEX). Особая возможность —SHOW CREATE TABLE, реконструирующая валидный DDL-запрос "на лету" из бинарной схемы таблицы. - DQL / DML: Продвинутая фильтрация с предикатами
LIKE,BETWEEN,IS NULL,IN. Поддержка коррелированных подзапросов, конструкцийIN (SELECT ...)иEXISTS (SELECT ...). Поддержка математических операций. - Динамическая CURRENT_DATE: Встроена поддержка функции
CURRENT_DATE(), которую можно использовать как в выборках, так и в качестве значения по умолчанию (DEFAULT CURRENT_DATE). Движок динамически генерирует строкуYYYY-MM-DDприINSERT. - Агрегация и защита (Resource Guard): Вычисление
COUNT,SUM,AVG,MIN,MAXс использованиемGROUP BYиHAVING. СортировкаORDER BY, пагинация (LIMIT,OFFSET). Для защиты памяти от перегрузки любойSELECTбез явного указания лимита аппаратно ограничивается 100 записями (Default LIMIT 100).
4. Многопоточность и конкурентный доступ
Перед тем как движок начнет выполнять построенное AST-дерево, запрос проходит через подсистему блокировок:
- Изоляция потоков: HTTP-сервер обрабатывает входящие запросы параллельно в пуле потоков. Изоляция транзакционного контекста сессий обеспечивается за счет
thread_localпеременных (таких как состояние транзакцииtxn_active_и её IDcurrent_txn_id_). - Управление блокировками: На уровне движка реализован механизм конкурентного доступа с использованием
std::shared_mutex(db_rw_mutex_). Читающие транзакции (SELECT,SHOW) захватывают разделяемую блокировку (shared lock), позволяя выполнять запросы параллельно. Модифицирующие запросы захватывают эксклюзивную блокировку (exclusive lock), что предотвращает состояние гонки и обеспечивает сериализуемость доступа к общим ресурсам.
5. Ролевая модель и управление доступом (RBAC)
Получив необходимые права (блокировки) на доступ к структурам, движок валидирует права самого инициатора запроса:
- Секьюритизация данных: Пароли подвергаются одностороннему хэшированию алгоритмом SHA-256 (с применением криптографического модуля OpenSSL).
- Модель Ownership: Авторизация базируется на модели владения. Пользователь, создавший базу данных, регистрируется как её владелец и обладает полным спектром DDL и DML прав.
- Делегирование прав и роль Editor: Владельцы имеют возможность предоставлять доступ другим аккаунтам посредством команд
GRANT DDL ON <db> TO <user>и отзывать черезREVOKE DDL. По умолчанию выдача прав назначает пользователю системную рольeditor, которая позволяет выполнять любые модификации схемы данных и DML-запросы в рамках указанной базы, но не позволяет удалять саму базу данных (что доступно только владельцу или глобальномуadmin). - Self-hosting системных таблиц: Вся ролевая модель и метаданные (учетные записи
sys_users, владельцыsys_db_owners, выданные праваsys_db_grants) не хранятся в отдельных конфигурационных файлах. Они хранятся в точно таких же B+ деревьях внутри скрытой системной базыsystem. На них автоматически распространяются все гарантии ACID, Buffer Pool кэширование и механизм восстановления через WAL. - Строгая изоляция системного каталога: Несмотря на то, что метаданные лежат в обычных таблицах, обычный пользователь (даже с высокими привилегиями) не может выполнить команды вроде
DROP TABLE sys_users. На уровне ядра (Executor) реализована жесткая программная проверка: любые прямые DML и DDL модификации к базеsystemотклоняются с ошибкой доступа. Эта база модифицируется исключительно внутренними C++ процедурами при вызове команд управления (например,REGISTER,GRANT).
6. Архитектура хранилища и индексы
После прохождения проверок доступа начинается физическое исполнение запроса к данным:
- Постраничное хранение и точечные обновления (In-place Updates): В отличие от базовых файловых хранилищ, переписывающих файл целиком при модификации, данные здесь организованы в бинарные
.dbфайлы, разбитые на независимые страницы фиксированного размера (8 КБ). При выполненииUPDATEили `INSERT` система считывает, модифицирует и перезаписывает на диск только одну конкретную 8-килобайтную страницу, абсолютно не затрагивая остальной объем файла. МодульBufferPoolдополнительно кэширует эти страницы по алгоритму LRU, чтобы минимизировать физические обращения к диску. - Самоописываемые таблицы (Meta-page 0): Нулевая страница (
Page 0) каждого бинарного файла зарезервирована под метаданные. Она хранит ID корневого узла B-дерева и саму схему таблицы (бинарно сериализованный объектTableSchema). Благодаря этому каждый файл является самоописываемым (self-describing) — структуру колонок можно восстановить напрямую из файла данных без внешних словарей. - Механизм переиспользования памяти (Freelist): Для предотвращения бесконечного роста файлов на диске реализована система управления свободными страницами. При удалении данных пустые страницы не теряются, а заносятся в Freelist. При последующих вставках движок приоритетно переиспользует эти пустые участки внутри существующего
.dbфайла. - Структура Slotted Page и бинарный поиск: Линейное сканирование строк внутри 8-килобайтной страницы является неэффективным. Для оптимизации поиска реализован паттерн
Slotted Page: данные добавляются от начала страницы к центру, а массив слотов (указателей) — от конца к центру. Массив слотов упорядочен по ключу, что позволяет использовать бинарный поиск (O(log K)) внутри загруженной в память страницы, значительно повышая производительность поиска. - Кластеризованные индексы (B+ Tree): Физическое расположение строк в таблицах упорядочено согласно структуре B+ дерева по первичному ключу. Это гарантирует логарифмическую временную сложность O(log N) для операций точечного поиска, вставки и удаления.
- Вторичные индексы и составные ключи: Механизм
CREATE INDEXпозволяет создавать некластеризованные индексы. Для решения проблемы неуникальных значений (когда под один ключ во вторичном индексе попадает множество строк), вторичные индексы на системном уровне используют составной ключ вида[Значение_индекса, Primary_Key]. Поскольку Primary Key уникален, составной ключ также всегда уникален, что позволяет эффективно хранить любое количество дубликатов. - Оптимизатор Index Scan: Ядро выполнения запросов (
tryIndexScan) автоматически определяет возможность использования B+ дерева при наличии предикатовWHERE col = 'val'илиBETWEEN. При совпадении условий полное сканирование таблицы (Full Table Scan) заменяется на индексный поиск. - Оптимизация ORDER BY: Если в запросе присутствует
ORDER BYпо индексированной колонке, подсистемаExecutorизбегает ресурсоемкой сортировки в памяти (in-memory sort). Движок просто последовательно читает листовые узлы B+ дерева, снижая алгоритмическую сложность сортировки с O(N log N) до O(N). - Механизмы JOIN: В зависимости от наличия индексов на объединяемых колонках, подсистема
Executorмаршрутизирует выполнение соединения. При совпадении с PK или вторичным индексом применяется Index-Based Join. В остальных случаях (для equi-joins) используется Hash Join. Поддерживаются алгоритмыINNER,LEFT,RIGHT,FULLиCROSS.
7. Интеграция с CSV форматом
Один из специализированных видов запросов — пакетный импорт (обрабатывается так же через движок хранилища):
- Команда
LOAD CSV: Позволяет загружать данные из файла (синтаксисLOAD CSV 'path' INTO table [APPEND]). Парсер построчно считывает файл, выполняет приведение типов и проверку всех существующих ограничений (Constraints). Каждая добавленная строка маршрутизируется через механизм WAL для гарантии сохранения данных при сбое. - Расширение схемы через CSV: Команда
ALTER TABLE ADD COLUMN ... FROM CSV 'path'предоставляет механизм массового пополнения данных. Она позволяет добавить новый столбец в существующую таблицу и автоматически заполнить его значениями из CSV-файла, сопоставляя строки по первичному ключу. Механизм строго контролирует кардинальность и целостность, откатывая операцию при несовпадении ключей.
8. Типизация данных и формат хранения (CellValue / BLOB)
Физическое чтение и запись строк на страницы памяти строго типизированы:
- Тип CellValue: Значения ячеек представлены специальным классом
CellValue, реализованным какstd::optional<CellPrimitive>(гдеCellPrimitive— этоstd::variant<int64_t, double, bool, std::string>). Такая архитектура позволяет элегантно обрабатыватьNULLзначения (как пустойstd::optional) отдельно от пустых строк, а также обеспечивает type-safe операции и быстрые сравнения на уровне нативных типов C++ (int64_t,double) при сортировках и обходе B-деревьев. - Хранение BLOB и строк: Строковые значения (
TEXT,VARCHAR) и бинарные данные переменной длины сериализуются модулемrow_codec. Такие поля динамически упаковываются в конец бинарного представления записи, а в её фиксированной части сохраняются массивы смещений (offset arrays). Это обеспечивает компактное хранение на страницах и предоставляет быстрый O(1) доступ к любым колонкам (включая тяжелые BLOB-объекты) без необходимости десериализации всей строки при чтении.
9. Гарантии ACID и логирование (WAL)
Завершающий этап жизненного цикла транзакции — обеспечение надежности и сброс данных на диск:
- Atomicity и Durability: Для обеспечения атомарности и отказоустойчивости применяется механизм Write-Ahead Logging (WAL). Любые модификации строк предварительно фиксируются в логе перед изменением страниц данных. При вызове
COMMIT(или при достижении порога лога в 4 МБ) происходит принудительная синхронизация (fsync) WAL с диском. - Политика No-Force (Отложенная запись): Измененные данные 8-килобайтных страниц не записываются на диск сразу. Они помечаются в Buffer Pool как
dirty. На диск синхронизируется исключительно легковесный WAL-лог. Тяжелая бинарная страница будет сброшена на диск только тогда, когда кэш переполнится и её вытеснит алгоритм LRU. Это кардинально снижает износ диска и существенно повышает пропускную способность дляUPDATE-запросов. - Восстановление (Crash Recovery) и Откат (Undo): При инициализации сервера система считывает WAL и выполняет накат изменений (Redo). Для команды
ROLLBACKреализована сложная логическая отмена (Undo). При откате движок читает записи WAL в обратном порядке от конца к началу транзакции, игнорируя уже зафиксированные (COMMIT) или прерванные (ABORT) транзакции. Для каждой операции модификации генерируется и немедленно пишется в WAL компенсационная запись (Compensation Log Record —CLR_ROW_UPSERT,CLR_ROW_DELETE), после чего физические данные возвращаются к состоянию до начала транзакции. Это гарантирует целостность базы даже в случае аппаратного сбоя во время выполнения отката. - Consistency: Обеспечивается строгим контролем ссылочной целостности и ограничений столбцов (
FOREIGN KEY,UNIQUE,NOT NULL) в момент транзакции.
10. Клиентская часть и графический интерфейс (GUI)
Основной точкой взаимодействия пользователя с СУБД является полноценное кроссплатформенное десктопное приложение CaseChampGui, написанное на C# (Avalonia UI) с использованием архитектурного паттерна MVVM. Интерфейс разделен на логические модули и предоставляет следующие возможности:
- Умная авторизация и управление профилем:
- Экран входа поддерживает аутентификацию на удаленном сервере и создание локальных учетных записей. Есть функция кэширования сессий («Запомнить пароль на этом компьютере»).
- В настройках аккаунта пользователь может загрузить собственный аватар, задать отображаемое имя (псевдоним для UI) и безопасно изменить пароль на сервере.
- Настройка сетевого подключения:
- Специализированный раздел настроек (вызываемый через иконку на экране приветствия) позволяет переопределить целевой IP-адрес и порт. Это дает возможность GUI клиенту гибко переключаться между локальной СУБД для тестирования и удаленными production-узлами.
- Автозапуск сервера (Built-in Launcher):
- В настройках подключения встроен механизм автоматического пинга сервера при старте. Если удаленный или локальный
dbserverне отвечает, GUI способен автоматически запустить бинарный файл СУБД в фоновом режиме прямо рядом с проектом, избавляя от необходимости работы с терминалом.
- В настройках подключения встроен механизм автоматического пинга сервера при старте. Если удаленный или локальный
- Рабочее пространство SQL (Консоль):
- Многострочный редактор с визуальным выбором active базы данных в верхнем меню (автоматически выполняет
USE db). - Наличие кнопок истории запросов и функции Dry run (холостой прогон для безопасной проверки синтаксиса без изменения данных).
- Справа располагается Динамический обозреватель схемы (Schema Viewer): он в виде раскрывающихся списков показывает структуру таблиц и колонок текущей БД, обеспечивая контекст при написании кода.
- Многострочный редактор с визуальным выбором active базы данных в верхнем меню (автоматически выполняет
- Визуализатор данных (Таблицы):
- Отдельная вкладка для табличного просмотра (Read-only режим).
- Интерфейс динамически генерирует DataGrid-колонки (например,
employees.full_name,employees.salary) на основе неструктурированных JSON-ответов сервера. - Встроена удобная навигация: переключатель таблиц в нижней панели и элементы управления пагинацией (постраничный просмотр), а также кнопки обновления данных.
- Управление фильтрами: Пользователи могут устанавливать фильтры для отдельных столбцов через всплывающее меню. Сбросить active фильтры можно в один клик с помощью кнопки «х фильтры» в нижней панели управления.
- Два режима фильтрации:
- Классический: использование стандартных операторов сравнения (
=,>,<). - Text2SQL: позволяет ввести условие фильтрации на естественном русском языке (например, "старше 18 лет"). ИИ Mistral автоматически переведет этот текст в корректное выражение
WHEREдля текущей таблицы.
- Классический: использование стандартных операторов сравнения (
- Интеллектуальный помощник (Text2SQL):
- Выделенное окно для перевода естественного языка в запросы. Интерфейс показывает текущую схему базы, позволяя формулировать запросы с учетом контекста схемы (например, "покажи имена всех пользователей старше 25 лет").
- Кнопка «Перевести и выполнить» отправляет текст к ИИ и маршрутизирует сгенерированный SQL прямо в ядро БД.
- Продвинутое управление ключами ИИ:
- Пользователь настраивает стратегию ключей Mistral AI: можно использовать личный ключ, раздавать его другим локальным профилям на ПК (Share-режим) или принимать общие ключи.
- Инновационный Чат-режим SQL (Chat Mode):
- Специальный переключатель в настройках полностью меняет парадигму рабочей среды, превращая классическую SQL-консоль в интерфейс мессенджера.
- Запросы пользователя отправляются через строку ввода внизу экрана и отображаются в виде "пузырей" (bubbles) с правой стороны.
- Ответы базы данных появляются слева в хронологическом порядке с указанием времени (таймстемпами). Ошибки выводятся обычным текстом, а при успешном выполнении
SELECT-запроса прямо внутри ответного сообщения рендерится полноценная встроенная DataGrid-таблица с результатами выборки.
- Кастомизация и внешний вид:
- Приложение поддерживает смену системных тем оформления и детальную настройку UI: размер шрифта редактора (через слайдер), включение плавных анимаций.
- Реализован Компактный режим боковой панели (и опция автоматического сворачивания меню при узком экране), позволяющий освободить максимум пространства для работы с кодом и таблицами.