本文目录导读:

我来介绍几种批量删除数据库旧记录的脚本方法,涵盖不同数据库类型。
MySQL 脚本
按时间条件删除
-- 删除30天前的记录 DELETE FROM your_table WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY); -- 或指定具体日期 DELETE FROM your_table WHERE create_time < '2024-01-01';
分批删除(避免锁表)
#!/bin/bash
# 分批删除脚本 delete_old_records.sh
DB_HOST="localhost"
DB_USER="root"
DB_PASS="password"
DB_NAME="your_database"
TABLE="your_table"
BATCH_SIZE=10000
SLEEP_INTERVAL=1
while true; do
# 删除一批旧记录
DELETE_SQL="DELETE FROM $TABLE
WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)
LIMIT $BATCH_SIZE"
RESULT=$(mysql -h$DB_HOST -u$DB_USER -p$DB_PASS $DB_NAME -e "$DELETE_SQL" 2>&1)
# 检查受影响行数
AFFECTED=$(echo $RESULT | grep -oP 'Rows matched: \d+' | grep -oP '\d+')
if [ "$AFFECTED" -eq 0 ]; then
echo "删除完成,没有更多记录"
break
fi
echo "删除了 $AFFECTED 条记录"
sleep $SLEEP_INTERVAL
done
PostgreSQL 脚本
使用存储过程
CREATE OR REPLACE FUNCTION batch_delete_old_records()
RETURNS void AS $$
DECLARE
batch_size INTEGER := 10000;
deleted_count INTEGER;
BEGIN
LOOP
DELETE FROM your_table
WHERE ctid IN (
SELECT ctid FROM your_table
WHERE created_at < NOW() - INTERVAL '30 days'
LIMIT batch_size
);
GET DIAGNOSTICS deleted_count = ROW_COUNT;
IF deleted_count = 0 THEN
EXIT;
END IF;
RAISE NOTICE 'Deleted % records', deleted_count;
-- 短暂暂停
PERFORM pg_sleep(0.1);
END LOOP;
END;
$$ LANGUAGE plpgsql;
-- 执行
SELECT batch_delete_old_records();
MongoDB 脚本
Node.js 批量删除脚本
// delete_old_records.js
const { MongoClient } = require('mongodb');
async function batchDeleteOldRecords() {
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
try {
await client.connect();
const db = client.db('your_database');
const collection = db.collection('your_collection');
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - 30); // 30天前
let deletedCount = 0;
const batchSize = 1000;
while (true) {
// 查找要删除的文档
const docsToDelete = await collection
.find({ createdAt: { $lt: cutoffDate } })
.limit(batchSize)
.project({ _id: 1 })
.toArray();
if (docsToDelete.length === 0) {
console.log(`删除完成,共删除 ${deletedCount} 条记录`);
break;
}
// 批量删除
const ids = docsToDelete.map(doc => doc._id);
const result = await collection.deleteMany({
_id: { $in: ids }
});
deletedCount += result.deletedCount;
console.log(`已删除 ${deletedCount} 条记录`);
// 短暂暂停
await new Promise(resolve => setTimeout(resolve, 100));
}
} finally {
await client.close();
}
}
batchDeleteOldRecords().catch(console.error);
通用 Python 脚本(支持多种数据库)
使用 SQLAlchemy
# batch_delete.py
import time
from datetime import datetime, timedelta
from sqlalchemy import create_engine, text
def batch_delete_old_records():
# 数据库连接配置
db_config = {
'mysql': 'mysql+pymysql://user:password@localhost/database',
'postgresql': 'postgresql://user:password@localhost/database',
# 其他数据库连接字符串
}
# 选择数据库类型
db_type = 'mysql'
engine = create_engine(db_config[db_type])
# 参数配置
table_name = 'your_table'
date_column = 'created_at'
days_old = 30
batch_size = 10000
cutoff_date = datetime.now() - timedelta(days=days_old)
total_deleted = 0
with engine.connect() as conn:
while True:
# 执行批量删除
if db_type == 'mysql':
sql = text(f"""
DELETE FROM {table_name}
WHERE {date_column} < :cutoff_date
LIMIT :batch_size
""")
elif db_type == 'postgresql':
sql = text(f"""
DELETE FROM {table_name}
WHERE ctid IN (
SELECT ctid FROM {table_name}
WHERE {date_column} < :cutoff_date
LIMIT :batch_size
)
""")
result = conn.execute(sql, {
'cutoff_date': cutoff_date,
'batch_size': batch_size
})
affected_rows = result.rowcount
total_deleted += affected_rows
if affected_rows == 0:
print(f"删除完成,共删除 {total_deleted} 条记录")
break
print(f"已删除 {total_deleted} 条记录")
# 避免数据库压力过大
time.sleep(0.5)
return total_deleted
if __name__ == '__main__':
batch_delete_old_records()
Shell 脚本(通用方案)
带日志和错误处理的完整脚本
#!/bin/bash
# safe_batch_delete.sh
# 配置
DB_TYPE="mysql" # mysql, postgresql
DB_HOST="localhost"
DB_PORT="3306"
DB_USER="root"
DB_PASS="password"
DB_NAME="your_db"
TABLE="your_table"
DATE_COL="created_at"
DAYS_OLD=90
BATCH_SIZE=5000
SLEEP_SEC=1
LOG_FILE="/var/log/db_cleanup.log"
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
# 错误处理
handle_error() {
log "错误: $1"
exit 1
}
# 检查配置
if [ -z "$DB_PASS" ]; then
handle_error "数据库密码未设置"
fi
# 计算截止日期
CUTOFF_DATE=$(date -d "$DAYS_OLD days ago" +%Y-%m-%d)
log "开始删除 $TABLE 表中 $DAYS_OLD 天前的记录(截止日期:$CUTOFF_DATE)"
TOTAL_DELETED=0
while true; do
# 构建删除SQL
if [ "$DB_TYPE" == "mysql" ]; then
DELETE_SQL="DELETE FROM $TABLE WHERE $DATE_COL < '$CUTOFF_DATE' LIMIT $BATCH_SIZE;"
elif [ "$DB_TYPE" == "postgresql" ]; then
DELETE_SQL="DELETE FROM $TABLE WHERE ctid IN (SELECT ctid FROM $TABLE WHERE $DATE_COL < '$CUTOFF_DATE' LIMIT $BATCH_SIZE);"
else
handle_error "不支持的数据库类型: $DB_TYPE"
fi
# 执行删除
if [ "$DB_TYPE" == "mysql" ]; then
RESULT=$(mysql -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASS $DB_NAME -e "$DELETE_SQL" 2>&1)
elif [ "$DB_TYPE" == "postgresql" ]; then
RESULT=$(psql -h$DB_HOST -p$DB_PORT -U$DB_USER -d$DB_NAME -c "$DELETE_SQL" 2>&1)
fi
# 检查错误
if [ $? -ne 0 ]; then
handle_error "删除失败: $RESULT"
fi
# 提取删除数量
if [ "$DB_TYPE" == "mysql" ]; then
AFFECTED=$(echo "$RESULT" | grep -oP 'Rows matched: \d+' | grep -oP '\d+')
else
AFFECTED=$(echo "$RESULT" | grep -oP 'DELETE \d+' | grep -oP '\d+')
fi
if [ -z "$AFFECTED" ] || [ "$AFFECTED" -eq 0 ]; then
log "删除完成,共删除 $TOTAL_DELETED 条记录"
break
fi
TOTAL_DELETED=$((TOTAL_DELETED + AFFECTED))
log "本轮删除 $AFFECTED 条记录,累计删除 $TOTAL_DELETED 条"
sleep $SLEEP_SEC
done
log "清理任务完成"
重要注意事项
备份数据
# 删除前备份 mysqldump -u root -p your_db your_table > backup_$(date +%Y%m%d).sql
测试环境验证
先在测试库运行,确认不影响业务。
监控数据库性能
-- MySQL 查看当前连接 SHOW PROCESSLIST; -- PostgreSQL 查看活动查询 SELECT * FROM pg_stat_activity;
建议的时间窗口
- 业务低峰期执行(凌晨2-5点)
- 避免在高峰时段进行大量删除
选择哪种脚本取决于你的数据库类型、表大小、业务需求等因素,对于大表(千万级以上),建议使用分批删除方式以避免锁表。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播