feat(db): V15 为高频表添加 RANGE 月分区
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
-- Phase 1.5: 为高频表添加 MySQL RANGE 月分区(分区键 create_time)
|
||||
-- 架构设计文档:docs/architecture/2026-07-06-message-customer-interaction-design.md 第 2.6.2 节
|
||||
|
||||
-- ============================
|
||||
-- 1. mci_message_event(消息事件表)
|
||||
-- ============================
|
||||
-- 调整主键/唯一键,确保包含分区键 create_time
|
||||
ALTER TABLE mci_message_event
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (id, create_time),
|
||||
DROP INDEX uk_event_id,
|
||||
ADD UNIQUE KEY uk_event_id (event_id, create_time);
|
||||
|
||||
-- 改为 RANGE COLUMNS 月分区,并预创建 2026-07 至 2026-12 分区
|
||||
ALTER TABLE mci_message_event
|
||||
PARTITION BY RANGE COLUMNS(create_time) (
|
||||
PARTITION p202607 VALUES LESS THAN ('2026-08-01'),
|
||||
PARTITION p202608 VALUES LESS THAN ('2026-09-01'),
|
||||
PARTITION p202609 VALUES LESS THAN ('2026-10-01'),
|
||||
PARTITION p202610 VALUES LESS THAN ('2026-11-01'),
|
||||
PARTITION p202611 VALUES LESS THAN ('2026-12-01'),
|
||||
PARTITION p202612 VALUES LESS THAN ('2027-01-01'),
|
||||
PARTITION pfuture VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- ============================
|
||||
-- 2. mci_send_record(发送记录表)
|
||||
-- ============================
|
||||
ALTER TABLE mci_send_record
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (id, create_time),
|
||||
DROP INDEX uk_task_target,
|
||||
ADD UNIQUE KEY uk_task_target (task_id, conversation_id, person_id, create_time);
|
||||
|
||||
ALTER TABLE mci_send_record
|
||||
PARTITION BY RANGE COLUMNS(create_time) (
|
||||
PARTITION p202607 VALUES LESS THAN ('2026-08-01'),
|
||||
PARTITION p202608 VALUES LESS THAN ('2026-09-01'),
|
||||
PARTITION p202609 VALUES LESS THAN ('2026-10-01'),
|
||||
PARTITION p202610 VALUES LESS THAN ('2026-11-01'),
|
||||
PARTITION p202611 VALUES LESS THAN ('2026-12-01'),
|
||||
PARTITION p202612 VALUES LESS THAN ('2027-01-01'),
|
||||
PARTITION pfuture VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- ============================
|
||||
-- 3. mci_conversation(会话表,可选但推荐)
|
||||
-- ============================
|
||||
-- MySQL 不支持外键与分区共存,因此需要先删除与会话表相关的外键约束。
|
||||
-- 这些外键属于数据库级完整性约束,应用层(MyBatis-Plus)不依赖它们。
|
||||
ALTER TABLE mci_conversation_participant
|
||||
DROP FOREIGN KEY fk_participant_conversation_id;
|
||||
|
||||
ALTER TABLE mci_channel_account_conversation
|
||||
DROP FOREIGN KEY fk_binding_conversation_id;
|
||||
|
||||
ALTER TABLE mci_conversation_tag_binding
|
||||
DROP FOREIGN KEY fk_conv_tag_conversation_id;
|
||||
|
||||
ALTER TABLE mci_conversation
|
||||
DROP FOREIGN KEY fk_conversation_owner_account;
|
||||
|
||||
ALTER TABLE mci_conversation
|
||||
DROP FOREIGN KEY fk_conversation_subject_id;
|
||||
|
||||
-- 调整主键/唯一键,确保包含分区键 create_time
|
||||
ALTER TABLE mci_conversation
|
||||
DROP PRIMARY KEY,
|
||||
ADD PRIMARY KEY (id, create_time),
|
||||
DROP INDEX uk_tenant_channel_conv,
|
||||
ADD UNIQUE KEY uk_tenant_channel_conv (tenant_code, channel_type, channel_conversation_id, deleted, create_time);
|
||||
|
||||
ALTER TABLE mci_conversation
|
||||
PARTITION BY RANGE COLUMNS(create_time) (
|
||||
PARTITION p202607 VALUES LESS THAN ('2026-08-01'),
|
||||
PARTITION p202608 VALUES LESS THAN ('2026-09-01'),
|
||||
PARTITION p202609 VALUES LESS THAN ('2026-10-01'),
|
||||
PARTITION p202610 VALUES LESS THAN ('2026-11-01'),
|
||||
PARTITION p202611 VALUES LESS THAN ('2026-12-01'),
|
||||
PARTITION p202612 VALUES LESS THAN ('2027-01-01'),
|
||||
PARTITION pfuture VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
|
||||
-- ============================
|
||||
-- 4. 创建定期扩展未来分区的存储过程
|
||||
-- ============================
|
||||
DELIMITER $$
|
||||
|
||||
CREATE PROCEDURE ExtendMonthlyPartitions(
|
||||
IN p_table_name VARCHAR(64),
|
||||
IN p_months_ahead INT
|
||||
)
|
||||
BEGIN
|
||||
DECLARE v_current DATE;
|
||||
DECLARE v_target DATE;
|
||||
DECLARE v_partition_name VARCHAR(16);
|
||||
DECLARE v_less_than VARCHAR(12);
|
||||
DECLARE v_max_partition VARCHAR(64);
|
||||
DECLARE v_sql VARCHAR(2000);
|
||||
|
||||
-- 从下个月开始补充分区
|
||||
SET v_current = DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01');
|
||||
SET v_target = DATE_FORMAT(CURDATE() + INTERVAL p_months_ahead MONTH, '%Y-%m-01');
|
||||
|
||||
-- 找到当前 MAXVALUE 分区名(通常为 pfuture)
|
||||
SELECT PARTITION_NAME INTO v_max_partition
|
||||
FROM information_schema.PARTITIONS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = p_table_name
|
||||
AND PARTITION_DESCRIPTION = 'MAXVALUE';
|
||||
|
||||
IF v_max_partition IS NULL THEN
|
||||
SIGNAL SQLSTATE '45000'
|
||||
SET MESSAGE_TEXT = 'No MAXVALUE partition found; table may not be range-partitioned';
|
||||
END IF;
|
||||
|
||||
WHILE v_current <= v_target DO
|
||||
SET v_partition_name = CONCAT('p', DATE_FORMAT(v_current, '%Y%m'));
|
||||
SET v_less_than = DATE_FORMAT(v_current + INTERVAL 1 MONTH, '%Y-%m-%d');
|
||||
|
||||
-- 仅当分区不存在时才添加,保证幂等
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.PARTITIONS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = p_table_name
|
||||
AND PARTITION_NAME = v_partition_name
|
||||
) THEN
|
||||
SET v_sql = CONCAT(
|
||||
'ALTER TABLE ', p_table_name,
|
||||
' REORGANIZE PARTITION ', v_max_partition,
|
||||
' INTO (PARTITION ', v_partition_name, ' VALUES LESS THAN (''', v_less_than, '''), ',
|
||||
'PARTITION ', v_max_partition, ' VALUES LESS THAN MAXVALUE)'
|
||||
);
|
||||
SET @sql = v_sql;
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
|
||||
SET v_current = v_current + INTERVAL 1 MONTH;
|
||||
END WHILE;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
36
scripts/extend-mysql-partitions.sh
Executable file
36
scripts/extend-mysql-partitions.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# 扩展 MySQL RANGE 月分区
|
||||
# 为 mci_message_event / mci_send_record / mci_conversation 自动添加未来月份分区。
|
||||
# 依赖 V15__add_range_partitions.sql 中创建的存储过程 ExtendMonthlyPartitions。
|
||||
#
|
||||
# 用法示例:
|
||||
# ./scripts/extend-mysql-partitions.sh
|
||||
# MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_USER=root MYSQL_PASSWORD=root MYSQL_DB=sino_mci ./scripts/extend-mysql-partitions.sh
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MYSQL_HOST="${MYSQL_HOST:-mci-mysql}"
|
||||
MYSQL_PORT="${MYSQL_PORT:-3306}"
|
||||
MYSQL_USER="${MYSQL_USER:-root}"
|
||||
MYSQL_PASSWORD="${MYSQL_PASSWORD:-root}"
|
||||
MYSQL_DB="${MYSQL_DB:-sino_mci}"
|
||||
MONTHS_AHEAD="${MONTHS_AHEAD:-3}"
|
||||
|
||||
TABLES=(
|
||||
mci_message_event
|
||||
mci_send_record
|
||||
mci_conversation
|
||||
)
|
||||
|
||||
echo "Extending monthly partitions for database: ${MYSQL_DB}"
|
||||
echo "Host: ${MYSQL_HOST}:${MYSQL_PORT}, User: ${MYSQL_USER}, Months ahead: ${MONTHS_AHEAD}"
|
||||
|
||||
for table in "${TABLES[@]}"; do
|
||||
echo " -> ${table}"
|
||||
mysql -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DB}" \
|
||||
-e "CALL ExtendMonthlyPartitions('${table}', ${MONTHS_AHEAD});"
|
||||
done
|
||||
|
||||
echo "Done."
|
||||
Reference in New Issue
Block a user