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)。

  1. 备份您的数据库。

如果使用 PostgreSQL 或 TimescaleDB,请参阅[已知 问题](/manual/installation/known_issues#database-restore-error-with-postgresqltimescaledb-after-upgrade-from-7. 0.0-7. 0.4),了解如何恢复在 Zabbix 7. 0.0-7. 0.4 中创建的 PostgreSQL 或 TimescaleDB 备份。

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

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

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

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

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

MySQL

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

另请参阅:重要说明

使用 mysqlsh 的 MySQL 8.0+

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

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

  • 启用 local_infile 变量后启动 MySQL。

  • 通过运行 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 身份(推荐)或任何具有 FILE 权限的用户登录 MySQL 控制台。

  • 如果在 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 性能的 13 个技巧

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
  • 创建一个目录对象,并将该对象的读写权限授予用于 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;
  • 对于 TimescaleDB,还需删除以下旧表:
DROP TABLE trends_old;

另请参阅