是的,你可以这样做。
请注意,调度程序默认情况下是不活动的(请参阅事件调度程序配置),因此它不是零风险选项。例如,如果您的运营团队将您的应用程序迁移到新服务器,但忘记启用调度程序,您的应用程序将被淹没。还需要特殊权限,这可能需要在新服务器上再次设置。
我的建议:首先,创建一个处理定期分区维护的存储过程(参见下面的代码示例):如果表变得太大,则删除旧分区,并添加足够的新分区(例如 1 周),这样即使维护过程不是暂时不运行,您的应用程序不会死机。
然后冗余地安排对该存储过程的调用。使用 MySQL 调度程序,使用 cron 作业,并使用您喜欢的任何其他方式。然后,如果一个调度程序不工作,另一个调度程序可以填补空缺。如果您正确设计了存储过程,那么在不需要执行任何操作的情况下执行空操作应该很便宜。您甚至可能希望从您的应用程序中调用它,例如作为生成长期运行报告时的第一条语句,或者作为您日常 ETL 流程的一部分(如果您有的话)。我的观点是,计划任务的致命弱点是确保调度程序实际工作——所以在这里考虑冗余。
只要确保不要同时安排所有通话,这样他们就不会互相踩踏!:-)
这是您的维护过程可能看起来的代码示例——首先它修剪旧分区,然后添加新分区。我留下了错误检查和防止多个同时执行作为读者的练习。
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`UpdatePartitions` $$
CREATE PROCEDURE `test`.`UpdatePartitions` ()
BEGIN
DECLARE maxpart_date date;
DECLARE partition_count int;
DECLARE minpart date;
DECLARE droppart_sql date;
DECLARE newpart_date date;
DECLARE newpart_sql varchar(500);
SELECT COUNT(*)
INTO partition_count
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='Calls' AND TABLE_SCHEMA='test';
-- first, deal with pruning old partitions
-- TODO: set your desired # of partitions below, or make it parameterizable
WHILE (partition_count > 1000)
DO
-- optionally, do something here to deal with the parition you're dropping, e.g.
-- copy the data into an archive table
SELECT MIN(PARTITION_DESCRIPTION)
INTO minpart
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='Calls' AND TABLE_SCHEMA='test';
SET @sql := CONCAT('ALTER TABLE Calls DROP PARTITION p'
, CAST((minpart+0) as char(8))
, ';');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT COUNT(*)
INTO partition_count
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='Calls' AND TABLE_SCHEMA='test';
END WHILE;
SELECT MAX(PARTITION_DESCRIPTION)
INTO maxpart_date
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='Calls' AND TABLE_SCHEMA='test';
-- create enough partitions for at least the next week
WHILE (maxpart_date < CURDATE() + INTERVAL 7 DAY)
DO
SET newpart_date := maxpart_date + INTERVAL 1 DAY;
SET @sql := CONCAT('ALTER TABLE Calls ADD PARTITION (PARTITION p'
, CAST((newpart_date+0) as char(8))
, ' values less than('
, CAST((newpart_date+0) as char(8))
, '));');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT MAX(PARTITION_DESCRIPTION)
INTO maxpart_date
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='Calls' AND TABLE_SCHEMA='test';
END WHILE;
END $$
DELIMITER ;
顺便说一句,分区维护(确保提前创建新分区,修剪旧分区等)恕我直言,对于自动化至关重要。我个人见过一个大型企业数据仓库宕机一天,因为最初创建了一年的分区,但没有人记得在明年到来时创建更多分区。所以你在这里考虑自动化是非常好的——这对你正在从事的项目来说是个好兆头。:-)