3 Обновление базы данных для использования первичных ключей

Обзор

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

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

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

Начиная с Zabbix 6.0, первичные ключи используются для всех таблиц при новых установках.

Автоматического обновления базы данных для перехода на использование первичных ключей нет; однако, существующие установки можно обновить вручную после обновления сервера Zabbix до версии 6.0 или более новой.

Инструкции доступны для:

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

Важные примечания

Чтобы выполнить обновление базы данных:

  1. Остановите сервер Zabbix.

На время обновления настоятельно рекомендуется остановить сервер Zabbix Однако, в случае крайней необходимости существует способ выполнить обновление при работающем сервере (только для MySQL, MariaDB и PostgreSQL без TimescaleDB).

  1. Сделайте резервную копию базы данных.
  2. Запустите скрипты для вашей базы данных.
  3. Запустите сервер Zabbix.

Запустите скрипты только для базы данных сервера. Прокси-сервер не получит выгоды от этого обновления.

Если база данных использует партиционирование, обратитесь за помощью к администратору базы данных или в службу поддержки Zabbix.

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

При желании интерфейс Zabbix можно переключить в режим обслуживания.

MySQL

Экспорт и импорт необходимо выполнять в tmux/screen, чтобы гарантировать, что сеанс не будет прерван.

См. также: Важные примечания

MySQL 8.0+ с mysqlsh

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

  • Подключитесь к консоли MySQL как root (рекомендуемый вариант) или как любой пользователь с привилегиями FILE.

  • Запустите MySQL с активированной переменной local_infile.

  • Переименуйте старые таблицы и создайте новые таблицы путём запуска history_pk_prepare.sql.

mysql -uzabbix -p<пароль> zabbix < /usr/share/zabbix-sql-scripts/mysql/history_pk_prepare.sql
  • Сделайте экспорт и импорт данных.

Подключитесь через mysqlsh. При использовании сокет-подключения может потребоваться указать путь.

sudo mysqlsh -uroot -S /run/mysqld/mysqld.sock --no-password -Dzabbix

Выполните (CSVPATH может быть изменён, как нужно):

CSVPATH="/var/lib/mysql-files";
       
       util.exportTable("history_old", CSVPATH + "/history.csv", { dialect: "csv" });
       util.importTable(CSVPATH + "/history.csv", {"dialect": "csv", "table": "history" });
       
       util.exportTable("history_uint_old", CSVPATH + "/history_uint.csv", { dialect: "csv" });
       util.importTable(CSVPATH + "/history_uint.csv", {"dialect": "csv", "table": "history_uint" });
       
       util.exportTable("history_str_old", CSVPATH + "/history_str.csv", { dialect: "csv" });
       util.importTable(CSVPATH + "/history_str.csv", {"dialect": "csv", "table": "history_str" });
       
       util.exportTable("history_log_old", CSVPATH + "/history_log.csv", { dialect: "csv" });
       util.importTable(CSVPATH + "/history_log.csv", {"dialect": "csv", "table": "history_log" });
       
       util.exportTable("history_text_old", CSVPATH + "/history_text.csv", { dialect: "csv" });
       util.importTable(CSVPATH + "/history_text.csv", {"dialect": "csv", "table": "history_text" });

MariaDB/MySQL 8.0+ без mysqlsh

Этот метод обновления занимает больше времени и должен использоваться, только если обновление с mysqlsh невозможно.

Обновление таблиц
  • Подключитесь к консоли MySQL как root (рекомендуемый вариант) или любой пользователь с привилегиями FILE.

  • Запустите MySQL с активированной переменной local_infile.

  • Переименуйте старые таблицы и создайте новые таблицы путём выполнения history_pk_prepare.sql:

mysql -uzabbix -p<пароль> zabbix < /usr/share/zabbix-sql-scripts/mysql/history_pk_prepare.sql
Миграция с остановленным сервером

Параметр max_execution_time должен быть отключён перед миграцией данных во избежание тайм-аута во время миграции.

SET @@max_execution_time=0;
       
       INSERT IGNORE INTO history SELECT * FROM history_old;
       INSERT IGNORE INTO history_uint SELECT * FROM history_uint_old;
       INSERT IGNORE INTO history_str SELECT * FROM history_str_old;
       INSERT IGNORE INTO history_log SELECT * FROM history_log_old;
       INSERT IGNORE INTO history_text SELECT * FROM history_text_old;

