简介本资源为Zabbix 7.0 LTS部署及数据库分区优化的操作记录文档面向运维工程师、监控系统管理员及需要处理Zabbix数据库性能瓶颈的技术人员。内容聚焦MySQL/MariaDB环境下历史记录与趋势表的分区方案针对housekeeper进程繁忙、旧数据删除效率低等常见痛点给出可落地的优化思路。资源包为1个PDF文件大小约835KB便于在数据库服务器或本地随时查阅。目前已有354人学习下载适合希望提升监控系统数据处理能力、降低维护成本的读者参考。文档围绕分区脚本的获取与执行、分区过程的自动调度、前端保留天数配置以及分区参数调整等环节展开并提示备份数据库、大型库执行耗时等注意事项可帮助读者理解分区机制并完成从部署到优化的完整实践。1. Zabbix 7.0 LTS 部署后第一刀为什么 housekeeper 总是 75% busyZabbix 7.0 LTS 装完前端能出图、告警能触发很多人就以为部署结束了。真正跑上一两周Zabbix housekeeper processes more than 75% busy这条告警会准时出现历史数据和趋势数据越堆越多MySQL/MariaDB 的 DELETE 语句开始拖慢整个库。Zabbix 把每个采集值写进 history 系列表把小时聚合写进 trends 系列表内务清理默认靠 DELETE 逐行删数据量一大就是灾难。这份操作记录解决的就是这个问题用 SQL 脚本给 Zabbix 的 history、trends 表做 RANGE 分区按小时或按天切表过期数据直接ALTER TABLE ... DROP PARTITION比 DELETE 快几个数量级。适合已经完成 Zabbix 7.0 LTS 部署、数据库是 MySQL 或 MariaDB、正在被 housekeeper 告警困扰的运维。脚本对 3.0 之后版本通用7.0 LTS 同样适用。下面按“脚本怎么落地 → 怎么自动跑 → 前端怎么配 → 坑在哪”一步步拆。2. 分区脚本落地从 zbx_db_partitiong.sql 到可调用的存储过程2.1 分区为什么能救 housekeeperZabbix 的数据生命周期里history 表存原始值trends 表存小时聚合min/avg/max。默认内务用DELETE FROM history WHERE clock ...清理InnoDB 要逐行标记删除、维护索引、写 undo几千万行下来 I/O 直接打满housekeeper 进程就卡在 75% 以上。分区把一张大表在物理上按clock范围切成多个小表。删除过期数据时DROP PARTITION是 DDL 操作直接丢弃整个分区文件不逐行扫描不产生大量 undo。创建新分区也是秒级。代价是分区键必须进主键或唯一索引Zabbix 的 history 表结构天然满足clock是范围列主键含 itemidclock所以改造阻力小。脚本里核心是四个存储过程partition_create建分区、partition_drop删过期分区、partition_verify检查并初始化分区、partition_maintenance按保留天数调度创建和删除。partition_maintenance_all则是对 history、history_log、history_str、history_text、history_uint、trends、trends_uint 七张表批量调用。2.2 下载脚本并确认保留天数先把脚本拉到数据库服务器上。注意脚本默认保留 7 天 history、365 天 trends如果你的合规或容量要求不同这一步就要改。# 下载并解压分区脚本 wget http://bestmonitoringtools.com/dl/zbx_db_partitiong.tar.gz tar -zxvf zbx_db_partitiong.tar.gz # 查看脚本内容确认保留天数 grep -n KEEP_DATA_DAYS\|partition_maintenance( zbx_db_partitiong.sql解压后得到zbx_db_partitiong.sql。脚本里partition_maintenance_all过程对 history 系列传的是 7 天、trends 系列传的是 365 天。要改就编辑这个文件把对应数字换掉再执行。参数含义第一个数字是保留天数第二个是分区粒度24 表示按小时切、每天 24 个分区第三个是预创建的未来分区数3 表示提前建 3 个。提示生产库执行前先mysqldump备份 zabbix 库。新装环境可跳过但只要有历史数据就别省这一步。2.3 执行脚本创建存储过程用 zabbix 库的账号密码把脚本灌进去脚本会创建上述存储过程不会立刻改表结构。# 语法mysql -u用户 -p密码 库名 脚本 mysql -u zabbix -pzabbixDBpass zabbix zbx_db_partitiong.sql新库上这条命令几秒完成大库上因为partition_verify首次要把已有表改造成分区表可能跑几小时期间别中断。执行完可以查一下过程是否建好-- 确认存储过程已创建 SELECT routine_name FROM information_schema.routines WHERE routine_schema zabbix AND routine_type PROCEDURE;看到partition_create、partition_drop、partition_verify、partition_maintenance、partition_maintenance_all就对了。此时表还没分区真正切表在下一步调用维护过程时发生。2.4 手动跑一次维护过程验证自动调度之前先手动调一次确认能正常建分区、删过期分区。mysql -u zabbix -pzabbixDBpass zabbix -e CALL partition_maintenance_all(zabbix);输出会是一串partition_create(zabbix,history,p202401010000,...)之类的消息表示分区已创建。然后验证 history 表结构SHOW CREATE TABLE history\G输出里应出现PARTITION BY RANGE (clock)和多个PARTITION p... VALUES LESS THAN (...)。如果还是普通表说明partition_verify没生效检查脚本是否完整执行、账号是否有 ALTER 权限。手动这一步跑通自动调度才有意义。3. 自动调度与前端联动让分区每天自己跑起来3.1 两条自动调度路线怎么选分区过程建好不会自己跑必须挂调度。两条路MySQL Event Scheduler 或系统 crontab。Event Scheduler 在数据库内部不依赖系统 cron推荐crontab 更直观适合 Event Scheduler 被禁用或权限受限的环境。两者选一个即可别同时挂否则同一时间两个调度抢着建删分区容易出并发问题。Event Scheduler 默认关闭先在 MySQL/MariaDB 配置里打开。配置文件位置因发行版而异MariaDB 常见在/etc/mysql/mariadb.conf.d/MySQL 在/etc/my.cnf.d/。[mysqld] event_scheduler ON改完重启数据库sudo systemctl restart mysql # 或 MariaDB sudo systemctl restart mariadb确认开启SHOW VARIABLES LIKE event_scheduler;Value 为 ON 即可。然后创建每 12 小时执行一次的事件CREATE EVENT zbx_partitioning ON SCHEDULE EVERY 12 HOUR DO CALL partition_maintenance_all(zabbix);12 小时后查执行情况SELECT event_name, last_executed, status FROM information_schema.events\Glast_executed有时间、status为 ENABLED 就说明在跑。3.2 crontab 方案与日志落盘如果走 crontab编辑 root 的定时任务加一行每天凌晨 3:30 执行并把输出重定向到日志便于排查。sudo crontab -e30 03 * * * /usr/bin/mysql -u zabbix -pzabbixDBpass zabbix -e CALL partition_maintenance_all(zabbix); /tmp/CronDBpartitiong.log 21日志文件/tmp/CronDBpartitiong.log会记录每次建删分区的消息。注意密码明文写在 crontab 里有泄露风险生产环境建议用~/.my.cnf配置[client]段存放凭据命令里去掉-p参数。3.3 Zabbix 前端内务必须同步改数据库分区和前端内务是两套清理逻辑必须对齐否则会出现“表没有值对应的分区”错误。进 Zabbix 前端管理 → 一般 → 管家。操作要点取消勾选“开启内部管家”下的历史记录和趋势清理勾选“覆盖监控项趋势期间”把历史和趋势的“数据存储期”天数设成和分区脚本一致默认 history 7 天、trends 365 天。点更新。天数不一致的后果很直接前端设 30 天、分区脚本只留 7 天第 8 天分区被删前端还在查 8~30 天的数据查询落空日志刷[Z3005] query failed: [1526] Table has no partition for value。所以两边数字必须一模一样。3.4 改保留天数新建过程而非重跑脚本上线后发现磁盘涨太快或合规要求留更久别重跑整个脚本。正确做法是新建一个带新天数的过程再让调度指向它。DELIMITER $$ CREATE PROCEDURE partition_maintenance_all_30and400(SCHEMA_NAME VARCHAR(32)) BEGIN CALL partition_maintenance(SCHEMA_NAME, history, 30, 24, 3); CALL partition_maintenance(SCHEMA_NAME, history_log, 30, 24, 3); CALL partition_maintenance(SCHEMA_NAME, history_str, 30, 24, 3); CALL partition_maintenance(SCHEMA_NAME, history_text, 30, 24, 3); CALL partition_maintenance(SCHEMA_NAME, history_uint, 30, 24, 3); CALL partition_maintenance(SCHEMA_NAME, trends, 400, 24, 3); CALL partition_maintenance(SCHEMA_NAME, trends_uint, 400, 24, 3); END$$ DELIMITER ;这里 history 改成 30 天、trends 改成 400 天。然后把事件指向新过程ALTER EVENT zbx_partitioning ON SCHEDULE EVERY 12 HOUR DO CALL partition_maintenance_all_30and400(zabbix);crontab 方案就注释旧行、加新行。旧过程留在库里不碍事需要回滚还能用。改完记得同步改前端内务的天数两边再次对齐。4. 避坑排查分区上线后最容易翻车的五件事4.1 现象日志刷 “Table has no partition for value”原因前端内务保留天数和分区脚本保留天数不一致或分区预创建数量不够新数据写入时没有对应分区。解决先核对两边天数再把partition_maintenance的第三个参数预创建分区数从 3 调大比如 5保证未来几小时/几天都有分区兜底。改完手动CALL partition_maintenance_all(zabbix)补建。4.2 现象housekeeper 告警没消失反而更忙原因前端“开启内部管家”没取消勾选DELETE 清理和分区 DROP 同时在跑两套逻辑打架。解决进前端管家页面取消历史记录和趋势的内部管家勾选只保留分区这一条清理路径。改完观察一个清理周期。4.3 现象大库执行脚本卡住几小时以为挂了原因partition_verify首次要把已有大表改造成分区表本质是一次全表重建数据量大就是慢。解决耐心等别中断中断可能留下半分区状态。选业务低峰期执行执行前确认磁盘有足够空间容纳重建期间的临时数据。4.4 现象Event Scheduler 显示 ON事件却不执行原因事件创建时ON SCHEDULE语法写错或数据库账号没有 EVENT 权限。解决查information_schema.events的 status若为 DISABLED 用ALTER EVENT ... ENABLE权限不足就GRANT EVENT ON zabbix.* TO zabbixlocalhost;。crontab 方案则检查 cron 服务是否运行、路径是否写全。4.5 现象分区建了但过期数据没删原因partition_drop按分区名里的日期和KEEP_DATA_DAYS比较如果分区名格式和脚本预期不符比如手工建过分区匹配不上就不删。解决查information_schema.partitions看分区名格式确保都是pYYYYMMDDHH00形式。手工建过的异常分区先手动 DROP 再让脚本接管。5. 验证与进阶怎么确认分区真的在按预期滚动分区上线不是跑通就完事得有一套验证习惯。我一般用三条 SQL 交叉确认。第一条看分区数量和最新分区边界SELECT table_name, partition_name, partition_description FROM information_schema.partitions WHERE table_schema zabbix AND table_name history ORDER BY partition_description DESC LIMIT 5;partition_description是 LESS THAN 的 unix 时间戳最新几个应该是未来时间说明预创建生效。第二条看数据是否落在合理分区SELECT PARTITION_NAME, TABLE_ROWS FROM information_schema.partitions WHERE table_schema zabbix AND table_name history;行数应集中在最近几个分区老分区行数为 0 或已被删。第三条看事件执行历史SELECT event_name, last_executed, interval_value, interval_field FROM information_schema.events WHERE event_name zbx_partitioning;last_executed应随时间推进。三条都对说明滚动正常。进阶一点可以把分区状态接进 Zabbix 自身监控写个 UserParameter 脚本查information_schema.partitions把分区总数、最老分区时间做成监控项配触发器——分区数异常增长或最老分区超过保留天数就告警。这样分区机制本身也被监控覆盖不会悄悄失效。还有个容易忽略的点history_uint和trends_uint在 7.0 LTS 里承载大量数值型监控项分区脚本对这两张表同样处理别只盯着 history 和 trends。验证时七张表都要看一遍任何一张漏了都会在对应数据类型上重新堆积。血泪经验是分区脚本改保留天数后前端内务天数忘了同步第二天日志就开始刷 1526 错误。从那以后我每次动分区参数都强制走一遍“改脚本 → 建新过程 → 改调度 → 改前端 → 查日志”五步一步不落。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?