用 schedule 库实现轻量级定时清理更可控,需封装独立函数、主循环加 sleep、每次新建数据库连接、sql 传参时间点、分批删除、建索引、加日志与异常防护。

用 schedule 库实现轻量级定时清理
不需要上 celery 或 APScheduler,小项目直接用 schedule 更可控。它不依赖外部服务,启动即跑,适合部署在单机或容器里。
常见错误是把定时逻辑写在主循环里却没加 time.sleep(1),导致 CPU 占满;或者用 threading.Timer 做递归调度,容易漏执行。
- 安装:
pip install schedule - 清理任务应封装为独立函数(如
clean_old_records()),避免闭包捕获过期连接 - 主程序末尾必须加
while True: schedule.run_pending(); time.sleep(1) - 别在定时函数里复用全局数据库连接对象——连接可能超时失效,每次执行应新建或从连接池取
DELETE 语句要带 WHERE 时间条件,且字段必须有索引
假设表 logs 有 created_at 字段,清理 3 个月前数据,最简写法是:
DELETE FROM logs WHERE created_at <p>但这是 PostgreSQL 写法;MySQL 要用 <code>DATE_SUB(NOW(), INTERVAL 3 MONTH)</code>;SQLite 用 <code>datetime('now', '-3 months')</code>。不统一 SQL 方言会导致迁移失败。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)"><img
src="https://img.php.cn/upload/skill/000/000/081/179212160094080.jpg" alt="Claw Code Suite (Python-Only Edition)" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)" class="overflowclass">Claw Code Suite (Python-Only Edition)</a>
<p class="overflowclass">仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...</p>
</div>
<a rel="nofollow" href="/xiazai/skill8551" title="Claw Code Suite (Python-Only Edition)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 务必确认
created_at字段已建索引,否则全表扫描会锁表、拖慢业务查询 - 生产环境避免一次性删太多——超过 10 万行建议分批,例如每次删 5000 行,用
LIMIT+ 循环 - 别用
SELECT * FROM ...先查再删,浪费内存和网络开销;直接DELETE更高效
Python 中用 datetime 构造安全的时间边界
硬写 SQL 时间表达式容易出错,尤其跨时区或夏令时场景。更稳妥的方式是在 Python 层算好时间点,传参进 SQL。
比如清理 90 天前的数据:
from datetime import datetime, timedelta<br>cut_off = datetime.now() - timedelta(days=90)<br>cursor.execute("DELETE FROM logs WHERE created_at
-
timedelta不受系统时区影响,但要注意datetime.now()返回本地时区时间;若数据库存的是 UTC,应改用datetime.utcnow() - PostgreSQL 对
timestamp without time zone字段,传入datetime对象时不会自动转时区;而timestamp with time zone会按 session timezone 转换——这点常被忽略,导致删错数据 - SQLite 的
datetime类型本质是文本,建议统一存 ISO 格式字符串(dt.isoformat()),避免解析歧义
清理脚本必须有日志和异常防护
没人盯着的时候删错数据,就只能靠日志回溯。但只打 print() 不够,得记录删了多少行、耗时、SQL 错误详情。
- 删之前先
SELECT COUNT(*)预估数量,超阈值(如 10 万)就发告警或跳过 - 用
cursor.rowcount拿到实际删除行数,写入日志;注意某些驱动(如 psycopg2)在executemany下不返回准确值 - 整个清理操作包在
try/except里,捕获OperationalError和IntegrityError,防止一次失败阻塞后续调度 - 别把密码或连接串写死在脚本里——通过环境变量读取,如
os.getenv('DB_URL')
真正麻烦的不是写几行 DELETE,而是确保删得准、删得稳、删了能追溯。时间字段类型、索引状态、连接生命周期、时区对齐——漏掉任一环,都可能让“定期清理”变成“定期事故”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










