不能。mysql连接(mysqlclient和pymysql的connection)均非线程安全,跨线程复用会导致连接丢失、数据错乱或崩溃;必须为每个线程/协程分配独立连接,推荐使用dbutils.pooleddb(mysqlclient)或aiomysql(异步)等线程隔离连接池。

mysqlclient 和 PyMySQL 的 connection 能不能跨线程复用
不能。两个库的 Connection 实例都**不是线程安全的**,哪怕只是并发读,也可能触发 MySQL server has gone away 或数据错乱。这不是 bug,是 MySQL 协议层和 Python 驱动实现共同决定的——每个线程必须持有自己的 Connection。
常见错误现象:OperationalError: (2013, 'Lost connection to MySQL server during query'),尤其在多线程 + 长连接 + 闲置超时场景下高频出现。
- PyMySQL 默认开启
autocommit=False,如果一个线程 commit 了,另一个线程还在用同一 connection,事务状态就乱了 - mysqlclient 底层是 C 扩展,对线程切换更敏感,偶尔会直接 segfault(尤其在 macOS 上)
- 即使加了锁保护 connection,也挡不住 MySQL 自身的 idle timeout(比如 wait_timeout=300),锁住也没用
怎么配线程池才不踩坑
别自己手写 connection 复用逻辑。用带线程隔离的连接池,而不是“共享一个 connection 对象”。
- mysqlclient 推荐用
DBUtils.PooledDB,配置maxshared=0(禁用共享)、maxconnections=N(N 是最大线程数),让每个线程 getconn() 拿到的是专属 connection - PyMySQL 可以用
pymysqlpool或直接上SQLAlchemy的QueuePool(默认 behavior 就是 per-thread connection) - 避免在 thread local 外缓存
Connection或Cursor实例——哪怕只存 1 秒,都可能被其他线程误取
示例(mysqlclient + DBUtils):
from DBUtils.PooledDB import PooledDB<br>pool = PooledDB(<br> creator=MySQLdb,<br> maxconnections=20,<br> maxshared=0,<br> blocking=True,<br> host='localhost',<br> user='root'<br>)<br># 每个线程调用 pool.connection(),拿到的都是独立 connection
立即学习“Python免费学习笔记(深入)”;
为什么 cursor 也不能跨线程传
Cursor 是 connection 的附属对象,生命周期绑定 connection。跨线程传 cursor 等价于跨线程操作 connection,一样会出问题。
- PyMySQL 的
Cursor.execute()内部会修改 connection 的内部 buffer,多线程写同一 buffer 就是未定义行为 - mysqlclient 的
cursor.fetchall()可能触发 C 层的全局状态变更(比如字符集缓存),导致另一线程解析结果出错 - 即使你只读不写,MySQL 的 packet sequence number 是 connection 级的,线程 A 发包、线程 B 收包,序号对不上直接断连
异步场景(asyncio)下更得小心
PyMySQL 原生不支持 asyncio;mysqlclient 完全不支持。硬套 loop.run_in_executor 时,connection 仍需按线程池方式管理,不能共用。
- 真要异步,用
aiomysql(基于 PyMySQL 改写,connection 绑定 event loop)或asyncmy(纯 async 实现) - 别试图把 mysqlclient 的 connection 丢进 executor 后再 await——它没实现 __await__,也不保证线程安全,executor 里多个任务仍可能撞上同一个 connection
- aiomysql 的
create_pool()默认就是 per-connection-per-task,比手动管线程池还省心
复杂点在于:connection 的创建/销毁成本高,但线程/协程隔离又不可妥协。折中方案只有两点——用池控数量,用短连接控超时。别的路,基本都绕不过去。










