Flask-migrate 通过 SSH 隧道连接到 MySQL 服务器时访问被拒绝

Access denied when Flask-migrate connects to MySQL server via SSH tunnel

TL;DR: 当我尝试将 flask db migrate 与远程数据库一起使用时,我得到:MySQLdb._exceptions.OperationalError: (1045 , "Access denied for user ''@'localhost' (using password: YES)").但我确定用户名和密码是正确的,远程用户具有 SELECT 权限,而且我实际上还没有声明任何模型。


我设置了 SSH 隧道以访问远程数据库。

$ ssh -L <local_port>:localhost:<remote_internal_port> <mysql_user>@<server> -p <remote_external_port>

我在远程 MySQL 数据库(真正的 MariaDB)上拥有只读用户的凭据。这不是存储用户的数据库,所以我使用 SQLALCHEMY_BINDS 添加第二个数据库。

我的环境是这样的:

DATABASE_URL=sqlite:////tmp/dev.db
DATABASE_BINDS="remote=mysql+mysqldb://<mysql_user>:<pass>@localhost:<local_port>/<db_name>"

然后在配置文件中:

from environs import Env

env = Env()
env.read_env()

SQLALCHEMY_DATABASE_URI = env.str("DATABASE_URL") # local
SQLALCHEMY_BINDS = env.dict("DATABASE_BINDS")  # remote, etc

我目前根本没有为远程数据库声明任何模型。我打算使用 reflection 加载它们。

flask db init --multidb 的初始 运行 工作正常。它创建迁移文件夹。但是当我 运行 flask db migrate -m "Initial DB" 时,我得到这个:

Traceback (most recent call last):
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 2275, in _wrap_pool_connect
    return fn()
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 303, in unique_connection
    return _ConnectionFairy._checkout(self)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 760, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 492, in checkout
    rec = pool._do_get()
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/impl.py", line 238, in _do_get
    return self._create_connection()
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection
    return _ConnectionRecord(self)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 437, in __init__
    self.__connect(first_connect_check=True)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/pool/base.py", line 639, in __connect
    connection = pool._invoke_creator(self)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect
    return dialect.connect(*cargs, **cparams)
  File "/path/to/project/venv/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 453, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/path/to/project/venv/lib/python3.7/site-packages/MySQLdb/__init__.py", line 84, in Connect
    return Connection(*args, **kwargs)
  File "/path/to/project/venv/lib/python3.7/site-packages/MySQLdb/connections.py", line 166, in __init__
    super(Connection, self).__init__(*args, **kwargs2)
MySQLdb._exceptions.OperationalError: (1045, "Access denied for user '<mysql_user>'@'localhost' (using password: YES)")

我已经检查并仔细检查了我在环境中声明的用户名和密码是否正确。我可以成功地使用具有这些设置的 GUI 客户端通过 SSH 隧道浏览远程 MySQL 数据库。我可以使用远程服务器上的 MySQL CLI 客户端在适当的数据库上使用和 SELECT。

我不知道在哪里看这里。我认为 SSH 隧道是一个转移注意力的问题,因为它在 GUI 客户端上运行良好,但我不知道如何获取更多日志记录以查看真正的问题所在。 This answer 暗示问题实际上可能是权限之一,而不是 l/p 本身。 Flask-Migrate 是否需要 SELECT 权限以外的权限?

问题是我使用的是 "localhost" 而不是“127.0.0.1”。