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.4+

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

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

  • 启动 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 模式。

不使用 mysqlsh 的 MariaDB/MySQL 8.4+

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

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

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

  • 运行 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 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

必须在 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

迁移正在运行的server

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

另请参阅