需求:

  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. JAVA的8种基本数据类型和类型转换

    byte 字节型                        1字节(8bit) 初始值:0 char 字符型 2字节 空格 short 短整型 2字节 0 int 整形    4字节 0 long ...

  2. 第二章 STM32的结构和组成

    2.5 芯片里面有什么 STM32F103采用的是Cortex-M3内核,内核即CPU,由ARM公司设计. ARM公司并不生产芯片,而是出售其芯片技术授权. 芯片生产厂商(SOC)如ST.TI.Fre ...

  3. [jzoj]3777.最短路(shortest)

    Link https://jzoj.net/senior/#main/show/3777 Description 小Y最近学得了最短路算法,一直想找个机会好好练习一下.话虽这么说,OJ上最短路的题目都 ...

  4. mysql找安装路经,更改密码

    1:如果安装了mysql但是启动不了,可以到C:/Windows/System32的cmd.exe,用管理员身份打开,然后输入net strat mysql即可 2:忘记安装路经       sele ...

  5. pngcrush caught libpng error原因及解决方法

    报错信息: While reading /Users/zhangyanfeng/Desktop/程序/KeyBoardDemo/KeyBoardDemo/keyboard/KerboardResour ...

  6. PAT基础6-7

    6-7 统计某类完全平方数 (20 分) 本题要求实现一个函数,判断任一给定整数N是否满足条件:它是完全平方数,又至少有两位数字相同,如144.676等. 函数接口定义: int IsTheNumbe ...

  7. 【map离散&容斥】Ghosts @Codeforces Round #478 (Div. 2) D

    传送门 题意:给你一条直线的斜率a和截距b,和某一时刻n个在直线上的点的横坐标,以及沿坐标轴方向的速度.问你这些点在(-∞,+∞)的时间内的碰撞次数. solution 设两个点在t时刻相碰,有: x ...

  8. H5C301

    标题H5C301 1.html5 h5最新版本.所有主流浏览器都支持h5.但仅ie9及以上支持h5 改变了用户与文档的交互方式:多媒体 新增了其他的特性:语义,本地存储,网页多媒体 抛弃了不合理的标签 ...

  9. js扩展运算符(spread)三个点(...)

    常见用法: 1.该运算符主要用于函数调用. function push(array, ...items) { array.push(...items); } function add(x, y) { ...

  10. Android 模拟器启动不了-问题解决方案

    一.Android 模拟器启动不了问题解决方案 在安装Android开发环境时,首先安装java虚拟机,然后下载android adk 管理android虚拟机. 在完成工作后,添加android的虚 ...