Следуйте инструкциям по пост-миграции, чтобы удалить старые таблицы.

Миграция при работающем сервере

Проверьте, для каких путей разрешены импорт/экспорт:

mysql> SELECT @@secure_file_priv;
       +-----------------------+
       | @@secure_file_priv    |
       +-----------------------+
       | /var/lib/mysql-files/ |
       +-----------------------+

Если значение secure_file_priv является путём к папке, экспорт/импорт будут выполняться для файлов в этой папке. В этом случае, отредактируйте пути к файлам в запросах соответственно либо на время обновления выставьте значение secure_file_priv в пустую строку.

Если значение secure_file_priv пустое, экспорт/импорт могут выполняться из любого места.

Если значением secure_file_priv является NULL, выставьте его в путь, который содержит данные заэкспортированных таблиц ('/var/lib/mysql-files/' в примере выше).

Для более подробной информации, смотрите документацию MySQL [en].

Параметр max_execution_time должен быть отключён перед экспортом данных во избежание тайм-аута во время экспорта.

SET @@max_execution_time=0;
       
       SELECT * INTO OUTFILE '/var/lib/mysql-files/history.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_old;
       LOAD DATA INFILE '/var/lib/mysql-files/history.csv' IGNORE INTO TABLE history FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';
       
       SELECT * INTO OUTFILE '/var/lib/mysql-files/history_uint.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_uint_old;
       LOAD DATA INFILE '/var/lib/mysql-files/history_uint.csv' IGNORE INTO TABLE history_uint FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';
       
       SELECT * INTO OUTFILE '/var/lib/mysql-files/history_str.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_str_old;
       LOAD DATA INFILE '/var/lib/mysql-files/history_str.csv' IGNORE INTO TABLE history_str FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';
       
       SELECT * INTO OUTFILE '/var/lib/mysql-files/history_log.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_log_old;
       LOAD DATA INFILE '/var/lib/mysql-files/history_log.csv' IGNORE INTO TABLE history_log FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';
       
       SELECT * INTO OUTFILE '/var/lib/mysql-files/history_text.csv' FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n' FROM history_text_old;
       LOAD DATA INFILE '/var/lib/mysql-files/history_text.csv' IGNORE INTO TABLE history_text FIELDS TERMINATED BY ',' ESCAPED BY '"' LINES TERMINATED BY '\n';

Следуйте инструкциям по пост-миграции, чтобы удалить старые таблицы.

PostgreSQL

Экспорт и импорт должны выполняться в tmux/screen во избежание обрыва сессии. Для установок с TimescaleDB, пропустите этот раздел и перейдите к PostgreSQL + TimescaleDB.

Смотрите также: Важные примечания

Обновление таблиц

  • Переименуйте таблицы, используя history_pk_prepare.sql:
sudo -u zabbix psql zabbix < /usr/share/zabbix-sql-scripts/postgresql/history_pk_prepare.sql

Миграция с остановленным сервером

  • Сделайте экспорт текущей истории, импорт её во временную таблицу, затем вставку данных в новые таблицы, игнорируя дубликаты:
INSERT INTO history SELECT * FROM history_old ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       INSERT INTO history_uint SELECT * FROM history_uint_old ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       INSERT INTO history_str SELECT * FROM history_str_old ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       INSERT INTO history_log SELECT * FROM history_log_old ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       INSERT INTO history_text SELECT * FROM history_text_old ON CONFLICT (itemid,clock,ns) DO NOTHING;

Смотрите советы по повышению производительности операции INSERT ([en]): PostgreSQL: Bulk Loading Huge Amounts of Data, Checkpoint Distance and Amount of WAL.

Миграция при работающем сервере

  • Сделайте экспорт текущей истории, импорт её во временную таблицу, затем вставку данных в новые таблицы, игнорируя дубликаты:
