zabbix mysql 表分区_zabbix5.0 mysql表分区

为解决Zabbix housekeeper报警及提升性能,本文介绍了如何清空并分区Zabbix MySQL数据库的history等大表。通过truncate命令删除历史数据,然后创建SQL文件进行表分区,包括创建、验证、维护和定时执行的存储过程,以实现自动分区管理。最终,检查分区效果并关闭Zabbix自带的清理功能。
摘要由CSDN通过智能技术生成

zabbix经常出现Zabbix housekeeper processes more than 75% busy报警,报警时WEB访问就变得很慢,尤其是加载历史数据的图形。

使用网上的调优设置,修改过housekeeper的进程和间隔时间,效果都不太理想。

0e086aaee5097e6625aec9608cf489d8.png

因此就按照网上的建议,做一下zabbix mysql的数据库表的分区吧。

使用mysql表分区来对history这种大表进行分区,但是一定要在数据量小的时候进行分区,当数据量达到好几十G设置几百G了还是采用第一种方法把数据清理了再作表分区。

我看了下我的数据,也是非常大。

[root@zabbix ~]# find /netzbxdb/ -type f -print0 | xargs -0 du -h | sort -rh | head -n 10

18G /netzbxdb/zabbix/history_uint.ibd

5.1G /netzbxdb/zabbix/history.ibd

2.1G /netzbxdb/zabbix/trends_uint.ibd

1.1G /netzbxdb/binlog.000051

1.1G /netzbxdb/binlog.000050

1.1G /netzbxdb/binlog.000049

过程不写了,最后做法是清空zabbix历史数据,再进行分区。

步骤如下吧!

1,使用truncate命令清空zabbix 所有监控数据

-------------------------------------------------------

truncate table history;

optimize table history;

-------------------------------------------------------

truncate table history_str;

optimize table history_str;

-------------------------------------------------------

truncate table history_uint;

optimize table history_uint;

-------------------------------------------------------

truncate table trends;

optimize table trends;

-------------------------------------------------------

truncate table trends_uint;

optimize table trends_uint;

-------------------------------------------------------

truncate table events;

optimize table events;

-------------------------------------------------------

注意:这些命令会把zabbix所有的监控数据清空,只是清空监控数据,添加的主机,配置,拓扑图不会丢失。如果对监控数据比较看重的话注意备份数据库

truncate是删除了表,然后根据表结构重新建立。

2,创建sql文件

[root@zabbix ~]# vim partition.sql

DELIMITER $$

CREATE PROCEDURE `partition_create`(SCHEMANAME varchar(64), TABLENAME varchar(64), PARTITIONNAME varchar(64), CLOCK int)

BEGIN

/*

SCHEMANAME = The DB schema in which to make changes

TABLENAME = The table with partitions to potentially delete

PARTITIONNAME = The name of the partition to create

*/

/*

Verify that the partition does not already exist

*/

DECLARE RETROWS INT;

SELECT COUNT(1) INTO RETROWS

FROM information_schema.partitions

WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND partition_description >= CLOCK;

IF RETROWS = 0 THEN

/*

1. Print a message indicating that a partition was created.

2. Create the SQL to create the partition.

3. Execute the SQL from #2.

*/

SELECT CONCAT( "partition_create(", SCHEMANAME, ",", TABLENAME, ",", PARTITIONNAME, ",", CLOCK, ")" ) AS msg;

SET @sql = CONCAT( 'ALTER TABLE ', SCHEMANAME, '.', TABLENAME, ' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', CLOCK, '));' );

PREPARE STMT FROM @sql;

EXECUTE STMT;

DEALLOCATE PREPARE STMT;

END IF;

END$$

DELIMITER ;

DELIMITER $$

CREATE PROCEDURE `partition_drop`(SCHEMANAME VARCHAR(64), TABLENAME VARCHAR(64), DELETE_BELOW_PARTITION_DATE BIGINT)

BEGIN

/*

SCHEMANAME = The DB schema in which to make changes

TABLENAME = The table with partitions to potentially delete

DELETE_BELOW_PARTITION_DATE = Delete any partitions with names that are dates older than this one (yyyy-mm-dd)

*/

DECLARE done INT DEFAULT FALSE;

