Mysql数据按天分区,定期删除
需求:
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数据按天分区,定期删除的更多相关文章
- MySQL数据表range分区例子
某些行业数据量的增长速度极快,随着数据库中数据量的急速膨胀,数据库的插入和查询效率越来越低.此时,除了程序代码和查询语句外,还得在数据库的结构上做点更改:在一个主读辅写的数据库中,当数据表数据超过10 ...
- mysql数据库主外键级联删除脚本RESTRICT --> CASCADE
在项目中,我们一般在数据库设计的时候做主外键关联设计,要么就不做.但是这样不符合规范,呵呵. 建立主外键关系的时候,默认是不能级联删除的.而出现往往在删除主表的数据时报错, 需要先删除从表然后再删除主 ...
- Hive管理表分区的创建,数据导入,分区的删除操作
Hive分区和传统数据库的分区的异同: 分区技术是处理大型数据集经常用到的方法.在Oracle中,分区表中的每个分区是一个独立的segment段对象,有多少个分区,就存在多少个相应的数据库对象.而在P ...
- mysql 数据表中查找、删除重复记录
为了性能考虑,在阅读之前提醒大家,如果有子查询,子查询查询到的数据最好不要超过总数据量的30%. 查询有重复数据的记录 select * from F group by a,b,c,d having ...
- MYSQL数据插入、更新及删除
上文讲到创建数据表,本文介绍create table后的数据插入: 一.通过insert into ...values...插入 insert into tablename (column1,colu ...
- mysql使用存储过程和event定期删除
-- 创建存储过程DELIMITER //CREATE PROCEDURE del_data()BEGIN DELETE FROM t_route_status WHERE route_date &l ...
- skymvc网站测试之mysql数据生成
skymvc网站测试之mysql数据生成 使用方法: 删除数据 /index.php?m=test_mysql&a=autoDelete 重置自增ID /index.php?m=test_my ...
- Mysql数据分片技术(一)——初识表分区
1. 为什么需要数据分片技术 2. 3种数据分片方式简述 3. 分片技术原理概述 4. 对单表分区的时机 1为什么需要数据分片技术 数据库产品的市场 在互联网行业内,绝大部分开发人员都会遇到数据表的性 ...
- es定期删除数据
es定期删除数据 1.定期删除索引 使用sentinl报警后,会产生大量如下索引,虽然不占空间,但时间久了也不好,故写个脚本定期删除 脚本如下: 1 #!/bin/bash 2 #只保留5天内的日志索 ...
随机推荐
- Spring cloud Eureka错误锦集(二)
最近学习spring cloud,在测试Eureka作为服务注册中心的时候碰到了问题,错误提示如下: "D:\Program\Java\JDK1.8\bin\java" -XX:T ...
- IntelliJ IDEA使用教程(简介)
最智能的IDE IDEA 全称IntelliJ IDEA 是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支 ...
- React性能优化记录(不定期更新)
React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...
- BZOJ3536 : [Usaco2014 Open]Cow Optics
枚举最后光线射到终点的方向,求出从起点出发以及从终点出发的光路,扫描线+树状数组统计交点个数即可. 注意当光路成环时,对应的两个方向应该只算一次. 时间复杂度$O(n\log n)$. #includ ...
- 2017.07.07【NOIP提高组】模拟赛B组
Summary 因为某种无法抗拒的原因,今天没有打比赛,所以也就没有那种心态.今天的题目有状压DP和二分,这套题不难也不简单,适中,适合我这种渣渣来做.在改题时,发现了许多问题.我连欧拉函数的计算都记 ...
- array中key所对应的value
获取数组中的键对应的值 class Test{ public function index(){ $info = array( 'name' => 'daicr', 'age' => 24 ...
- 3ds max学习笔记(三)--视点显示控制
显示模式:1.模型一般是以实体方式显示的,若想看线框方式,摁F3:返回实体,摁F3:2.实体加线框模式显示,摁F4:返回,摁F4:3.透明效果:ALT+X,透明显示,之后F4,显示线框:程序内的其他显 ...
- oracle函数返回结果集
一.用自定义类型实现 1.创建表对象类型. 在Oracle中想要返回表对象,必须自定义一个表类型,如下所示: create or replace type type_table is table of ...
- Sublime_SublimeServer
1. 遇到问题:如下代码第17行,获取本地json文件,如果直接在浏览器中打开引用该文件的.html文件,在chrme浏览器中并不能读取到json文件. var vm=new Vue({ el:&qu ...
- 4、css属性操作
前面说的主要是css的使用规则和选择器等,这篇主要讲解css的具体使用. 本篇导航: css text 背景属性 边框属性 列表属性 dispaly属性 外边距(margine)和内边距(paddin ...