3 数据库升级至主键

概述

本节提供有关如何在现有安装中手动将表升级为主键的说明。

将表升级为主键可以优化数据的索引和访问方式,这可能会加快queries的速度并节省空间。
它还可以在集群设置中改进数据管理和同步,帮助系统扩展,并确保即使某些服务器发生故障,系统仍保持可靠。

本页提供的说明适用于高级用户,可能需要根据您的特定配置进行调整。
升级到主键可能耗时且资源消耗较大。
请确保有足够的可用磁盘空间;根据您的数据库大小和存储的数据量,该过程可能需要高达历史表当前占用空间2.5倍的空间。

自Zabbix 6.0起,新安装的所有表均使用主键。

数据库不会自动升级到主键;但是,在将Zabbix server升级到6.0或更高版本之后,可以手动升级现有安装。

自Zabbix 7.0起,将表升级到主键的同时也会将表升级为使用双精度数据类型。



如果您使用的是Zabbix 7.0,表已经使用双精度。
但是,您仍可以按照本页上的说明将表升级为主键,而不会影响已经使用双精度的表。



如果您使用的是Zabbix 6.4(或更早版本),请考虑首先将表升级到双精度。
有关更多信息,请参见Upgrading to numeric values of extended range

支持以下数据库的说明:

重要说明

执行数据库升级:

1。停止 Zabbix server。

强烈建议在升级期间停止 Zabbix server。 但是,如果绝对必要,您可以在服务器运行时执行升级(仅适用于 MySQL、mariadb 和不带 TimescaleDB 的 PostgreSQL)。

2。备份您的数据库。

如果使用 PostgreSQL 或 TimescaleDB,请参阅已知 问题,了解如何恢复在 Zabbix 7.0.0-7.0.4 中创建的 PostgreSQL 或 TimescaleDB 备份。

3。安装与您的 Zabbix version 兼容的最新 zabbix-sql-scripts 包(例如,对于 RHEL:dnf install zabbix-sql-scripts)。 4。运行适用于您的数据库的脚本。 5。启动 Zabbix server。

仅对服务器数据库运行脚本。proxy 不会从此升级中受益。

如果数据库使用分区,请联系数据库管理员或 Zabbix 支持以获取帮助。

成功升级到主键后,可以删除 CSV 文件。

可选地,Zabbix 前端可以切换到 maintenance mode

MySQL

导出和 import 必须在 tmux/screen 中执行,以确保会话不会中断。

另请参阅:重要说明

使用mysqlsh的MySQL 8.0+

此方法可与正在运行的 Zabbix server 一起使用,但建议在升级期间停止服务器。
MySQL Shell(mysqlsh)必须已安装 installed 并能够连接到数据库。

  • 以 root 身份(推荐)或具有 FILE 权限的任意用户身份登录 MySQL 控制台。

  • 使用启用 local_infile 变量的方式启动 MySQL。

  • 通过运行 history_upgrade_prepare.sql 重命名旧表并 create 新表。

mysql -uzabbix -p<password> zabbix < /usr/share/zabbix-sql-scripts/mysql/option-patches/history_upgrade_prepare.sql
  • 导出并 import 数据。

通过 mysqlsh 连接。如果使用套接字连接,可能需要指定路径。

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

使用以下命令切换到 JavaScript 模式:

\js