DECLARE drop_part_name VARCHAR(16);

/*

Get a list of all the partitions that are older than the date

in DELETE_BELOW_PARTITION_DATE. All partitions are prefixed with

a "p", so use SUBSTRING TO get rid of that character.

*/

DECLARE myCursor CURSOR FOR

SELECT partition_name

FROM information_schema.partitions

WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND CAST(SUBSTRING(partition_name FROM 2) AS UNSIGNED) < DELETE_BELOW_PARTITION_DATE;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

/*

Create the basics for when we need to drop the partition. Also, create

@drop_partitions to hold a comma-delimited list of all partitions that

should be deleted.

*/

SET @alter_header = CONCAT("ALTER TABLE ", SCHEMANAME, ".", TABLENAME, " DROP PARTITION ");

SET @drop_partitions = "";

/*

Start looping through all the partitions that are too old.

*/

OPEN myCursor;

read_loop: LOOP

FETCH myCursor INTO drop_part_name;

IF done THEN

LEAVE read_loop;

END IF;

SET @drop_partitions = IF(@drop_partitions = "", drop_part_name, CONCAT(@drop_partitions, ",", drop_part_name));

END LOOP;

IF @drop_partitions != "" THEN

/*

1. Build the SQL to drop all the necessary partitions.

2. Run the SQL to drop the partitions.

3. Print out the table partitions that were deleted.

*/

SET @full_sql = CONCAT(@alter_header, @drop_partitions, ";");

PREPARE STMT FROM @full_sql;

EXECUTE STMT;

DEALLOCATE PREPARE STMT;

SELECT CONCAT(SCHEMANAME, ".", TABLENAME) AS `table`, @drop_partitions AS `partitions_deleted`;

ELSE

/*

No partitions are being deleted, so print out "N/A" (Not applicable) to indicate

that no changes were made.

*/

SELECT CONCAT(SCHEMANAME, ".", TABLENAME) AS `table`, "N/A" AS `partitions_deleted`;

END IF;

END$$

DELIMITER ;

DELIMITER $$

CREATE PROCEDURE `partition_maintenance`(SCHEMA_NAME VARCHAR(32), TABLE_NAME VARCHAR(32), KEEP_DATA_DAYS INT, HOURLY_INTERVAL INT, CREATE_NEXT_INTERVALS INT)

BEGIN

DECLARE OLDER_THAN_PARTITION_DATE VARCHAR(16);

DECLARE PARTITION_NAME VARCHAR(16);

DECLARE OLD_PARTITION_NAME VARCHAR(16);

DECLARE LESS_THAN_TIMESTAMP INT;

DECLARE CUR_TIME INT;

CALL partition_verify(SCHEMA_NAME, TABLE_NAME, HOURLY_INTERVAL);

SET CUR_TIME = UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d 00:00:00'));

SET @__interval = 1;

create_loop: LOOP

IF @__interval > CREATE_NEXT_INTERVALS THEN

LEAVE create_loop;

END IF;

SET LESS_THAN_TIMESTAMP = CUR_TIME + (HOURLY_INTERVAL * @__interval * 3600);

SET PARTITION_NAME = FROM_UNIXTIME(CUR_TIME + HOURLY_INTERVAL * (@__interval - 1) * 3600, 'p%Y%m%d%H00');

IF(PARTITION_NAME != OLD_PARTITION_NAME) THEN

CALL partition_create(SCHEMA_NAME, TABLE_NAME, PARTITION_NAME, LESS_THAN_TIMESTAMP);

END IF;

SET @__interval=@__interval+1;

SET OLD_PARTITION_NAME = PARTITION_NAME;

END LOOP;

SET OLDER_THAN_PARTITION_DATE=DATE_FORMAT(DATE_SUB(NOW(), INTERVAL KEEP_DATA_DAYS DAY), '%Y%m%d0000');

CALL partition_drop(SCHEMA_NAME, TABLE_NAME, OLDER_THAN_PARTITION_DATE);

END$$

DELIMITER ;

DELIMITER $$

CREATE PROCEDURE `partition_verify`(SCHEMANAME VARCHAR(64), TABLENAME VARCHAR(64), HOURLYINTERVAL INT(11))

BEGIN

DECLARE PARTITION_NAME VARCHAR(16);

