3 数据库升级到主键

概述

本节提供了将现有安装中的表手动升级为使用主键的说明。

升级为主键可优化数据的索引和访问方式,从而可能加快查询速度并节省空间。 它还可改进集群环境中的数据管理和同步,有助于扩展,并确保即使部分服务器发生故障,系统仍能保持可靠。

本页提供的说明面向高级用户,可能需要根据您的具体配置进行调整。 升级为主键可能耗时较长且会大量占用资源。 请确保有足够的可用磁盘空间;根据数据库大小和存储的数据量,此过程最多可能需要达到当前历史表已用空间 2.5 倍的空间。

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

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

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

如果您使用的是 Zabbix 7.0(或更高版本),则这些表已使用双精度。 不过,仍可按照本页中的说明将表升级为主键,而不会影响已使用双精度的表。

如果您使用的是 Zabbix 6.4(或更早版本),建议先将表升级为双精度。 更多信息,请参见 Zabbix 7.0 文档中的升级为扩展范围的数值

可用说明包括:

重要说明

要执行数据库升级:

  1. 停止 Zabbix 服务器。

强烈建议在升级期间停止 Zabbix 服务器。 但是,如果确有必要,也可以在服务器运行时执行升级(仅适用于 MySQL、MariaDB,以及未使用 TimescaleDB 的 PostgreSQL)。

  1. 备份您的数据库。
  2. 安装与您的 Zabbix 版本兼容的最新 zabbix-sql-scripts 软件包(例如,对于 RHEL:dnf install zabbix-sql-scripts)。
  3. 运行适用于您的数据库的脚本。
  4. 启动 Zabbix 服务器。

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

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

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

可选地,可将 Zabbix 前端切换到维护模式

MySQL

导出和导入必须在 tmux/screen 中执行,以确保会话不会被丢弃。

另请参阅:重要说明

使用 mysqlsh 的 MySQL 8.0+

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

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

  • 启动 MySQL 时启用 local_infile 变量。

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

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

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

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

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

\js

然后运行下面的代码(可根据需要更改 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 模式。

MariaDB/MySQL 8.0+,不使用 mysqlsh

这种升级方式耗时更长,仅在无法使用 mysqlsh 升级时才应采用。

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

  • 如果在 Zabbix 服务器运行时执行迁移,请在启用 local_infile 变量的情况下启动 MySQL。

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

mysql -uzabbix -p<password> zabbix < /usr/share/zabbix/sql-scripts/mysql/option-patches/history_upgrade_prepare.sql
在服务器停止时迁移

在迁移数据之前,必须禁用 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;

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

在服务器运行时迁移

检查启用了导入/导出的路径:

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 文档MariaDB 文档

在导出数据之前,必须禁用 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

导出和导入必须在 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

在服务器停止时进行迁移

  • 导出当前历史数据,将其导入临时表,然后在忽略重复项的情况下将数据插入新表:
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 性能的提示,请参见:PostgreSQL: Bulk Loading Huge Amounts of DataCheckpoint 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_upgrade_prepare.sql 重命名表。

    • 如果已启用压缩(默认安装中已启用),请从 /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression 运行脚本:
      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 运行脚本:
      cat /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/without-compression/history_upgrade_prepare.sql | sudo -u zabbix psql zabbix
  • 根据压缩设置运行 TimescaleDB hypertable 迁移脚本:

    • 如果已启用压缩(默认安装中已启用),请从 /usr/share/zabbix/sql-scripts/postgresql/timescaledb/option-patches/with-compression 运行脚本:
      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 运行脚本:
      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

另请参见:提示,以提升 INSERT 性能。

迁移后

对于所有数据库,迁移完成后,请执行以下操作:

  • 验证一切是否按预期运行。

  • 删除旧表:

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;

另请参阅