|
|
-- ============================================================
|
|
|
-- 自动分区与日志清理(幂等)
|
|
|
-- 1) 分区管理表 log_partition_tracker
|
|
|
-- 2) 存储过程 sp_ensure_partitions
|
|
|
-- 3) 存储过程 sp_check_partitions
|
|
|
-- 4) MariaDB 事件 ev_ensure_partitions
|
|
|
-- 注意:本脚本设计为幂等,重复执行不会重复创建分区
|
|
|
-- ============================================================
|
|
|
|
|
|
USE cnc_log;
|
|
|
|
|
|
-- 1. 分区追踪表
|
|
|
CREATE TABLE IF NOT EXISTS log_partition_tracker (
|
|
|
table_name VARCHAR(100) NOT NULL,
|
|
|
partition_name VARCHAR(50) NOT NULL,
|
|
|
partition_value VARCHAR(30) NOT NULL,
|
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
PRIMARY KEY (table_name, partition_name)
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
|
COMMENT='分区管理追踪表';
|
|
|
|
|
|
-- 2. 自动分区存储过程
|
|
|
DELIMITER $$
|
|
|
DROP PROCEDURE IF EXISTS sp_ensure_partitions$$
|
|
|
CREATE PROCEDURE sp_ensure_partitions()
|
|
|
BEGIN
|
|
|
-- 当前月的第一天
|
|
|
SET @base := DATE_FORMAT(CURDATE(), '%Y-%m-01');
|
|
|
SET @d1 := DATE_ADD(@base, INTERVAL 1 MONTH);
|
|
|
SET @d2 := DATE_ADD(@base, INTERVAL 2 MONTH);
|
|
|
SET @p1 := CONCAT('p', DATE_FORMAT(@d1, '%Y%m'));
|
|
|
SET @p2 := CONCAT('p', DATE_FORMAT(@d2, '%Y%m'));
|
|
|
|
|
|
-- 对 log_collect_analysis 表分区
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
|
|
|
WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p1) THEN
|
|
|
SET @dead1 := DATE_FORMAT(@d1, '%Y-%m-01');
|
|
|
SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_analysis ADD PARTITION (PARTITION ', @p1,
|
|
|
' VALUES LESS THAN (TO_DAYS(', '''', @dead1, '''', '))');
|
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_analysis', @p1, @dead1);
|
|
|
END IF;
|
|
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
|
|
|
WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p2) THEN
|
|
|
SET @dead2 := DATE_FORMAT(@d2, '%Y-%m-01');
|
|
|
SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_analysis ADD PARTITION (PARTITION ', @p2,
|
|
|
' VALUES LESS THAN (TO_DAYS(', '''', @dead2, '''', '))');
|
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_analysis', @p2, @dead2);
|
|
|
END IF;
|
|
|
|
|
|
-- 对 log_collect_cycle 表分区
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
|
|
|
WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p1) THEN
|
|
|
SET @dead1 := DATE_FORMAT(@d1, '%Y-%m-01');
|
|
|
SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_cycle ADD PARTITION (PARTITION ', @p1,
|
|
|
' VALUES LESS THAN (TO_DAYS(', '''', @dead1, '''', '))');
|
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_cycle', @p1, @dead1);
|
|
|
END IF;
|
|
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.PARTITIONS
|
|
|
WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p2) THEN
|
|
|
SET @dead2 := DATE_FORMAT(@d2, '%Y-%m-01');
|
|
|
SET @sql := CONCAT('ALTER TABLE cnc_log.log_collect_cycle ADD PARTITION (PARTITION ', @p2,
|
|
|
' VALUES LESS THAN (TO_DAYS(', '''', @dead2, '''', '))');
|
|
|
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
|
|
INSERT IGNORE INTO log_partition_tracker(table_name, partition_name, partition_value) VALUES ('log_collect_cycle', @p2, @dead2);
|
|
|
END IF;
|
|
|
END$$
|
|
|
DELIMITER ;
|
|
|
|
|
|
-- 3. 分区检查存储过程
|
|
|
DELIMITER $$
|
|
|
DROP PROCEDURE IF EXISTS sp_check_partitions$$
|
|
|
CREATE PROCEDURE sp_check_partitions()
|
|
|
BEGIN
|
|
|
-- 计算未来两月分区名是否存在
|
|
|
SET @base := DATE_FORMAT(CURDATE(), '%Y-%m-01');
|
|
|
SET @d1 := DATE_ADD(@base, INTERVAL 1 MONTH);
|
|
|
SET @d2 := DATE_ADD(@base, INTERVAL 2 MONTH);
|
|
|
SET @p1 := CONCAT('p', DATE_FORMAT(@d1, '%Y%m'));
|
|
|
SET @p2 := CONCAT('p', DATE_FORMAT(@d2, '%Y%m'));
|
|
|
|
|
|
SET @need := 0;
|
|
|
IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p1) = 0 THEN SET @need = 1; END IF;
|
|
|
IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p1) = 0 THEN SET @need = 1; END IF;
|
|
|
IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_analysis' AND PARTITION_NAME = @p2) = 0 THEN SET @need = 1; END IF;
|
|
|
IF (SELECT COUNT(*) FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = 'cnc_log' AND TABLE_NAME = 'log_collect_cycle' AND PARTITION_NAME = @p2) = 0 THEN SET @need = 1; END IF;
|
|
|
|
|
|
IF @need = 1 THEN
|
|
|
CALL sp_ensure_partitions();
|
|
|
END IF;
|
|
|
|
|
|
SELECT @need AS need_partition_creation;
|
|
|
END$$
|
|
|
DELIMITER ;
|
|
|
|
|
|
-- 4. MariaDB 事件:每月1日凌晨2:00执行 sp_check_partitions
|
|
|
SET GLOBAL event_scheduler = ON;
|
|
|
DROP EVENT IF EXISTS ev_ensure_partitions;
|
|
|
CREATE EVENT IF NOT EXISTS ev_ensure_partitions
|
|
|
ON SCHEDULE
|
|
|
EVERY 1 MONTH
|
|
|
STARTS TIMESTAMP '2026-06-01 02:00:00'
|
|
|
DO
|
|
|
CALL sp_check_partitions();
|