pymysql连接失败常见报错及解法:认证插件不兼容(如mysql 8.0默认caching_sha2_password)、网络不通(服务未启动/防火墙拦截)、权限未开放(host限制或grant不足),需分别检查插件兼容性、服务状态与网络连通性、用户授权配置。

PyMySQL连接失败的常见报错和对应解法
连接不上基本就三类原因:认证插件不兼容、网络不通、权限没开。最典型的是 MySQL 8.0 默认用 caching_sha2_password 插件,而旧版 PyMySQL(Authentication plugin 'caching_sha2_password' is not supported。
- 升级 PyMySQL 到 1.1.0+:
pip install --upgrade pymysql - 或降级服务端认证方式(不推荐):
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_pass'; - 检查 host 是否允许远程连接(
bind-address在my.cnf中是否为0.0.0.0或注释掉) - 确认用户有对应 IP 的访问权限:
SELECT host, user FROM mysql.user;
用 PyMySQL 执行带参数的 INSERT/UPDATE 时防 SQL 注入的关键写法
千万别用 Python 字符串格式化拼接 SQL,比如 f"INSERT INTO t VALUES ({user_input})" —— 这等于把门敞开给注入攻击。PyMySQL 的参数化查询只认 %s 占位符,且必须传 tuple 或 list。
- 正确写法:
cursor.execute("INSERT INTO users (name, age) VALUES (%s, %s)", ("Alice", 28)) - 传单个值也要加逗号成元组:
cursor.execute("SELECT * FROM logs WHERE level = %s", ("ERROR",)) - 批量插入用
executemany:cursor.executemany("INSERT INTO t(x) VALUES (%s)", [(1,), (2,), (3,)]) - WHERE 条件含 IN 时不能直接传 list,得动态拼占位符:
"WHERE id IN ({})".format(",".join(["%s"] * len(ids))),再传ids元组
PyMySQL 查询结果怎么取成字典而不是元组
默认 cursor.fetchone() 返回 tuple,字段顺序依赖 SQL 里写的列顺序,易错且难维护。想按字段名取值,得换游标类型。
- 创建连接时指定
cursorclass=pymysql.cursors.DictCursor:
conn = pymysql.connect(
host='localhost',
user='root',
password='123',
database='test',
cursorclass=pymysql.cursors.DictCursor
)
cursor.fetchone() 就返回类似 {'id': 1, 'name': 'Bob'} 的 dictcursorclass,也可临时换:cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
长时间空闲连接被 MySQL 自动断开怎么办
MySQL 默认 wait_timeout=28800(8小时),但实际生产中常设为 300–600 秒。PyMySQL 不自动重连,一旦连接断开再执行 execute 就会报 Lost connection to MySQL server during query。
- 最稳妥是连接时开启自动重连:
connect(..., autocommit=True, ping=True)(ping=True表示每次执行前先发 ping 检查连接) - 或手动检测并重连:
try: cursor.execute(...) except pymysql.OperationalError as e: if "Lost connection" in str(e): conn.ping(reconnect=True) - 更推荐用连接池(如
DBUtils.PooledDB),它内置健康检查和失效连接剔除逻辑 - 别依赖
autocommit=False+ 长事务保活——这反而增加锁等待和主从延迟风险
PyMySQL 本身轻量,但连接管理、参数安全、结果结构这些点一旦忽略,轻则出错,重则数据错乱或被攻破。尤其 DictCursor 和 ping=True 这两个开关,很多人写完第一版才想起来补,其实该在初始化连接时就定死。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