DECLARE RETROWS INT(11);

DECLARE FUTURE_TIMESTAMP TIMESTAMP;

/*

* Check if any partitions exist for the given SCHEMANAME.TABLENAME.

*/

SELECT COUNT(1) INTO RETROWS

FROM information_schema.partitions

WHERE table_schema = SCHEMANAME AND table_name = TABLENAME AND partition_name IS NULL;

/*

* If partitions do not exist, go ahead and partition the table

*/

IF RETROWS = 1 THEN

/*

* Take the current date at 00:00:00 and add HOURLYINTERVAL to it. This is the timestamp below which we will store values.

* We begin partitioning based on the beginning of a day. This is because we don't want to generate a random partition

* that won't necessarily fall in line with the desired partition naming (ie: if the hour interval is 24 hours, we could

* end up creating a partition now named "p201403270600" when all other partitions will be like "p201403280000").

*/

SET FUTURE_TIMESTAMP = TIMESTAMPADD(HOUR, HOURLYINTERVAL, CONCAT(CURDATE(), " ", '00:00:00'));

SET PARTITION_NAME = DATE_FORMAT(CURDATE(), 'p%Y%m%d%H00');

-- Create the partitioning query

SET @__PARTITION_SQL = CONCAT("ALTER TABLE ", SCHEMANAME, ".", TABLENAME, " PARTITION BY RANGE(`clock`)");

SET @__PARTITION_SQL = CONCAT(@__PARTITION_SQL, "(PARTITION ", PARTITION_NAME, " VALUES LESS THAN (", UNIX_TIMESTAMP(FUTURE_TIMESTAMP), "));");

-- Run the partitioning query

PREPARE STMT FROM @__PARTITION_SQL;

EXECUTE STMT;

DEALLOCATE PREPARE STMT;

END IF;

END$$

DELIMITER ;

DELIMITER $$

CREATE PROCEDURE`partition_maintenance_all`(SCHEMA_NAME VARCHAR(32))

BEGIN

CALL partition_maintenance(SCHEMA_NAME, 'history', 90, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'history_log', 90, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'history_str', 90, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'history_text', 90, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'history_uint', 90, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'trends', 730, 24, 14);

CALL partition_maintenance(SCHEMA_NAME, 'trends_uint', 730, 24, 14);

END$$

DELIMITER ;

3,导入sql文件

[root@zabbix ~]# mysql -uzabbix -p123456 zabbix < partition.sql

4,添加计划任务

[root@zabbix ~]# crontab -e

#zabbix partition_maintenance

01 01 * * * mysql -uzabbix -p123456 zabbix -e"CALL partition_maintenance_all('zabbix')" &>/var/log/partition.log

注意: mysql的zabbix用户的密码部分按照实际环境配置

首次执行一次,确保已成功执行。

将crontab时间改为后1分钟,等待1分钟,再看log即可,比如现在是14:45,那就修改crontab如下:

[root@zabbix ~]# crontab -e

46 14 * * * mysql -uzabbix -p123456 zabbix -e"CALL partition_maintenance_all('zabbix')" &>/var/log/partition.log

5,检查分区是否成功

可以在/var/log/partition.log查看:

[root@zabbix ~]# cat /var/log/partition.log

d4b172f468bf8cae54998e02eaa7aa98.png

也可以登陆mysql,使用以下命令查看:

52d5366cbb2e9e78614ae99b32cf2dbe.png

最后,再检查一下mysql目录下的表文件,可以看到经过分区后的表的数据库文件由原来打个ibd文件变成了按照日期划分的多个ibd文件。

[root@zabbix zabbix]# ll -h | grep history

83354fd2d898770f6475617588ea021e.png

6,关闭zabbix再带的清理功能。

依次打开,管理—-一般—-设置—管家,取消图中标识的2处勾选。

1f728f1e4b4986a4da58556b372d60f9.png

至此,zabbix5.0 mysql表分区完成,本人亲测,zabbix5.0有效。

附:修改’partition_maintenance_all

show procedure status like ‘partition_maintenance%’ \G;

drop procedure partition_maintenance_all;

重新复制修改后的partition_maintenance_all

CALL partition_maintenance_all(‘zabbix’);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值