Журнал DDL-операций#

Журнал DDL-операций предназначен для регистрации изменений структуры базы данных, выполненных через DDL-команды PostgreSQL.

Журнал фиксирует:

  • создание объектов схемы;

  • изменение объектов схемы;

  • удаление объектов схемы.

Для каждой операции сохраняются:

  • время выполнения команды;

  • пользователь базы данных;

  • пользователь сессии PostgreSQL;

  • клиентская машина;

  • IP-адрес клиента;

  • схема;

  • объект;

  • тип объекта;

  • текст DDL-команды.

Форма просмотра реализована в Btk_DDLJournalAvi. Создание таблицы и функции записи выполняется через Btk_DDLJournalPkg.

Журнал доступен по пути: Настройка системы > Аудит > Журнал DDL-операций.

Интерфейс журнала#

Интерфейс журнала DDL-операций используется для просмотра зарегистрированных изменений структуры базы данных.

Форма представлена таблицей в режиме просмотра. Создание, редактирование и удаление записей из формы не предусмотрены.

В Btk_DDLJournal.avm.xml специальных фильтров нет. Обязательные фильтры также не заданы.

Список DDL-операций#

В основной таблице отображаются записи из таблицы aud.BTK_DDLJOURNAL.

Колонка

Описание

Таймштамп

Дата и время выполнения DDL-команды

Пользователь БД

Пользователь базы данных, выполнивший команду

Пользователь системы

Пользователь сессии PostgreSQL

Имя машины

Имя клиентской машины

IP-адрес

IP-адрес клиента

Схема

Схема базы данных, в которой выполнена команда

Сущность

Объект базы данных, к которому относится DDL-команда

Тип сущности

Тип объекта PostgreSQL

Текст DDL

Текст выполненной DDL-команды

Примечание

Для практической работы рекомендуется использовать стандартные фильтры грида по полям dTimeStamp, sSchema, sEntity, sDBUserName или sEntityType.

Настройка журнала#

Структура хранения создается install-скриптом Btk_DDLJournalPkg.pkg.xml.

Скрипт создает:

  • таблицу aud.BTK_DDLJOURNAL;

  • индексы по основным полям фильтрации;

  • PostgreSQL-функцию log_ddl_operations().

Запись событий выполняется не приложением, а event trigger в PostgreSQL. В install-скрипте команда создания триггера оставлена закомментированной:

CREATE EVENT TRIGGER ddl_audit_trigger
ON ddl_command_end
EXECUTE FUNCTION log_ddl_operations();

Это означает, что логирование DDL включается только после ручного создания event trigger в базе данных. Без него таблица и функция существуют, но новые DDL-события автоматически не записываются.

Для переноса старых данных предусмотрен метод Btk_DDLJournalPkg.migrateData(). Метод проверяет наличие старой таблицы public.Btk_DDLJournal и переносит записи в aud.BTK_DDLJOURNAL.

События формирования записей#

Записи формируются при завершении DDL-команды, если в базе создан и активен event trigger ddl_audit_trigger.

Журнал фиксирует команды, дошедшие до события PostgreSQL ddl_command_end.

Если trigger не создан или отключен, журнал не пополняется.

Если trigger активен, запись происходит на уровне базы данных независимо от способа выполнения операции:

  • через приложение;

  • напрямую через SQL;

  • через инструмент администрирования базы данных.

Через пользовательский интерфейс записи не создаются и не редактируются. В AVM для представления отключены операции вставки, удаления, редактирования карточки и сохранения формы.

Хранение данных#

Данные хранятся в таблице aud.BTK_DDLJOURNAL.

Одна строка соответствует одной DDL-команде, дошедшей до события ddl_command_end.

Функция log_ddl_operations() получает данные из текущего контекста PostgreSQL:

  • время события — через current_timestamp;

  • пользователя базы данных — через current_user;

  • пользователя сессии — через session_user;

  • имя клиентской машины — из pg_stat_activity.client_hostname;

  • IP-адрес — через inet_client_addr();

  • текущую схему — через current_schema();

  • тип и объект команды — из pg_event_trigger_ddl_commands();

  • текст команды — через current_query().

Для ускорения фильтрации создаются btree-индексы по полям:

  • sDBUserName;

  • sUserName;

  • sMachineName;

  • sIpAddress;

  • sSchema;

  • sEntity;

  • sEntityType.

Отдельного первичного ключа у таблицы в текущей структуре нет.

Хранимые поля#

Поле

Описание

dTimeStamp

Дата и время DDL-события

sDBUserName

Пользователь базы данных, выполнивший команду

sUserName

Пользователь сессии PostgreSQL

sMachineName

Имя клиентской машины из pg_stat_activity

sIpAddress

IP-адрес клиента

sSchema

Текущая схема в момент выполнения команды

sEntity

Объект, к которому относится DDL-команда

sEntityType

Тип объекта PostgreSQL

sDDL

Текст DDL-команды

В пользовательской форме эти же поля выводятся в таблице только для просмотра. Для dTimeStamp используется редактор даты и времени.

Программные интерфейсы#

Ключевая логика записи находится в PostgreSQL-функции log_ddl_operations(). Она формирует запись журнала и добавляет ее в aud.BTK_DDLJOURNAL.

В Btk_DDLJournalPkg есть метод migrateData(), который переносит данные из старой таблицы public.Btk_DDLJournal в новую таблицу aud.BTK_DDLJOURNAL.

Отдельных методов программной вставки или штатной очистки для этого журнала в коде нет.

Особенности эксплуатации#

Журнал ведется автоматически только после включения PostgreSQL event trigger.

Требования к безопасной настройке журналов, разграничению доступа, хранению и использованию журналов при расследовании инцидентов описаны в документе «Логирование, аудит и управление инцидентами», в разделах Защита журналов и Аудит пользовательской активности.

При выборе срока хранения учитывайте:

  • частоту миграций;

  • частоту автогенерации схемы;

  • объем текста DDL-команд;

  • количество DDL-событий при обновлениях системы.

Основной рост может давать поле sDDL, потому что оно хранит полный текст команды.

Для оценки объема рекомендуется анализировать:

  • количество записей по dTimeStamp за день, неделю и месяц;

  • распределение записей по sSchema, sEntityType и sDBUserName;

  • самые длинные значения sDDL;

  • фактический размер таблицы вместе с индексами.

Хранение и очистка#

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

Рекомендуемая настройка:

  • spClass = "aud.BTK_DDLJOURNAL";

  • npDeleteType = DeleteType.sqlDelete;

  • spAttrCreateDate = "dTimeStamp";

  • npDaysKeep — по регламенту, например 180 или 365 дней;

  • bpActive = 1.

SQL-эквивалент:

delete from aud.BTK_DDLJOURNAL
where dTimeStamp < current_timestamp - interval '365 days';