目的:解决mysql空间越来越大,mysql性能出现瓶颈,zabbix会无端出现大量agent超时报警
中间遇到一个mysql问题:5.1版本的mysql不支持分表(其实是支持的,需要重新编译mysql,加上参数--with-plugins=partition(支持分表功能)),最后升级mysql到5.6版本解决
 
1、修改两张表的结构:
use zabbix
Alter table history_text drop primary key, add index (id), drop index history_text_2, add index history_text_2 (itemid, id);
Alter table history_log drop primary key, add index (id), drop index history_log_2, add index history_log_2 (itemid, id);
 
2、导入存储过程(先别着急执行,可以往下看,保存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 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');
CALL partition_create(SCHEMA_NAME, TABLE_NAME, PARTITION_NAME, LESS_THAN_TIMESTAMP);
SET @__interval=@__interval+1;
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 ;
 
可以将这四个存储过程写成一个SQL文件直接导入:
/usr/local/mysql/bin/mysql  -uroot -p zabbix < partition_call.sql

完成上面四个存储过程后

3、使用存储过程
CALL partition_maintenance('<zabbix_db_name>', '<table_name>', <days_to_keep_data>, <hourly_interval>, <num_future_intervals_to_create>)
例如:mysql> CALL partition_maintenance('zabbix', 'history', 7, 24, 7);
zabbix_db_name:库名
table_name:表名
days_to_keep_data:保存多少天的数据
hourly_interval:每隔多久生成一个分区
num_future_intervals_to_create:本次一共生成多少个分区
这个例子就是history表最多保存7天的数据,每隔24小时生成一个分区,这次一共生成7个分区
 
4、下面这个存储过程就是统一调用
 

DELIMITER $$
CREATE PROCEDURE `partition_maintenance_all`(SCHEMA_NAME VARCHAR(32))
BEGIN
CALL partition_maintenance(SCHEMA_NAME, 'history', 31, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'history_log', 31, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'history_str', 31, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'history_text', 31, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'history_uint', 31, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'trends', 730, 24, 14);
CALL partition_maintenance(SCHEMA_NAME, 'trends_uint', 730, 24, 14);
END$$
DELIMITER ;

 

保存成文件,再次导入存储过程:

/usr/local/mysql/bin/mysql  -uroot -p'123456' zabbix < partition_all.sql
 
以后只需要调用这个存储过程就可以了,每天执行一次:
mysql -uzabbix -pzabbix zabbix -e "CALL partition_maintenance_all('zabbix');"

将上面这条命令写入到计划任务中如下:

01 01 * * * /opt/software/mysql/bin/mysql -uzabbix -pzabbix zabbix -e "CALL partition_maintenance_all('zabbix');"

zabbix-3.0.3 mysql表分区的方法的更多相关文章

  1. MySQL表分区技术

    MySQL表分区技术 MySQL有4种分区类型: 1.RANGE 分区 - 连续区间的分区 - 基于属于一个给定连续区间的列值,把多行分配给分区: 2.LIST 分区 - 离散区间的分区 - 类似于按 ...

  2. Mysql 表分区和性能

    以下内容节选自<Mysql技术内幕InnoDB存储引擎> mysql表分区: 分区功能并不是所有存储引擎都支持的,如CSV.MERGE等就不支持.mysql数据库支持的分区类型为水平分区( ...

  3. Mysql表分区的选择与实践小结

    在一些系统中有时某张表会出现百万或者千万的数据量,尽管其中使用了索引,查询速度也不一定会很快.这时候可能就需要通过分库,分表,分区来解决这些性能瓶颈. 一. 选择合适的解决方法 1. 分库分表. 分库 ...

  4. zabbix(4)数据库表分区优化

    一.zabbix 数据库存储 zabbix-server将采集到的数据存储在数据库(mysql.oracle等),而数据存储的大小与每秒处理的数量量有关,因此数据存储取决于以下两个因数: (1)Req ...

  5. Mysql 表分区

    是否支持分区:mysql> show variables like '%partition%';+-----------------------+-------+| Variable_name ...

  6. MySQL 表分区详解MyiSam引擎和InnoDb 区别(实测)

    一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了.如:某用户表的记录超过了1000万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区 ...

  7. mysql表分区、查看分区

    原文地址:http://blog.csdn.net/feihong247/article/details/7885199 一.       mysql分区简介 数据库分区 数据库分区是一种物理数据库设 ...

  8. mysql表分区简述

    一. 简介 数据库分区 数据库分区是一种物理数据库设计技术.虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减sql语句的响应时间,同时对于应用来说分区完全是 ...

  9. mysql 表分区技术

    表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分.从逻辑上看,只有一张表,但是底层却是由多个物理分区组成. 表分区有什么好处: a.分区表的数据可以分布在不同的物理设备上, ...

随机推荐

  1. 10 Minutes to pandas

    摘要   一.创建对象 二.查看数据 三.选择和设置 四.缺失值处理 五.相关操作 六.聚合 七.重排(Reshaping) 八.时间序列 九.Categorical类型   十.画图      十一 ...

  2. 关于百度编辑器UEditor的一点说明

    大家在使用的时候要特别注意editor_config.js中的“URL”这个参数 我的理解:1.这个参数是editor整个结构的总路径          2.首先要把这个路径配置好了.才能正常的显示, ...

  3. 关于安卓6.0权限申请 PermissionDog

    最近在一家公司实习,项目中需要用到适配安卓6.0以上的系统,我本来是想用其他人已经写好的权限申请框架来实现的,但是发现跟我的需求有点小区别,所以就自己写了一个 这个权限申请的帮助类很小,只有一个jav ...

  4. ASP.NET AntiXSS的作用

    XSS跨站脚本攻击        是指用户输入HTML编码对网站进行跨站攻击.            通过使用FCKeditor.FreeTextBox.Rich TextBox.Cute Edito ...

  5. 微信SDK开发——接口接入

    园子里面很多关于微信接口开发的文章,Github也一堆的开源代码. 官方文档地址:http://mp.weixin.qq.com/wiki/home/index.html 接下来主要以代码为主,接口说 ...

  6. Java 素数 prime numbers-LeetCode 204

    Description: Count the number of prime numbers less than a non-negative number, n click to show more ...

  7. 【分布式】Chubby与Paxos

    一.前言 在上一篇理解了Paxos算法的理论基础后,接下来看看Paxos算法在工程中的应用. 二.Chubby Chubby是一个面向松耦合分布式系统的锁服务,GFS(Google File Syst ...

  8. 匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的

    0x00 前言 由于工作繁忙所以距离上一篇博客已经过去一个多月的时间了,因此决心这个周末无论如何也得写点东西出来,既是总结也是分享.那么本文主要的内容集中在了委托的使用以及内部结构(当然还有事件了,但 ...

  9. LINQ to SQL语句(18)之运算符转换

    运算符转换 1.AsEnumerable:将类型转换为泛型 IEnumerable 使用 AsEnumerable<TSource> 可返回类型化为泛型 IEnumerable 的参数.在 ...

  10. MVC 传值

    1.ViewBag    Controller:ViewBag.Message = "Hello, Word";    View:@ViewBag.Message   注:View ...