4. Подготовка таблицы журнала аудита для партиционирования

Обзор

Некоторые базы данных (например, MySQL) требуют, чтобы столбец партиционирования был частью уникального ограничения таблицы (table's unique constraint). Поэтому для партиционирования таблицы auditlog по времени первичный ключ необходимо изменить с auditid на составной ключ auditid + clock.

В этом разделе приведены инструкции по изменению первичного ключа таблицы auditlog.

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

Изменение первичного ключа может быть ресурсоёмкой операцией, которая занимает много времени в зависимости от размера таблицы auditlog. Рекомендуется остановить сервер Zabbix и переключить веб-интерфейс Zabbix в режим обслуживания на время изменения. Однако, если это абсолютно необходимо, есть способ изменить первичный ключ без простоя (смотрите ниже).

Партиционирование таблицы auditlog может улучшить, например, процедуру очистки истории в больших инсталляциях.

Хотя очистка истории Zabbix в настоящее время не может использовать преимущества партиционированных таблиц (за исключением TimescaleDB), вы можете отключить очистку истории Zabbix и удалять партиции с помощью скриптов.

Начиная с версии Zabbix 7.0, таблица auditlog для TimescaleDB была преобразована в гипертаблицу, что позволяет администратору удалять данные по частям. Чтобы обновить существующую таблицу auditlog до гипертаблицы, смотрите Обновление схемы TimescaleDB.

MySQL

Важные замечания по перестроению индексов

MySQL автоматически перестраивает индексы для первичного ключа во время операции ALTER TABLE. Однако, чтобы обеспечить оптимальную производительность базы данных, настоятельно рекомендуется также вручную перестроить индексы с помощью оператора OPTIMIZE TABLE.

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

ANALYZE TABLE auditlog;
       SHOW TABLE STATUS LIKE 'auditlog';

Если доступное дисковое пространство вызывает беспокойство, следуйте инструкциям Изменение первичного ключа без простоя. Также доступны другие варианты:

  • Увеличение параметра MySQL sort_buffer_size [en] может помочь сократить использование дискового пространства при ручном перестроении индексов. Однако изменение этой переменной может повлиять на общее использование памяти базы данных.
  • Рассмотрите возможность освобождения места путем удаления потенциально ненужных данных.
  • Рассмотрите возможность уменьшения параметра очистки истории Период хранения данных (Data storage period) перед выполнением очистки истории.
Изменение первичного ключа с простоем

1. Удалите текущий первичный ключ таблицы auditlog и добавьте новый первичный ключ.

ALTER TABLE auditlog DROP PRIMARY KEY, ADD PRIMARY KEY (auditid, clock);

2. Перестройте индексы (необязательно, но настоятельно рекомендуется, смотрите Важные примечания по перестроению индексов).

OPTIMIZE TABLE auditlog;
Изменение первичного ключа без простоя

Здесь описан ручной метод изменения первичного ключа. В качестве альтернативы вы можете использовать набор инструментов pt-online-schema-change [en] от Percona. Этот набор инструментов автоматически выполняет следующие действия, а также минимизирует пространство, используемое для изменения таблицы auditlog.

1. Создайте новую таблицу с новым первичным ключом и создайте индексы.

CREATE TABLE `auditlog_new` (
         `auditid`            varchar(25)                               NOT NULL,
         `userid`             bigint unsigned                           NULL,
         `username`           varchar(100)    DEFAULT ''                NOT NULL,
         `clock`              integer         DEFAULT '0'               NOT NULL,
         `ip`                 varchar(39)     DEFAULT ''                NOT NULL,
         `action`             integer         DEFAULT '0'               NOT NULL,
         `resourcetype`       integer         DEFAULT '0'               NOT NULL,
         `resourceid`         bigint unsigned                           NULL,
         `resource_cuid`      varchar(25)                               NULL,
         `resourcename`       varchar(255)    DEFAULT ''                NOT NULL,
         `recordsetid`        varchar(25)                               NOT NULL,
         `details`            longtext                                  NOT NULL,
         PRIMARY KEY (auditid,clock)
       ) ENGINE=InnoDB;
       CREATE INDEX `auditlog_1` ON `auditlog_new` (`userid`,`clock`);
       CREATE INDEX `auditlog_2` ON `auditlog_new` (`clock`);
       CREATE INDEX `auditlog_3` ON `auditlog_new` (`resourcetype`,`resourceid`);

2. Поменяйте таблицы местами.

RENAME TABLE auditlog TO auditlog_old, auditlog_new TO auditlog;

3. Скопируйте данные из старой таблицы в новую.

INSERT INTO auditlog SELECT * FROM auditlog_old;

Это можно сделать частями (несколько операторов INSERT INTO с условиями WHERE clock по мере необходимости), чтобы избежать чрезмерного использования ресурсов.

4. Удалите старую таблицу.

DROP TABLE auditlog_old;

PostgreSQL

Важные замечания по перестроению индексов

PostgreSQL автоматически перестраивает индексы для первичного ключа во время операции ALTER TABLE. Однако, чтобы обеспечить оптимальную производительность базы данных, настоятельно рекомендуется также вручную перестроить индексы с помощью оператора REINDEX TABLE CONCURRENTLY.

Перестроение индексов может временно потребовать до трёхкратного дискового пространства, используемого индексами в данный момент. Чтобы получить текущий размер индексов, можно выполнить следующий запрос:

SELECT pg_size_pretty(pg_indexes_size('auditlog'));

Если доступное дисковое пространство вызывает беспокойство, следуйте инструкциям Изменение первичного ключа без простоя. Также доступны другие варианты:

  • Увеличение параметра PostgreSQL maintenance_work_mem [en] может помочь сократить использование дискового пространства при ручном перестроении индексов. Однако, изменение этой переменной может повлиять на общее использование памяти базы данных.
  • Если у вас есть другой диск или табличное пространство с большим свободным местом, вы можете рассмотреть возможность изменения временного места хранения для перестроения индекса. Вы можете задать параметр PostgreSQL temp_tablespaces [en], чтобы указать другое табличное пространство для временных объектов.
  • Рассмотрите возможность освобождения места путём удаления потенциально ненужных данных.
  • Рассмотрите возможность уменьшения параметра очистки истории Период хранения данных (Data storage period) перед выполнением очистки истории.
Изменение первичного ключа с простоем

1. Удалите текущий первичный ключ таблицы auditlog и добавьте новый первичный ключ.

ALTER TABLE auditlog DROP CONSTRAINT auditlog_pkey;
       ALTER TABLE auditlog ADD PRIMARY KEY (auditid,clock);

2. Перестройте индексы (необязательно, но настоятельно рекомендуется, смотрите Важные примечания по перестроению индексов).

REINDEX TABLE CONCURRENTLY auditlog;
Изменение первичного ключа без простоя

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

1. Создайте новую таблицу с новым первичным ключом и создайте индексы.

CREATE TABLE auditlog_new (
         auditid              varchar(25)                               NOT NULL,
         userid               bigint                                    NULL,
         username             varchar(100)    DEFAULT ''                NOT NULL,
         clock                integer         DEFAULT '0'               NOT NULL,
         ip                   varchar(39)     DEFAULT ''                NOT NULL,
         action               integer         DEFAULT '0'               NOT NULL,
         resourcetype         integer         DEFAULT '0'               NOT NULL,
         resourceid           bigint                                    NULL,
         resource_cuid        varchar(25)                               NULL,
         resourcename         varchar(255)    DEFAULT ''                NOT NULL,
         recordsetid          varchar(25)                               NOT NULL,
         details              text            DEFAULT ''                NOT NULL,
         PRIMARY KEY (auditid,clock)
       );
       CREATE INDEX auditlog_new_1 ON auditlog_new (userid,clock);
       CREATE INDEX auditlog_new_2 ON auditlog_new (clock);
       CREATE INDEX auditlog_new_3 ON auditlog_new (resourcetype,resourceid);

2. Поменяйте таблицы местами.

ALTER TABLE auditlog RENAME TO auditlog_old;
       ALTER TABLE auditlog_new RENAME TO auditlog;

3. Скопируйте данные из старой таблицы в новую.

INSERT INTO auditlog SELECT * FROM auditlog_old;

Это можно сделать частями (несколько операторов INSERT INTO с условиями WHERE clock по мере необходимости), чтобы избежать чрезмерного использования ресурсов.

4. Удалите старую таблицу.

DROP TABLE auditlog_old;

Oracle

Важные замечания по перестроению индексов

Oracle автоматически перестраивает индексы для первичного ключа во время операции ALTER TABLE. Однако, чтобы обеспечить оптимальную производительность базы данных, настоятельно рекомендуется также вручную перестроить индексы с помощью операторов ALTER INDEX <индекс> REBUILD PARALLEL.

Перестроение индексов может временно потребовать значительного дискового пространства.

Если доступное дисковое пространство вызывает беспокойство, следуйте инструкциям Изменение первичного ключа без простоя. Также доступны другие варианты:

  • Увеличение параметра Oracle SORT_AREA_SIZE [en] может помочь сократить использование дискового пространства при ручном перестроении индексов. Однако, изменение этой переменной повлияет на общее использование памяти базой данных.
  • Вы можете задать степень параллелизма с помощью предложения PARALLEL, например: ALTER INDEX auditlog_1 REBUILD PARALLEL 4
  • Рассмотрите возможность освобождения места путём удаления потенциально ненужных данных.
  • Рассмотрите возможность уменьшения параметра хранения истории Период хранения данных (Data storage period) перед выполнением очистки истории.
Изменение первичного ключа с простоем

1. Получите имя ограничения (constraint'а).

SELECT CONSTRAINT_NAME FROM all_constraints WHERE TABLE_NAME = 'AUDITLOG' AND CONSTRAINT_TYPE = 'P';

2. Удалите текущий первичный ключ таблицы auditlog и добавьте новый первичный ключ.

ALTER TABLE auditlog DROP CONSTRAINT <constraint_name>;
       ALTER TABLE auditlog ADD CONSTRAINT auditlog_pk PRIMARY KEY (auditid, clock);

3. Перестройте индексы (необязательно, но настоятельно рекомендуется, смотрите Важные замечания по перестроению индексов).

3.1. Получите имена индексов.

SELECT index_name FROM user_indexes WHERE table_name='AUDITLOG';

3.2. Перестройте каждый индекс.

ALTER INDEX auditlog_pk REBUILD PARALLEL;
       ALTER INDEX auditlog_1 REBUILD PARALLEL;
       ALTER INDEX auditlog_2 REBUILD PARALLEL;
       ALTER INDEX auditlog_3 REBUILD PARALLEL;
Изменение первичного ключа без простоя

1. Создайте новую таблицу с новым первичным ключом и создайте индексы.

CREATE TABLE auditlog_new (
         auditid              nvarchar2(25)                             ,
         userid               number(20)                                NULL,
         username             nvarchar2(100)  DEFAULT ''                ,
         clock                number(10)      DEFAULT '0'               NOT NULL,
         ip                   nvarchar2(39)   DEFAULT ''                ,
         action               number(10)      DEFAULT '0'               NOT NULL,
         resourcetype         number(10)      DEFAULT '0'               NOT NULL,
         resourceid           number(20)                                NULL,
         resource_cuid        nvarchar2(25)                             ,
         resourcename         nvarchar2(255)  DEFAULT ''                ,
         recordsetid          nvarchar2(25)                             ,
         details              nclob           DEFAULT ''                ,
         PRIMARY KEY (auditid,clock)
       );
       CREATE INDEX auditlog_new_1 ON auditlog_new (userid,clock);
       CREATE INDEX auditlog_new_2 ON auditlog_new (clock);
       CREATE INDEX auditlog_new_3 ON auditlog_new (resourcetype,resourceid);

2. Поменяйте таблицы местами.

ALTER TABLE auditlog RENAME TO auditlog_old;
       ALTER TABLE auditlog_new RENAME TO auditlog;

3. Скопируйте данные из старой таблицы в новую.

INSERT INTO auditlog SELECT * FROM auditlog_old;

Это можно сделать частями (несколько операторов INSERT INTO с условиями WHERE clock по мере необходимости), чтобы избежать чрезмерного использования ресурсов.

4. Удалите старую таблицу.

DROP TABLE auditlog_old;

Смотрите также