Python连接MySQL数据库时遇到报错,怎么办?

来源:站长平台作者:美园和花头衔:网络博主
导读:本期聚焦于美园和花创作的《Python连接MySQL数据库时遇到报错,怎么办?》,敬请观看详情。排查Python连MySQL的报错,最忌一上来就重装驱动或改一堆配置。其实Access denied、Can't connect to MySQL server、Unknown database这些高频异常,分别对应认证层、网络层和库名参数问题。本文以PyMySQL为主,同时对比mysqlclient与官方mysql-connector-python的差异,按照驱动加载、账号权限、主机匹配、超时设置、字符集这五步建立清晰的排查顺序。重点说明MySQL 8默认caching_sha2_password导致旧驱动无法认证的典型场景,以及localhost和127.0.0.1在权限匹配上的本质区别,并给出可执行的授权语句和连接重试封装思路。读完可以根据完整报错快速判断问题出在代码参数、数据库账号还是网络策略,避免无效重试和重复安装。

Python连接MySQL时报错,很多人第一反应是“密码是不是输错了”,但真正的原因可能出在驱动没装对、账号主机不匹配,或者MySQL 8的认证插件发生了变化。与其反复试错,不如先看清完整异常信息,再按连接层、认证层、网络层、会话层的顺序排查。这篇文章以PyMySQL为主要示例,同时兼顾mysqlclient和官方mysql-connector-python,把常见的连接报错和处理方式一次说清。

Python连接MySQL数据库时遇到报错,怎么办?

一、驱动安装与连接方式:先解决ModuleNotFoundError

如果运行脚本时直接抛出 ModuleNotFoundError: No module named 'pymysql',说明当前Python环境中还没有安装对应驱动。先执行 pip install PyMySQL。需要注意的是,包名是 PyMySQL,导入时写小写的 pymysql,这两者不是同一个值。还有不少旧项目导入的是 MySQLdb,这是 MySQL-python 的接口名称,PyMySQL 安装后并不会自动提供 MySQLdb 这个模块名,所以会继续报 No module named 'MySQLdb'。这时有两种选择:一是把 import MySQLdb 改成 import pymysql;二是安装 mysqlclient,它才是 MySQLdb 的正统编译版本。

mysqlclient 依赖系统编译工具,在 Windows 上经常出现 Microsoft Visual C++ 14.0 is required 这样的报错。如果只是做常规查询和事务操作,不建议为了装 mysqlclient 去折腾编译环境,直接使用 PyMySQL 或官方 mysql-connector-python 更省事。前者是纯 Python 实现,部署简单;后者由 Oracle 提供,支持更多 MySQL 特性。下面这段代码可以在安装 PyMySQL 后做最小连接验证。

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="your_password",
    database="test_db",
    charset="utf8mb4",
    connect_timeout=5,
)
cursor = conn.cursor()
cursor.execute("SELECT VERSION()")
print(cursor.fetchone())
cursor.close()
conn.close()

如果这段代码能输出类似 (8.0.36,) 这样的版本号,说明驱动、端口和账号密码都通。如果这里就报错,不要把密码拼到命令行里继续试,应当保留这段脚本,使用 print 输出连接参数但不含密码,或直接阅读异常类型。

二、Access denied与认证插件:账号权限问题的两个重灾区

Access denied for user 'root'@'localhost' (using password: YES) 是最典型的认证失败提示。很多人第一反应是密码错误,但这条日志里还包含两个关键信息:用户是 root,来源主机是 localhost。MySQL 的账号体系并不只是一个用户名,而是由 user 和 host 共同组成。也就是说,root@localhost 和 root@127.0.0.1 在权限表中是两个不同的账号。当代码使用 host='127.0.0.1' 连接时,如果数据库里只有 root@localhost,就可能匹配不到账号或权限被拒绝。

处理这一问题时,可以先在 MySQL 命令行执行 SELECT user, host FROM mysql.user; 查看当前有哪些账号。如果应用从本机走 TCP 连接,建议为 127.0.0.1 或 % 创建独立账号,而不是直接开放 root。下面示例创建一个专门给 Python 应用使用的账号,并授予目标库权限。

CREATE USER 'app_user'@'%' IDENTIFIED BY 'App@123';
GRANT SELECT, INSERT, UPDATE, DELETE ON order_db.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

这里使用 % 表示允许任意主机连接。如果数据库在公网环境,更安全的做法是把 % 换成应用服务器所在的内网 IP 段,例如 'app_user'@'192.168.1.%'。同时密码里如果包含 @、#、% 等字符,在 Python 的 connect 参数中直接写成字符串通常没有问题,但如果把账号密码拼进 SQLAlchemy 的数据库 URL,就需要做 URL 编码,否则会出现解析错误。

