概述
Mysql不能自动创建分区,需要使用mysql event事件的方式自动创建分区,今天主要分享一下在MYSQL数据库应如何实现自动创建分区。
1、准备测试表及数据
CREATE TABLE `t1` ( `id` bigint(20) NOT NULL COMMENT 'id', `insert_user` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT 'Insert User', `insert_date` datetime NOT NULL COMMENT 'Insert Date', PRIMARY KEY (`id`,insert_date) USING BTREE, KEY `fsl_idx_order_release_insert_date` (`insert_date`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='test'/*!50500 PARTITION BY RANGE COLUMNS(insert_date)( PARTITION p202007 VALUES LESS THAN ('2020-08-01') ENGINE = InnoDB, PARTITION p202008 VALUES LESS THAN ('2020-09-01') ENGINE = InnoDB) */insert into t1 values (1,'hwb',now()),(1,'hwb2',now()+1),(1,'hwb3',now()+2);
![2d4bcd88f52d2bacee79a201110d4564.png](https://i-blog.csdnimg.cn/blog_migrate/0ded1120bdcef0c2975eb9de665d6cfd.jpeg)
2、相关存储过程
每次执行先校验当前分区是否存在,如果存在则不处理;不存在则创建
DELIMITER //#该表所在数据库名称USE `ycdb` // DROP PROCEDUREIFEXISTS `create_partition_by_month` // CREATE PROCEDURE `create_partition_by_month` ( IN_SCHEMANAME VARCHAR ( 64 ), IN_TABLENAME VARCHAR ( 64 ) ) BEGINDECLAREROWS_CNT INT UNSIGNED;DECLAREBEGINTIME TIMESTAMP;DECLAREENDTIME INT UNSIGNED;DECLAREPARTITIONNAME VARCHAR ( 16 );DECLAREENDTIME_DATETIME VARCHAR ( 30 );SET BEGINTIME = DATE( NOW( ) - INTERVAL DAY ( NOW( ) ) DAY + INTERVAL 1 DAY + INTERVAL 1 MONTH ); select BEGINTIME;SET PARTITIONNAME = DATE_FORMAT( BEGINTIME, 'p%Y%m' ); select PARTITIONNAME;SET ENDTIME = UNIX_TIMESTAMP( BEGINTIME + INTERVAL 1 MONTH );select endtime;SET ENDTIME_DATETIME = FROM_UNIXTIME( ENDTIME ); select ENDTIME_DATETIME;SELECTCOUNT( * ) INTO ROWS_CNT FROMinformation_schema.PARTITIONS WHEREtable_schema = IN_SCHEMANAME AND table_name = IN_TABLENAME AND partition_name = PARTITIONNAME;IFROWS_CNT = 0 THENSET @SQL = CONCAT( 'ALTER TABLE `', IN_SCHEMANAME, '`.`', IN_TABLENAME, '`', ' ADD PARTITION (PARTITION ', PARTITIONNAME, " VALUES LESS THAN ('", ENDTIME_DATETIME, "') ENGINE = InnoDB);" );PREPARE STMT FROM@SQL;EXECUTE STMT;DEALLOCATE PREPARE STMT;ELSE SELECTCONCAT( "partition `", PARTITIONNAME, "` for table `", IN_SCHEMANAME, ".", IN_TABLENAME, "` already exists" ) AS result;END IF;END //DELIMITER; --手动测试call create_partition_by_month("ycdb", "t1");
![ea839e069f851490142a492cd09e2852.png](https://i-blog.csdnimg.cn/blog_migrate/0035f819af6759f268e082468009f4e5.jpeg)
3、数据库定时任务(每小时执行一次)
每小时执行一次,检查下个月的表分区是否已经创建,如果没有创建,则调用上面的存储过程创建。
DELIMITER $$#该表所在的数据库名称USE `ycdb`$$CREATE EVENT IF NOT EXISTS `Month_partition_t1`ON SCHEDULE EVERY 1 hour #执行周期,还有天、月等等STARTS '2020-08-10 17:00:00'ON COMPLETION PRESERVEENABLECOMMENT 'Creating partitions By month'DO BEGIN #调用刚才创建的存储过程,第一个参数是数据库名称,第二个参数是表名称 CALL ycdb.create_partition_by_month("ycdb", "t1");END$$DELIMITER ;
![3d68b2e0911a74d728f6713b16306d94.png](https://i-blog.csdnimg.cn/blog_migrate/55f03d52692315010525c727e467ff02.jpeg)
如果没有执行,请检查Mysql是否开启了event(默认是关闭的)
[mysqld] event_scheduler=ON
后面会分享更多devops和DBA方面内容,感兴趣的朋友可以关注下~
![3eab605943b398b38e076e71f142bd8b.gif](https://i-blog.csdnimg.cn/blog_migrate/cf62e7afb1d85195201cf4af0bfabc1e.gif)