需求:

  1.日志表需要按天分区

  2.只保留一个月数据

方案:

  1.创建两个事件,一个事件生成未来需要的分区,另一个事件定期检查过期数据(移除分区)

  2.创建事件每小时执行一次,删除事件每天执行一次

  3.事件开始时需要先创建一个当前所需分区

全量方法:

  1.先构造存储过程 create_partition_today :将表转化为分区表,并将历史数据归集到该分区,未来数据则按天放置:

#alter table to partition table
DELIMITER $$
USE `dc_log`$$
DROP PROCEDURE IF EXISTS `create_partition_today`$$
CREATE PROCEDURE `create_partition_today`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
BEGIN
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME TIMESTAMP;
DECLARE DAYS_ENDTIME INT;
DECLARE PARTITIONNAME VARCHAR(16);
SET BEGINTIME = NOW();
SET ENDTIME = BEGINTIME + INTERVAL 1 DAY;
SET PARTITIONNAME = DATE_FORMAT(BEGINTIME, 'p%Y%m%d');
SET DAYS_ENDTIME = TO_DAYS(ENDTIME);
SET @SQL = CONCAT('ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' PARTITION BY RANGE (to_days(create_time))
(PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', DAYS_ENDTIME, '))');
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END$$
DELIMITER ;

  2.按天构造分区的存储过程create_partition_by_day:

#procedure of build partition of today and next day
DELIMITER $$
USE `dc_log`$$
DROP PROCEDURE IF EXISTS `create_partition_by_day`$$
CREATE PROCEDURE `create_partition_by_day`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
BEGIN
DECLARE ROWS_CNT INT UNSIGNED;
DECLARE BEGINTIME TIMESTAMP;
DECLARE ENDTIME TIMESTAMP;
DECLARE DAYS_ENDTIME INT;
DECLARE PARTITIONNAME VARCHAR(16);
SET BEGINTIME = NOW() + INTERVAL 1 DAY;
SET PARTITIONNAME = DATE_FORMAT(BEGINTIME, 'p%Y%m%d');
SET ENDTIME = BEGINTIME + INTERVAL 1 DAY;
SET DAYS_ENDTIME = TO_DAYS(ENDTIME);
SELECT COUNT(*)
INTO ROWS_CNT
FROM information_schema.partitions
WHERE table_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME;
IF ROWS_CNT = 0
THEN
SET @SQL = CONCAT('ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', DAYS_ENDTIME, '))');
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
ELSE
SELECT CONCAT("partition `", PARTITIONNAME, "` for table `", IN_SCHEMANAME, ".", IN_TABLENAME,
"` already exists") AS result;
END IF;
END$$
DELIMITER ;

  3.按天清除数据的存储过程clear_partition_by_day

DELIMITER $$
USE `dc_log`$$
DROP PROCEDURE IF EXISTS `clear_partition_by_day`$$
CREATE PROCEDURE `clear_partition_by_day`(IN_SCHEMANAME VARCHAR(64), IN_TABLENAME VARCHAR(64))
BEGIN
DECLARE NOWDAYS INT;
DECLARE Done INT;
DECLARE part VARCHAR(64);
DECLARE descr INT;
DECLARE rs CURSOR FOR SELECT
partition_name part,
partition_description descr
FROM information_schema.partitions
WHERE
table_schema = IN_SCHEMANAME
AND table_name = IN_TABLENAME;
/* 异常处理 */
DECLARE CONTINUE HANDLER FOR SQLSTATE '' SET Done = 1;
OPEN rs;
SET NOWDAYS = TO_DAYS(NOW());
FETCH rs into part,descr;
while Done is null DO
IF NOWDAYS - descr > 30
THEN
select descr AS cc;
SET @SQL = CONCAT('ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`',
' DROP PARTITION ', part);
select descr AS aa;
SELECT @SQL AS result;
select descr AS bb;
PREPARE STMT FROM @SQL;
EXECUTE STMT;
DEALLOCATE PREPARE STMT;
END IF;
FETCH rs into part,descr;
end WHILE;
CLOSE rs;
END$$
DELIMITER ;

  注意:以上过程有可能报错,这里记录两个错误:

  1.分区字段必须包含主键:

  这里采用的是事件字段作为分区字段,当然不可能是主键,所以再mysql中会报错,查阅资料大多说是因为分区表中不能保证数据唯一,需要将分区健纳入主键才可,不清楚原理.如果不愿意这样做也可以考虑,删除已有主键,无主键的表可以用任意字段作为分区字段

