mysql 分区处理数据

记录一下分区代码:

1.建立存储过程,将原表按照时间转化为分区表,并建立当天分区

#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.建立存储过程,负责检查第二天的分区是否存在,如果不存在则建立

#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.为了避免数据无限量扩大,建立存储过程,负责清除30天前的分区表数据

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 '02000' 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 ;

4.这时候创建两个事件,负责按周期去执行建立分区和删除分区

#invoke event to create future partitions
#hour event of checking partition existed or not(invoke procedure every day)
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 18:27:30'
  ON COMPLETION PRESERVE
ENABLE
  COMMENT 'clearing data'
DO BEGIN
  CALL clear_partition_by_day('dc_log', 'business_log');
END$$
DELIMITER ;

5.如果事件没有运行,则可能是事件开关未开启

#turn event_scheduler on
SET GLOBAL event_scheduler = 'ON'; #打开

6.加入另外一张表操作,修改事件内容

#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');
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 ;
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 ;

done

 

posted @ 2018-05-06 22:00  但行好事-莫问前程  阅读(953)  评论(0编辑  收藏  举报