Skip to content

MySQL 数据清理(Rename 方案)

适用于 MySQL 8.0.34+,通过建新表+导入保留数据+Rename 切换,避免 DELETE 大量数据的性能问题

前置检查

-- 确认表结构
DESCRIBE old_table;
SHOW INDEX FROM old_table;

-- 确认数据分布
SELECT 
    COUNT(*) AS total_rows,
    COUNT(CASE WHEN id <= 1000 THEN 1 END) AS keep_rows
FROM old_table;

-- 确认磁盘空间(需大于表大小 × 2)
SELECT 
    ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024 / 1024, 2) AS size_gb 
FROM information_schema.TABLES 
WHERE table_name = 'old_table' AND table_schema = DATABASE();

操作步骤

1. 创建新表

CREATE TABLE new_table LIKE old_table;

-- 验证结构
SHOW CREATE TABLE new_table\G

2. 导入保留数据

-- 小数据量(< 100万行)
INSERT INTO new_table 
SELECT * FROM old_table 
WHERE id <= 1000;

-- 大数据量(分批导入)
INSERT INTO new_table SELECT * FROM old_table WHERE id BETWEEN 1 AND 100000;
INSERT INTO new_table SELECT * FROM old_table WHERE id BETWEEN 100001 AND 200000;
-- ...

3. 数据校验

-- 行数核对
SELECT 
    (SELECT COUNT(*) FROM new_table) AS new_count,
    (SELECT COUNT(*) FROM old_table WHERE id <= 1000) AS old_count;

-- 抽查数据一致性
SELECT o.id, o.col1, n.col1 
FROM old_table o 
JOIN new_table n ON o.id = n.id 
WHERE o.id IN (100, 500, 999);

4. Rename 切换

-- 原子切换(秒级完成)
RENAME TABLE 
    old_table TO old_table_bak_$(date +%Y%m%d),
    new_table TO old_table;

-- 验证
SHOW TABLES LIKE 'old_table%';
SELECT COUNT(*) FROM old_table;

回滚

-- 如出现问题,立即回滚
RENAME TABLE 
    old_table TO new_table_err,
    old_table_bak_$(date +%Y%m%d) TO old_table;

清理

-- 确认业务正常后,删除备份表
DROP TABLE old_table_bak_$(date +%Y%m%d);

按时间清理示例

-- 保留 90 天内数据
CREATE TABLE new_table LIKE old_table;

INSERT INTO new_table 
SELECT * FROM old_table 
WHERE create_time >= DATE_SUB(NOW(), INTERVAL 90 DAY);

RENAME TABLE old_table TO old_table_bak, new_table TO old_table;