ALTER TABLE dc_system.service_push DROP PRIMARY KEY;

  2.时间字段不允许作为分区字段:

  这是因为 DATETIME 会受到时间区的影响,mysql里面分区的时间字段需要用CURRENT_TIMESTAMP

ALTER TABLE business_log
MODIFY create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

4.继续往下,打开事件变量,这里直接修改

SET GLOBAL event_scheduler = 'ON'; #打开

  重启后会被重置,如果需要永久修改,在my.cnf(mysql配置文件)中[mysqld]部分中添加下面内容,重启MYSQL

event_scheduler=ON

5.调用存储过程创建当天分区:

#created today's partition
CALL create_partition_today('dc_log', 'business_log');

6.创建事件:

DELIMITER $$
USE `dc_log`$$
CREATE EVENT IF NOT EXISTS `e_part_manage`
ON SCHEDULE EVERY 1 HOUR #every minute
STARTS '2018-05-01 18:27:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT 'Creating partitions'
DO BEGIN
CALL dc_log.create_partition_by_day('dc_log', 'business_log');
END$$
DELIMITER ; #event of clear data which out of date of 30 days
DELIMITER $$
USE `dc_log`$$
CREATE EVENT IF NOT EXISTS `clear_data`
ON SCHEDULE EVERY 1 DAY #every minute
STARTS '2018-05-01 15:58:51'
ON COMPLETION PRESERVE
ENABLE
COMMENT 'clearing data'
DO BEGIN
CALL clear_partition_by_day('dc_log', 'business_log');
END$$
DELIMITER ;

7.如果有其他表也需要如此处理,则先执行创建当天分区,再修改事件:

#service_push #same steps of table business_log
ALTER TABLE dc_system.service_push DROP PRIMARY KEY;
CALL create_partition_today('dc_system', 'service_push'); DELIMITER ;
DELIMITER $$
ALTER EVENT e_part_manage
DO BEGIN
CALL dc_log.create_partition_by_day('dc_log', 'business_log');
CALL dc_log.create_partition_by_day('dc_system', 'service_push');
END$$
DELIMITER ; DELIMITER $$
ALTER EVENT clear_data
DO BEGIN
CALL dc_log.clear_partition_by_day('dc_log', 'business_log') ;
CALL dc_log.clear_partition_by_day('dc_system', 'service_push');
END$$
DELIMITER ;

8.查看表的分区情况:

use dc_log;
SELECT
partition_name part,
partition_expression expr,
partition_description descr,
table_rows
FROM
INFORMATION_SCHEMA.partitions
WHERE
TABLE_SCHEMA = SCHEMA()
AND TABLE_NAME='service_push' ;

9.手动添加分区:

ALTER TABLE dc_log.all_log ADD PARTITION (PARTITION 'PARTITIONNAME' VALUES LESS THAN (TO_DAYS(now())));

10.查看事件和事件开关

show events;
SHOW VARIABLES LIKE 'event_scheduler';

done