\copy history_old TO '/tmp/history.csv' DELIMITER ',' CSV
       CREATE TEMP TABLE temp_history (
           itemid                   bigint                                    NOT NULL,
           clock                    integer         DEFAULT '0'               NOT NULL,
           value                    DOUBLE PRECISION DEFAULT '0.0000'          NOT NULL,
           ns                       integer         DEFAULT '0'               NOT NULL
       );
       \copy temp_history FROM '/tmp/history.csv' DELIMITER ',' CSV
       INSERT INTO history SELECT * FROM temp_history ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       \copy history_uint_old TO '/tmp/history_uint.csv' DELIMITER ',' CSV
       CREATE TEMP TABLE temp_history_uint (
           itemid                   bigint                                    NOT NULL,
           clock                    integer         DEFAULT '0'               NOT NULL,
           value                    numeric(20)     DEFAULT '0'               NOT NULL,
           ns                       integer         DEFAULT '0'               NOT NULL
       );
       \copy temp_history_uint FROM '/tmp/history_uint.csv' DELIMITER ',' CSV
       INSERT INTO history_uint SELECT * FROM temp_history_uint ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       \copy history_str_old TO '/tmp/history_str.csv' DELIMITER ',' CSV
       CREATE TEMP TABLE temp_history_str (
           itemid                   bigint                                    NOT NULL,
           clock                    integer         DEFAULT '0'               NOT NULL,
           value                    varchar(255)    DEFAULT ''                NOT NULL,
           ns                       integer         DEFAULT '0'               NOT NULL
       );
       \copy temp_history_str FROM '/tmp/history_str.csv' DELIMITER ',' CSV
       INSERT INTO history_str (itemid,clock,value,ns) SELECT * FROM temp_history_str ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       \copy history_log_old TO '/tmp/history_log.csv' DELIMITER ',' CSV
       CREATE TEMP TABLE temp_history_log (
           itemid                   bigint                                    NOT NULL,
           clock                    integer         DEFAULT '0'               NOT NULL,
           timestamp                integer         DEFAULT '0'               NOT NULL,
           source                   varchar(64)     DEFAULT ''                NOT NULL,
           severity                 integer         DEFAULT '0'               NOT NULL,
           value                    text            DEFAULT ''                NOT NULL,
           logeventid               integer         DEFAULT '0'               NOT NULL,
           ns                       integer         DEFAULT '0'               NOT NULL
       );
       \copy temp_history_log FROM '/tmp/history_log.csv' DELIMITER ',' CSV
       INSERT INTO history_log SELECT * FROM temp_history_log ON CONFLICT (itemid,clock,ns) DO NOTHING;
       
       \copy history_text_old TO '/tmp/history_text.csv' DELIMITER ',' CSV
       CREATE TEMP TABLE temp_history_text (
           itemid                   bigint                                    NOT NULL,
           clock                    integer         DEFAULT '0'               NOT NULL,
           value                    text            DEFAULT ''                NOT NULL,
           ns                       integer         DEFAULT '0'               NOT NULL
       );
       \copy temp_history_text FROM '/tmp/history_text.csv' DELIMITER ',' CSV
       INSERT INTO history_text SELECT * FROM temp_history_text ON CONFLICT (itemid,clock,ns) DO NOTHING;

PostgreSQL + TimescaleDB

Экспорт и импорт должны выполняться в tmux/screen во избежание обрыва сессии. Zabbix сервер должен быть остановлен на время обновления.

Смотрите также: Важные примечания

  • Переименуйте таблицы, используя history_pk_prepare.sql:
sudo -u zabbix psql zabbix < /usr/share/zabbix-sql-scripts/postgresql/history_pk_prepare.sql

Начиная с версии Zabbix 6.0.9, путь к history_pk_prepare.sql был изменён. Для версий более старых, чем 6.0.9, должна использоваться следующая команда:

sudo -u zabbix psql zabbix < /usr/share/doc/zabbix-sql-scripts/postgresql/history_pk_prepare.sql
  • Выполните скрипты миграции гипертаблиц TimescaleDB (совместимо с обеими версиями TSDB v2.x и v1.x), основываясь на настройках сжатия:
    • Если сжатие включено (при установке по умолчанию), выполните скрипты из папки /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression:

      cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression/history_pk.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression/history_pk_uint.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression/history_pk_log.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression/history_pk_str.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_with_compression/history_pk_text.sql | sudo -u zabbix psql zabbix
    • Если сжатие выключено, выполните скрипты из папки /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression:

      cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression/history_pk.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression/history_pk_uint.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression/history_pk_log.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression/history_pk_str.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/tsdb_history_pk_upgrade_no_compression/history_pk_text.sql | sudo -u zabbix psql zabbix

Смотрите также: Советы [en] для повышения производительности операций INSERT.

Oracle

Экспорт и импорт должны выполняться в tmux/screen во избежание обрыва сессии. Zabbix сервер должен быть остановлен на время обновления.

