SQL Server归档后需日志备份+收缩才能释放磁盘空间,因DELETE/ TRUNCATE仅标记删除;MySQL则可通过DROP PARTITION瞬时释放空间。两者均须分批操作、删前校验、归档后留底。

直接删数据不等于释放磁盘空间——SQL Server 和 MySQL 的归档清理逻辑完全不同,盲目 DELETE 或 TRUNCATE 可能只“标记删除”,不回收文件体积。
SQL Server 归档后必须做日志备份 + 收缩
SQL Server 不会自动把 DELETE 掉的行对应的空间还给磁盘。即使你已把历史数据从主表移走,.ldf(日志)和 .mdf(数据)文件仍维持原大小。
- 先确认数据库恢复模式:
SELECT recovery_model_desc FROM sys.databases WHERE name = 'yourdb';只有FULL或BULK_LOGGED模式才需日志备份 - 执行事务日志备份(否则
DBCC SHRINKFILE无效):BACKUP LOG [yourdb] TO DISK = 'D:\backup\yourdb_log.trn' - 查日志文件逻辑名:
SELECT name FROM sys.master_files WHERE database_id = DB_ID('yourdb') AND type = 1 - 收缩日志文件(例如逻辑名为
yourdb_log):DBCC SHRINKFILE (N'yourdb_log', 1)—— 第二个参数是目标 MB,设为 1 表示尽可能小 - 注意:频繁收缩会加剧文件碎片,建议收缩后重建索引,且仅在备份窗口内操作
MySQL 分区表归档 + DROP PARTITION 是最省力方案
对按时间归档的表(如 log_archive_202401),用 DROP PARTITION 能瞬时释放磁盘空间,不走逐行 DELETE 流程,也不触发 binlog 膨胀。
- 确保表已按时间字段分区:
PARTITION BY RANGE (TO_DAYS(create_time)),否则无法使用该方式 - 检查现有分区:
SELECT partition_name, table_rows FROM information_schema.partitions WHERE table_name = 'log_archive' - 删除过期分区(比如最老的):
ALTER TABLE log_archive DROP PARTITION p202401 - 若需自动化,用事件调度器配合存储过程动态计算并删分区,避免硬编码分区名
- 禁用
event_scheduler默认是关闭的,需先执行:SET GLOBAL event_scheduler = ON
通用安全清理三原则:分批、校验、留底
不管 SQL Server 还是 MySQL,只要涉及批量删数据,就必须绕开长事务锁表、日志爆满、误删不可逆这三大坑。
- 永远分批操作:MySQL 用
LIMIT 10000,SQL Server 用TOP (10000)+WHERE范围条件,每次处理后加WAITFOR DELAY '00:00:01'(SQL Server)或SLEEP(0.1)(MySQL)缓解 IO 压力 - 删前必查数:
SELECT COUNT(*) FROM orders WHERE status = 'archived' AND create_time ,记录结果;删后立刻再查,偏差超 0.1% 就中止 - WHERE 条件必须带索引字段,用
EXPLAIN(MySQL)或执行计划(SSMS)确认走了索引;禁止无条件DELETE FROM table - 硬编码保留底线,例如脚本里写死:
AND create_time > '2022-01-01',哪怕传参出错也能兜底
最容易被忽略的是:归档迁移完成后,原表上对应字段没加 COMMENT 或归档库没设 READ ONLY 权限——后续一个误操作可能让整套归档失效。这事没法靠脚本自动发现,得人工核对一次。


