另一个高频认证报错是 Authentication plugin 'caching_sha2_password' cannot be loaded。MySQL 8 把默认认证插件从 mysql_native_password 改成了 caching_sha2_password,而旧版本的 mysqlclient、部分 Linux 发行版自带的连接库并没有实现该插件。解决办法有三种:升级驱动到新版本;给 Python 环境安装 cryptography 库,让 PyMySQL 支持该插件;或者在数据库中临时把用户改回 mysql_native_password。

ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'App@123';
FLUSH PRIVILEGES;

修改认证插件会影响安全性,只建议在兼容旧客户端的过渡阶段使用。新项目尽量保持 caching_sha2_password,并使用新版驱动连接。

三、网络类报错:连接被拒、超时和库名错误的定位方法

Can't connect to MySQL server on '127.0.0.1' (111) 中的 111 表示端口被拒绝。这个问题通常不是 Python 代码引起的,而是 MySQL 服务没有启动、监听的端口不是 3306,或者 bind-address 限制只允许本地 socket。先确认服务状态,再检查端口监听。Linux 下可以用 ss -lntp | grep 3306,Windows 下用 netstat -ano | findstr 3306 查看。

如果 MySQL 只监听 127.0.0.1,那么从另一台机器连接就会被拒绝。需要修改 my.cnf 或 my.ini 中的 bind-address 为 0.0.0.0,并重启服务。云服务器还要检查安全组是否放行 3306 端口,否则服务正常但公网仍然连不上。报错码 10060 一般对应连接超时,常见于防火墙丢弃数据包;10061 则是端口拒绝,常见于服务未启动或端口不对。

除了 TCP 连接,超时参数也需要合理设置。connect_timeout 控制建立连接阶段的等待时间,read_timeout 和 write_timeout 控制后续读写的最长等待时间。如果数据库查询本身比较慢,read_timeout 设得太小会出现 Lost connection to MySQL server during query。可以在连接参数里显式指定这类超时值。

conn = pymysql.connect(
    host="db.internal.ipipp.com",
    port=3306,
    user="app_user",
    password="App@123",
    database="order_db",
    charset="utf8mb4",
    connect_timeout=10,
    read_timeout=30,
    write_timeout=30,
)

Unknown database 'order_db' 报错则说明账号是通的,但目标库名不存在或拼写错误。此时可以先不传 database 参数连接,再执行 SHOW DATABASES; 查看实际库名。也可以在建表、查询前用 cursor.execute("USE order_db") 切换库。还有一类与字符集相关的异常,例如 Illegal mix of collations,通常是连接字符集与表字段字符集不一致。建议连接时统一使用 charset='utf8mb4',数据库和表也尽量使用 utf8mb4,避免 emoji 或特殊中文写入失败。

四、用异常分类和重试机制提高连接稳定性

连接失败时如果只捕获 Exception,虽然不会让程序崩溃,但会把编程错误、权限错误和网络抖动混在一起。PyMySQL 的异常体系以 MySQLError 为基类,下面细分 OperationalError、ProgrammingError、InterfaceError 等。连接超时、服务断开通常抛出 OperationalError;SQL 语法或权限问题多抛出 ProgrammingError。分开捕获可以更准确地记录日志和决定是否重试。

下面是一个带重试的连接函数。网络抖动导致的 OperationalError 可以重试,而账号密码错误这类 ProgrammingError 不应盲目重试,否则会浪费时间和锁资源。示例中只对 OperationalError 进行有限次重试,其他异常直接抛出。

import time
import logging
import pymysql

def get_connection(retries=3, delay=2):
    last_error = None
    for attempt in range(1, retries + 1):
        try:
            conn = pymysql.connect(
                host="127.0.0.1",
                port=3306,
                user="app_user",
                password="App@123",
                database="order_db",
                charset="utf8mb4",
                connect_timeout=5,
            )
            logging.info("MySQL连接成功,第 %s 次", attempt)
            return conn
        except pymysql.err.OperationalError as exc:
            last_error = exc
            logging.warning("连接失败第 %s 次:%s", attempt, exc)
            if attempt < retries:
                time.sleep(delay * attempt)
        except pymysql.err.ProgrammingError as exc:
            raise RuntimeError("请检查账号、密码或SQL权限") from exc
    raise last_error

实际生产环境中,频繁创建连接会带来额外开销,可以使用 DBUtils 或 SQLAlchemy 的连接池管理连接。连接池会维护一定数量的空闲连接,并自动检测连接是否被服务端断开。不过问题排查阶段仍然建议先用单次连接定位错误,确认账号和网络都正常后再切换到连接池。

最后可以按照一个固定清单检查:驱动是否安装且导入名称正确;MySQL 服务是否监听目标端口;账号的 user 和 host 是否与连接来源匹配;密码是否直接以参数传入;MySQL 8 认证插件是否需要升级驱动;目标库是否存在;charset 是否统一为 utf8mb4;云主机安全组是否放行端口。把完整报错信息和这份清单对照,绝大多数 Python 连接 MySQL 的问题都能快速解决。

Python连接MySQLMySQL报错数据库连接修改时间:2026-09-17 12:38:55

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0917/58413.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。