MySQL增量更新必须依赖唯一标识(如自增主键或updated_at时间戳)或哈希生成的signature字段并加索引,否则ON DUPLICATE KEY UPDATE将失效;应避免REPLACE INTO,严格使用INSERT...ON DUPLICATE KEY UPDATE仅更新业务字段,并确保爬虫写入真实时间而非NOW()。

增量更新前必须确认的主键或时间戳字段
没有唯一标识或递增时间戳,增量更新就无从谈起。MySQL 表里至少得有一个 id(自增主键)或 updated_at(datetime 类型且爬虫能写入)字段。如果源数据本身没提供稳定 ID,又无法控制爬虫写入时间戳,就得在入库前用哈希生成 md5(url + content) 作为 signature 字段——但要注意 MySQL 的 md5 函数和 Python 的 hashlib.md5() 输出一致,且该字段需加索引,否则 INSERT ... ON DUPLICATE KEY UPDATE 会变全表扫描。
- 避免用
title或url当唯一键:URL 可能重定向、title 可能重复或含不可见字符 - 如果用
updated_at,爬虫抓取时必须统一用datetime.now()而非服务器系统时间,防止时区错乱 - 字段类型别选
TEXT做唯一键:MySQL 不允许对全文本字段建唯一索引,得用VARCHAR(255)或前缀索引
用 REPLACE INTO 还是 INSERT ... ON DUPLICATE KEY UPDATE?
REPLACE INTO 看似简单,但它本质是「删+插」,会引发自增 ID 跳变、触发器重复执行、外键约束检查开销大。真正做增量更新,必须用 INSERT ... ON DUPLICATE KEY UPDATE,且 ON DUPLICATE KEY UPDATE 后只更新业务字段,不碰主键和时间戳以外的元数据。
- 示例语句:
INSERT INTO news (id, title, content, updated_at) VALUES (%s, %s, %s, %s) ON DUPLICATE KEY UPDATE title=VALUES(title), content=VALUES(content), updated_at=VALUES(updated_at) - 别写
updated_at=NOW():这会让所有行都更新时间,掩盖真实变更;应始终传入爬虫获取到的原始时间 - 如果表有多个唯一键(比如
url和id),ON DUPLICATE KEY UPDATE只响应第一个冲突的键,其余键的冲突会报错
定时任务里怎么避免重复抓取和写入冲突
用 APScheduler 或 celery beat 调度时,不能只靠「每隔 N 分钟跑一次」。网络延迟、解析卡顿、MySQL 锁等待都可能导致上一轮还没结束,下一轮已启动,结果同一批数据被插入两次。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
- 加文件锁或数据库锁:在任务开头查
SELECT GET_LOCK('crawler_lock', 0),成功才继续;结尾用SELECT RELEASE_LOCK('crawler_lock') - 记录上次执行时间点:每次运行前读
last_run_time表(单行单列),WHERE 条件限定只抓publish_time > last_run_time的新数据,完成后更新该值 - 别依赖爬虫端的「sleep(60)」:它不解决并发问题,只让单进程节奏变慢;分布式环境下更无效
MySQL 连接池和事务边界怎么设才不拖垮服务
每条 INSERT ... ON DUPLICATE KEY UPDATE 单独 commit 是最慢的。但把几千条攒成一个事务提交,万一中途失败就得全滚回,重试成本高。折中做法是按批次提交,同时连接复用。
立即学习“Python免费学习笔记(深入)”;
- 用
pymysql时设置max_connections=10、mincached=3,避免频繁建连;SQLAlchemy用户直接配pool_size=5和max_overflow=10 - 每 100 条数据 wrap 在一个
connection.begin()里,出错时只回滚当前批次,不影响其他数据 - 别在事务里做耗时操作:下载、解析、清洗必须在事务外完成,只把最终结构化数据传进
execute_many()
max_allowed_packet —— 如果某条 content 字段超了 4MB,默认就会静默截断,而 Python 端可能只报个 OperationalError: Packet sequence number wrong,得去 MySQL error log 里翻真实原因。

















