You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RHEL下sqlalchemy用mysql+mysqldb连接MySQL报Access denied,其他系统正常

感谢您花时间阅读此问题。我花费了大量时间查找解决方案,也翻阅了pydobc和mysqldb的源码,但始终没有找到原因。

问题概述

我可以使用相同的连接方式和连接串在多台机器上连接MySQL服务器,但在RHEL服务器上使用相同方法会持续抛出Access denied错误,目前基本排除是真实权限问题导致。

背景信息

我使用sqlalchemy连接部署在远程网络的MySQL服务器。使用相同的凭据,我可以通过MySQL Workbench、MySQL Shell、本地Jupyter Notebook、本地Python脚本、Ubuntu 18.04 WSL1虚拟机,以及出问题的这台RHEL服务器连接MySQL——但RHEL服务器无法使用其他实例通用的连接方式。
我确认我的用户拥有MySQL服务器对应库表的读写权限(而且我的笔记本也可以正常建立ODBC连接),所以尽管报错提示权限不足,我认为这不是真实原因,欢迎大家提供排查思路。

问题详情

除RHEL服务器外,在上述所有环境中我都可以使用以下代码创建引擎并建立连接:

engine = sqlalchemy.create_engine('mysql+mysqldb://{user}:{password}@{server}:{port}/{database}?charset=utf8mb4'.format(user=user
                                ,password=password
                                ,server=server
                                ,port=port
                                ,database=database))

con = engine.connect()

后续我可以正常使用该连接执行pd.to_sql()、直接执行SQL等操作,运行完全正常。
但在RHEL服务器上执行相同代码时,会抛出如下报错:

>>> engine.connect()
Traceback (most recent call last):
  File "/python_dir/python3.8/site-packages/sqlalchemy/engine/base.py", line 3211, in _wrap_pool_connect
    return fn()
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 307, in connect
    return _ConnectionFairy._checkout(self)
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 767, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 425, in checkout
    rec = pool._do_get()
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/impl.py", line 146, in _do_get
    self._dec_overflow()
  File "/python_dir/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/python_dir/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/impl.py", line 143, in _do_get
    return self._create_connection()
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 253, in _create_connection
    return _ConnectionRecord(self)
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 368, in __init__
    self.__connect()
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 611, in __connect
    pool.logger.debug("Error on connect(): %s", e)
  File "/python_dir/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "/python_dir/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
  File "/python_dir/python3.8/site-packages/sqlalchemy/pool/base.py", line 605, in __connect
    connection = pool._invoke_creator(self)
  File "/python_dir/python3.8/site-packages/sqlalchemy/engine/create.py", line 578, in connect
    return dialect.connect(*cargs, **cparams)
  File "/python_dir/python3.8/site-packages/sqlalchemy/engine/default.py", line 584, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/python_dir/python3.8/site-packages/MySQLdb/__init__.py", line 130, in Connect
    return Connection(*args, **kwargs)
  File "/python_dir/python3.8/site-packages/MySQLdb/connections.py", line 187, in __init__
    super().__init__(*args, **kwargs2)
MySQLdb._exceptions.OperationalError: (1045, "Access denied for user 'USER'@'SERVER_ADDRESS' (using password: YES)")

出于安全考虑我对报错中的敏感信息做了修改,唯一的有效报错信息为:

MySQLdb._exceptions.OperationalError: (1045, "Access denied for user 'USER'@'SERVER_ADDRESS' (using password: YES)")

RHEL环境下的可用连接方式

尽管上述连接方式在RHEL上失效,但我可以通过另一种配置在RHEL上正常连接MySQL:

engine = sqlalchemy.create_engine('mysql+pyodbc://my_dsn')

该方式使用pyodbc,通过我在RHEL服务器/etc/odbc.ini中配置的DSN建立连接,对应配置示例如下(保留了原文件的大小写和空值,仅修改敏感信息):

[ODBC Data Sources]
my_dsn = My Special DSN

[my_dsn]
Driver = /dir/libmyodbc5.so
Description = Description
SERVER = Server
PORT = Port
USER = User
Password = Password
Database = Database
OPTION = 3
SOCKET = 