Mysql数据按天分区,定期删除的更多相关文章

  1. MySQL数据表range分区例子

    某些行业数据量的增长速度极快,随着数据库中数据量的急速膨胀,数据库的插入和查询效率越来越低.此时,除了程序代码和查询语句外,还得在数据库的结构上做点更改:在一个主读辅写的数据库中,当数据表数据超过10 ...

  2. mysql数据库主外键级联删除脚本RESTRICT --> CASCADE

    在项目中,我们一般在数据库设计的时候做主外键关联设计,要么就不做.但是这样不符合规范,呵呵. 建立主外键关系的时候,默认是不能级联删除的.而出现往往在删除主表的数据时报错, 需要先删除从表然后再删除主 ...

  3. Hive管理表分区的创建,数据导入,分区的删除操作

    Hive分区和传统数据库的分区的异同: 分区技术是处理大型数据集经常用到的方法.在Oracle中,分区表中的每个分区是一个独立的segment段对象,有多少个分区,就存在多少个相应的数据库对象.而在P ...

  4. mysql 数据表中查找、删除重复记录

    为了性能考虑,在阅读之前提醒大家,如果有子查询,子查询查询到的数据最好不要超过总数据量的30%. 查询有重复数据的记录 select * from F group by a,b,c,d having ...

  5. MYSQL数据插入、更新及删除

    上文讲到创建数据表,本文介绍create table后的数据插入: 一.通过insert into ...values...插入 insert into tablename (column1,colu ...

  6. mysql使用存储过程和event定期删除

    -- 创建存储过程DELIMITER //CREATE PROCEDURE del_data()BEGIN DELETE FROM t_route_status WHERE route_date &l ...

  7. skymvc网站测试之mysql数据生成

    skymvc网站测试之mysql数据生成 使用方法: 删除数据 /index.php?m=test_mysql&a=autoDelete 重置自增ID /index.php?m=test_my ...

  8. Mysql数据分片技术(一)——初识表分区

    1. 为什么需要数据分片技术 2. 3种数据分片方式简述 3. 分片技术原理概述 4. 对单表分区的时机 1为什么需要数据分片技术 数据库产品的市场 在互联网行业内,绝大部分开发人员都会遇到数据表的性 ...

  9. es定期删除数据

    es定期删除数据 1.定期删除索引 使用sentinl报警后,会产生大量如下索引,虽然不占空间,但时间久了也不好,故写个脚本定期删除 脚本如下: 1 #!/bin/bash 2 #只保留5天内的日志索 ...

随机推荐

  1. 贪心,打表(或者快速幂), UVA - 11636

    题目链接: https://cn.vjudge.net/problem/34398/origin 题目比较简单,就是水题,基础贪心,大于所需的即可: AC代码: 打表: #include <cm ...

  2. Eclipse块选择快捷键

    快捷键:Shift+Alt+A 功能:可删除复制选中区域中的内容 效果图:

  3. [PA2014]Zadanie

    [PA2014]Zadanie 题目大意: 一棵\(n(n\le3\times10^5)\)个点的树,每个点上有\(a_i\)个人.树上所有人到\(i\)号点距离之和为\(b_i\).已知\(\{b_ ...

  4. git上传本地项目到github,方法2

    第一步:去github上创建自己的Repository,创建页面如下图所示: 填写相应信息后点击create即可 Repository name: 仓库名称 Description(可选): 仓库描述 ...

  5. vue环境配置 vue-cli脚手架

    vue 环境配置步骤: 第一步: 在官网下载node,Node  下载地址 http://nodejs.cn/ 并安装node.检测node是否安装成功, 按 “windows+r”  进入cmd命令 ...

  6. 学习Struts--Chap07:Struts2文件上传和下载

    1.struts2文件上传 1.1.struts2文件上传的基本概述 在开发web应用的时候,我们一般会为用户提供文件上传的功能,比如用户上传一张图像作为头像等.为了能上传文件,我们必须将表单的met ...

  7. js中函数对象创建的总结

    在JavaScript的函数对象创建方法中,可以分为三种情况: 1:第一种是使用function语句定义函数 <script type="text/javascript"&g ...

  8. python中@classmethod @staticmethod区别(转)

    pthon中3种方式定义类方法, 常规方式, @classmethod修饰方式, @staticmethod修饰方式. class A(object): def foo(self, x): print ...

  9. openstack 之~keystone之网关协议

    第一:静态页面和动态页面 上一篇博客介绍了HTTP后,我们知道一个web server的本质就是 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP ...

  10. Unity2017灯光烘焙知识点

    去研究一下灯光探针,性能可以提升不少.