问题现象
使用CentOS 9部署Zabbix 7.0使用一段时间后,查询历史数据时出现报错,Zabbix图形历史数据显示异常。并且Zabbix对接了Grafana,在Grafana历史图形中出现图像数据不连续的现象。
Zabbix前端Top hosts by CPU untilization显示红色告警框,告警内容如下:
Error in query [SELECT * FROM history_uint h WHERE h.itemid='42253' AND h.clock>1739060872 ORDER BY h.clock DESC,h.ns DESC LIMIT 1] [Index for table 'history_uint' is corrupt; try to repair it] [zabbix.php:17 → require_once() → ZBase->run() → ZBase->processRequest() → CController->run() → Widgets\TopHosts\Actions\WidgetView->doAction() → Widgets\TopHosts\Actions\WidgetView->getData() → Widgets\TopHosts\Actions\WidgetView->getitemValues() → CHistoryManager->getLastValues() → CHistoryManager->getLastValuesFromSqlWithPk() → DBselect() → trigger_error() in include/db.inc.php:243]
进入数据库检查表状态,表空间损坏丢失。
MariaDB [(none)]> use zabbix; MariaDB [zabbix]> check table history_uint; +---------------------+-------+----------+------------------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +---------------------+-------+----------+------------------------------------------------------------------------------+ | zabbix.history_uint | check | Error | Got error 194 "Tablespace is missing for a table" from storage engine InnoDB | | zabbix.history_uint | check | error | Corrupt | +---------------------+-------+----------+------------------------------------------------------------------------------+ 2 rows in set (0.000 sec)
修复方法
可以通过启用innodb_force_recovery临时模式启动数据库,删除损坏表并重建表结构即可修复history_uint表损坏问题。
1、停止Zabbix服务
[root@localhost ~]# systemctl stop zabbix-server
2、启用InnoDB强制恢复模式
编辑MySQL主配置文件/etc/my.cnf
[root@localhost ~]# vim /etc/my.cnf
在主配置文件中添加以下内容:
[mysqld]
innodb_force_recovery=1
3、重启数据库服务
[root@localhost ~]# systemctl stop mariadb.service
[root@localhost ~]# systemctl start mariadb.service
4、删除并重建history_uint表
进入数据库:
[root@localhost ~]# mysql -uroot -p
执行以下SQL语句:
USE zabbix;
DROP TABLE history_uint;CREATE TABLE `history_uint` (`itemid` bigint(20) unsigned NOT NULL,`clock` int(11) NOT NULL DEFAULT 0,`value` bigint(20) unsigned NOT NULL DEFAULT 0,`ns` int(11) NOT NULL DEFAULT 0,PRIMARY KEY (`itemid`,`clock`,`ns`)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
5、关闭恢复模式并重启数据库
删除/etc/my.cnf配置文件中新增的以下内容:
[mysqld]
innodb_force_recovery=1
重启数据库服务:
[root@localhost ~]# systemctl stop mariadb.service
[root@localhost ~]# systemctl start mariadb.service
6、启动Zabbix服务
[root@localhost ~]# systemctl start zabbix-server
至此,即可完成history_uint表损坏导致历史数据查询异常的问题。
脚本修复
1、创建一个名为zabbix_db_tools.sh的文件
vim zabbix_db_tools.sh
2、将以下内容复制到文件中,按下Esc键,然后按下Shift+:键,输入wq!保存
#!/bin/bash # =============================================== # Zabbix 数据库修复脚本 (history_uint 表损坏修复) # 使用前请确认运行用户有root权限 # ===============================================MYSQL_CONF="/etc/my.cnf" MYSQL_CMD="/usr/bin/mariadb -uroot" ZABBIX_DB="zabbix"echo "===============================" echo "开始执行 Zabbix 数据库修复流程..." echo "==============================="# Step 1: 停止 Zabbix 服务 echo "[1/10] 停止 Zabbix 服务..." systemctl stop zabbix-server 2>/dev/null systemctl stop zabbix-agent 2>/dev/null# Step 2: 启用 innodb_force_recovery echo "[2/10] 启用 innodb_force_recovery=1 ..." if grep -q "innodb_force_recovery" "$MYSQL_CONF"; thensed -i 's/^#\?\s*innodb_force_recovery=.*/innodb_force_recovery=1/' "$MYSQL_CONF" elsesed -i '/^\[mysqld\]/a innodb_force_recovery=1' "$MYSQL_CONF" fi# Step 3: 停止数据库服务 echo "[3/10] 停止 MariaDB 数据库..." systemctl stop mariadb.service# Step 4: 启动数据库(恢复模式) echo "[4/10] 启动 MariaDB (恢复模式)..." systemctl start mariadb.service sleep 3# Step 5-6: 删除并重建表 echo "[5/10] 连接数据库并修复表..." $MYSQL_CMD <<EOF USE $ZABBIX_DB; DROP TABLE IF EXISTS history_uint; CREATE TABLE \`history_uint\` (\`itemid\` bigint(20) unsigned NOT NULL,\`clock\` int(11) NOT NULL DEFAULT 0,\`value\` bigint(20) unsigned NOT NULL DEFAULT 0,\`ns\` int(11) NOT NULL DEFAULT 0,PRIMARY KEY (\`itemid\`,\`clock\`,\`ns\`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; EOF# Step 7: 禁用 innodb_force_recovery echo "[6/10] 禁用 innodb_force_recovery..." sed -i 's/^innodb_force_recovery/#innodb_force_recovery/' "$MYSQL_CONF"# Step 8-9: 重启数据库 echo "[7/10] 重启 MariaDB..." systemctl stop mariadb.service sleep 2 systemctl start mariadb.service sleep 3# Step 10: 启动 Zabbix 服务 echo "[8/10] 启动 Zabbix 服务..." systemctl start zabbix-server systemctl start zabbix-agentecho "===============================" echo "数据库修复完成!" echo "请登录 Zabbix 检查数据是否正常。" echo "==============================="
4、执行脚本进行修复
在脚本所在目录,执行脚本即可修复history_uint表损坏的问题。
sudo ./zabbix_db_tools.sh