然后 run 以下代码(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" });

如果收到消息 "JavaScript is not supported",说明您的 MySQL Shell 安装缺少 JS 支持。在这种情况下,请从 Oracle 官方安装 MySQL Shell package(或从源代码构建),以启用 JavaScript 模式。

不使用mysqlsh的MariaDB/MySQL 8.0+

此升级方法耗时较长,仅在无法使用 mysqlsh 升级时使用。

表升级
  • 以 root 用户(推荐)或具有 FILE 权限的任意用户身份登录 MySQL 控制台。

  • 启用 local_infile 变量启动 MySQL。

  • 通过运行 history_upgrade_prepare.sql 重命名旧表并create新表:

mysql -uzabbix -p<password> zabbix < /usr/share/zabbix-sql-scripts/mysql/option-patches/history_upgrade_prepare.sql

{HEADER_31011298}

在迁移数据之前必须禁用 max_execution_time(在 MySQL 中)或 max_statement_time(在 mariadb 中),以避免迁移过程中超时。

对于 MySQL:

SET @@max_execution_time=0;

对于 mariadb:

SET @@max_statement_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;

请按照迁移后说明删除旧表。

运行服务迁移

检查 import/export 启用的路径:

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

如果 secure_file_priv 的值是一个目录路径,则将对该目录中的文件执行 export/import。在这种情况下,请相应地编辑 queries 中的文件路径,或在升级期间将 secure_file_priv 的值设置为空字符串 string。

如果 secure_file_priv 的值为空,则可以从任意位置执行 export/import。

如果 secure_file_priv 的值为 NULL,请将其设置为包含导出表数据的路径(如上面示例中的 '/var/lib/mysql-files/')。

有关更多信息,请参阅 MySQL documentationMariaDB documentation

在导出数据之前必须禁用 max_execution_time(在 MySQL 中)或 max_statement_time(在 mariadb 中),以避免导出过程中超时。

对于 MySQL:

SET @@max_execution_time=0;

对于 mariadb:

SET @@max_statement_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

导出和import必须在 tmux/screen 中执行,以确保会话不会中断。
对于使用 TimescaleDB 的安装,请跳过本节并继续阅读 PostgreSQL + TimescaleDB

另请参阅:重要说明

表升级

  • 使用 history_upgrade_prepare.sql 重命名表:
sudo -u zabbix psql zabbix < /usr/share/zabbix-sql-scripts/postgresql/option-patches/history_upgrade_prepare.sql

停止服务迁移

  • 导出当前的历史数据,将其import到临时表中,
    然后将数据插入新表并忽略重复项:
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;

有关提高插入性能的提示,请参阅:PostgreSQL: Bulk Loading Huge Amounts of DataCheckpoint Distance and Amount of WAL

运行中的服务器迁移

  • 导出当前历史数据,将其import到临时表中, 然后将数据插入新表,同时忽略重复项:
\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

导出和import操作必须在tmux/screen会话中进行,以确保会话不会中断。 升级期间Zabbix server应处于关闭状态。

另请参阅:重要注意事项

  • 使用history_upgrade_prepare.sql重命名表:
    • 如果启用了压缩(默认安装情况下),从/usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression执行run脚本:

      cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
    • 如果禁用了压缩,从/usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression执行run脚本:

      cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
  • 根据压缩设置运行TimescaleDB超表迁移脚本:
    • 如果启用了压缩(默认安装情况下),从/usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression执行run脚本:

      cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_uint.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_log.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_str.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/history_upgrade_text.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/with-compression/trends_upgrade.sql | sudo -u zabbix psql zabbix
    • 如果禁用了压缩,从/usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression执行run脚本:

      cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_uint.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_log.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_str.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_text.sql | sudo -u zabbix psql zabbix
             cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb/option-patches/without-compression/trends_upgrade.sql | sudo -u zabbix psql zabbix

另请参阅:Tips以提升INSERT性能。

Oracle

自 Zabbix 7.0 起,不再推荐支持 Oracle DB。

导出和 import 必须在 tmux/screen 中执行,以确保会话不会中断。 升级期间 Zabbix server 应处于关闭状态。

另请参阅:重要说明

表升级

有关性能提示,请参阅 Oracle Data Pump documentation

  • 使用 history_upgrade_prepare.sql 重命名表。
cd /path/to/zabbix-sources/database/oracle/option-patches
       sqlplus zabbix/password@oracle_host/service
       sqlplus> @history_upgrade_prepare.sql

历史表的批量迁移

  • 准备 Data Pump 目录。

Data Pump 必须对这些目录具有读写权限。

示例:

mkdir -pv /export/history
       chown -R oracle:oracle /export
  • 创建目录 object 并向用于 Zabbix 认证的用户(如下例中的 'zabbix')授予对该 object 的读写权限。以 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
  • 创建一个目录 object 并向用于Zabbix认证的用户(如下例中的'zabbix')授予对该 object 的读写权限。在 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;
  • 导出并import每个表。将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;
  • 对于 TimescaleDB,还需删除以下旧表:
DROP TABLE trends_old;

另请参阅