我发现DSN配置和传给mysqldb的连接串之间唯一的显著差异是DSN可以指定OPTION参数,但我不清楚pyodbc如何使用该参数。
我查阅了sqlalchemy、pyodbc、MySQL官方文档、StackOverflow、SuperUser、相关源码,希望找到为mysqldb指定OPTION参数的方法,但始终没有结果。我不确定OPTION参数是否是导致问题的核心原因,但这是目前我唯一无法匹配的配置项。
我也找到了相关问答和对应的参考页面,对OPTION参数的含义有了基础了解,但仍未解决我的问题。

预期目标

我希望所有系统和服务器都可以使用完全相同的连接代码,不需要在每台机器上单独配置DSN(因此RHEL上使用pyodbc的方案不符合要求),但目前RHEL上没有其他可用的连接方式。

已尝试的排查操作

我对驱动和Linux配置的了解有限,不排除是我配置错误导致的问题,已尝试过以下操作:

  • 尝试了多种不同的连接串,指定不同的驱动和连接参数
  • 尝试在RHEL上安装多个不同的MySQL驱动,效果不一
  • 查阅了数十篇同类问题的问答和技术文章
  • 尝试了多种其他临时配置方案,均未生效

配置信息

  • 问题服务器:RHEL Version 7
  • 其他正常运行环境:Ubuntu 18.04、Windows 10
  • Python版本:3.8
  • SQLAlchemy版本:RHEL为1.4.20,Windows为1.4.15,Ubuntu为1.4.22
  • pyodbc版本:RHEL为4.0.30,Windows为4.0.30,Ubuntu为4.0.31

如果需要更多信息请随时告知,非常感谢大家的帮助。


解决方案

核心问题定位

你遇到的1045报错不是真实权限问题,是RHEL7默认的MySQL客户端配置、以及mysqlclient(即mysqldb底层依赖)的默认连接逻辑和ODBC配置的差异导致的。
你ODBC里配置的OPTION=3是两个标志位的组合:1(CLIENT_FOUND_ROWS)+2(CLIENT_LONG_PASSWORD),其中CLIENT_LONG_PASSWORD是解决问题的核心——RHEL7自带的系统级MySQL客户端库默认关闭了旧版密码哈希兼容逻辑,而你的MySQL服务端可能使用了旧版密码哈希算法存储用户密码,直接用mysqldb连接时不会自动启用该兼容逻辑,导致密码校验失败。

修复方案

直接在SQLAlchemy连接串的connect_args参数里传递对应的客户端标志即可,不需要修改任何系统配置,也能保证所有环境代码完全一致:

from MySQLdb.constants import CLIENT

engine = sqlalchemy.create_engine(
    'mysql+mysqldb://{user}:{password}@{server}:{port}/{database}?charset=utf8mb4'.format(
        user=user,
        password=password,
        server=server,
        port=port,
        database=database
    ),
    connect_args = {
        'client_flag': CLIENT.FOUND_ROWS | CLIENT.LONG_PASSWORD
    }
)

如果不想引入MySQLdb的依赖导入,也可以直接传递对应的数值(两个标志位的和为3,和你ODBC里的OPTION值完全一致):

engine = sqlalchemy.create_engine(
    'mysql+mysqldb://{user}:{password}@{server}:{port}/{database}?charset=utf8mb4'.format(
        user=user,
        password=password,
        server=server,
        port=port,
        database=database
    ),
    connect_args = {
        'client_flag': 3
    }
)

补充排查项

如果上述方案无效,可以再检查两个RHEL7特有的配置:

  1. 检查RHEL7的/etc/my.cnf或/etc/mysql/my.cnf中是否有default-character-set相关配置,若默认字符集和其他环境不一致,也可能导致密码编码错误,你在连接串中显式指定charset=utf8mb4已经覆盖了该问题;
  2. 检查RHEL7是否开启了SELinux强制访问控制,若开启可以临时执行setenforce 0测试,确认是否是SELinux拦截了MySQL连接请求。

内容的提问来源于stack exchange,提问作者BowSto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 04:12:02