Смотрите также: Важные примечания

Обновление таблиц

Смотрите документацию [en] по Oracle Data Pump для советов по производительности.

  • Переименуйте таблицы, используя history_pk_prepare.sql:
cd /usr/share/zabbix/zabbix-sql-scripts/database/oracle
       sqlplus zabbix/password@oracle_host/service
       sqlplus> @history_pk_prepare.sql

Пакетная миграция таблиц истории

  • Подготовьте папки для Data Pump.

Data Pump должен иметь права на чтение и запись в эти папки.

Пример:

mkdir -pv /export/history
       chown -R oracle:oracle /export
  • Создайте объект папки и назначьте права на чтение и запись в этот объект пользователю, который используется для аутентификации Zabbix ('zabbix' в примере ниже). Под ролью sysdba, выполните:
create directory history as '/export/history';
       grant read,write on directory history to zabbix;
  • Сделайте экспорт таблиц. Замените N на желаемое количество потоков.
expdp zabbix/password@oracle_host/service \
           DIRECTORY=history \
           TABLES=history_old,history_uint_old,history_str_old,history_log_old,history_text_old \
           PARALLEL=N
  • Сделайте импорт таблиц. Замените N на желаемое количество потоков.
impdp zabbix/password@oracle_host/service \
           DIRECTORY=history \
           TABLES=history_uint_old \
        REMAP_TABLE=history_old:history,history_uint_old:history_uint,history_str_old:history_str,history_log_old:history_log,history_text_old:history_text \
           data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND  PARALLEL=N CONTENT=data_only

Индивидуальная миграция таблиц истории

  • Подготовьте папки для Data Pump для каждой таблицы истории. Data Pump должен иметь права на чтение и запись в эти папки.

Пример:

mkdir -pv /export/history /export/history_uint /export/history_str /export/history_log /export/history_text
       chown -R oracle:oracle /export
  • Создайте объект папки и назначьте права на чтение и запись этого объекта пользователю, который используется для аутентификации Zabbix ('zabbix' в примере ниже). Под ролью sysdba, выполните:
create directory history as '/export/history';
       grant read,write on directory history to zabbix;
       
       create directory history_uint as '/export/history_uint';
       grant read,write on directory history_uint to zabbix;
       
       create directory history_str as '/export/history_str';
       grant read,write on directory history_str to zabbix;
       
       create directory history_log as '/export/history_log';
       grant read,write on directory history_log to zabbix;
       
       create directory history_text as '/export/history_text';
       grant read,write on directory history_text to zabbix;
  • Выполните экспорт и импорт каждой таблицы. Замените N на желаемое количество потоков.
expdp zabbix/password@oracle_host:1521/xe DIRECTORY=history TABLES=history_old PARALLEL=N
       
       impdp zabbix/password@oracle_host:1521/xe DIRECTORY=history TABLES=history_old REMAP_TABLE=history_old:history data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND PARALLEL=N CONTENT=data_only
       
       expdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_uint TABLES=history_uint_old PARALLEL=N
       
       impdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_uint TABLES=history_uint_old REMAP_TABLE=history_uint_old:history_uint data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND PARALLEL=N CONTENT=data_only
       
       expdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_str TABLES=history_str_old PARALLEL=N
       
       impdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_str TABLES=history_str_old REMAP_TABLE=history_str_old:history_str data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND PARALLEL=N CONTENT=data_only
       
       expdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_log TABLES=history_log_old PARALLEL=N
       
       impdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_log TABLES=history_log_old REMAP_TABLE=history_log_old:history_log data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND PARALLEL=N CONTENT=data_only
       
       expdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_text TABLES=history_text_old PARALLEL=N
       
       impdp zabbix/password@oracle_host:1521/xe DIRECTORY=history_text TABLES=history_text_old REMAP_TABLE=history_text_old:history_text data_options=SKIP_CONSTRAINT_ERRORS table_exists_action=APPEND PARALLEL=N CONTENT=data_only

Пост-миграция

Для всех баз данных после завершения миграции сделайте следующее:

  • Проверьте, что всё работает, как ожидается.

  • Удалите старые таблицы:

DROP TABLE history_old;
       DROP TABLE history_uint_old;
       DROP TABLE history_str_old;
       DROP TABLE history_log_old;
       DROP TABLE history_text_old;