直接用mysql-connector-python单条插入会卡住或丢数据,因频繁提交触发大量网络往返与事务开销,autocommit=false导致连接长期持锁;应改用executemany批量插入、显式commit、复用连接并设utf8mb4字符集。

为什么直接用 mysql-connector-python 插入会卡住或丢数据?
实时写入不是“每抓一条就 execute() 一次”,频繁单条提交会触发大量网络往返和事务开销,MySQL 的 autocommit=False 默认设置还会让连接长期持锁。常见现象是:爬虫速度越来越慢、连接超时、部分数据没进库但程序没报错。
实操建议:
- 用
executemany()批量插入,每次攒够 100–500 条再提交(具体看字段长度和 MySQLmax_allowed_packet) - 显式设置
autocommit=True或手动调用conn.commit(),别依赖连接默认行为 - 避免在循环里反复
cursor.close()和conn.close(),连接应复用;可用上下文管理器或连接池 - 插入前加
try/except捕获mysql.connector.IntegrityError和OperationalError,失败时记录日志并跳过,别让单条错误中断整个流程
如何处理中文、特殊字符和 NULL 值不入库问题?
MySQL 表字符集是 utf8mb4,但 Python 连接器默认可能只认 utf8(实际是 utf8mb3),导致 emoji 或生僻字变 ?;NULL 值被转成字符串 'None' 也是常见坑。
实操建议:
- 创建连接时强制指定
charset='utf8mb4'和collation='utf8mb4_unicode_ci' - SQL 插入语句用占位符
%s,别拼字符串——既防 SQL 注入,也自动处理None→NULL映射 - 检查表字段是否允许
NULL:如果字段定义为NOT NULL但传了None,会直接报IntegrityError - 对可能为空的字段,在 Python 侧提前转换:
value if value is not None else None,保持类型纯净
怎么让爬虫和数据库写入不互相拖慢?
同步阻塞写入会让爬虫等 DB 响应,DB 等网络 IO,一卡全卡。尤其当目标站响应快、MySQL 在远程服务器时,瓶颈立刻暴露。
实操建议:
- 用线程队列解耦:爬虫线程往
queue.Queue放数据,单独一个 DB 写入线程消费,控制队列大小防内存爆掉 - 不要用
threading.Thread随便起一堆写入线程——MySQL 单连接不支持并发执行,多线程争同一连接反而更慢 - 若用异步爬虫(如
aiohttp),搭配aiomysql,但注意它不支持预编译语句缓存,高频插入时性能反不如同步 + 批量 - 监控
SHOW PROCESSLIST,确认没有长事务或锁表操作堆积
遇到 “Packet too large” 或 “Lost connection” 怎么快速定位?
错误信息 mysql.connector.errors.OperationalError: Packet too large 说明某条记录(通常是 TEXT/BLOB 字段)超出 MySQL 的 max_allowed_packet;Lost connection to MySQL server during query 多因网络波动或超时未设置。
实操建议:
- 查服务端配置:
SELECT @@max_allowed_packet;,一般设为 64M(需 DBA 权限修改) - 客户端连接时加参数:
connection_timeout=30、pool_size=5、pool_reset_session=True - 插入前校验单条记录大小:
sys.getsizeof(json.dumps(item)),超 10MB 就拆分或压缩存储 - 把大字段(如 HTML 正文)单独建表、按需延迟加载,主表只存摘要和 ID
wait_timeout=28800(8 小时),但云服务商(如阿里云 RDS)可能设成 300 秒。一旦连接闲置超过这个时间,下次 execute() 就直接断连报错,得加心跳或用连接池自动重连。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











