python - 如何使用Python+SQLAlchemy远程连接MySQL数据库?

标签 python mysql tcp sqlalchemy ssh-tunnel

我无法远程访问 MySQL。我使用SSH隧道,想使用Python+SQLALchemy连接数据库MySQL。

当我在我的控制台中使用 MySQL 客户端并指定“ptotocol=TCP”时,一切都很好! 我使用命令:

mysql -h localhost —protocol=TCP -u USER -p

我通过 SSH 隧道访问远程数据库。

但是,当我想使用 Python+SQLAchemy 连接到数据库时,我找不到像 —protocol=TCP 这样的选项 否则,我只能连接到本地 MySQL 数据库。 请告诉我,有没有办法使用 SQLAlchemy 来完成。

最佳答案

这个问题的经典答案是使用 127.0.0.1 或主机的 IP主机名 而不是“特殊名称”localhost。来自 documentation :

[...] connections on Unix to localhost are made using a Unix socket file by default

之后:

On Unix, MySQL programs treat the host name localhost specially, in a way that is likely different from what you expect compared to other network-based programs. For connections to localhost, MySQL programs attempt to connect to the local server by using a Unix socket file. This occurs even if a --port or -P option is given to specify a port number. To ensure that the client makes a TCP/IP connection to the local server, use --host or -h to specify a host name value of 127.0.0.1, or the IP address or name of the local server.


但是,这个简单的技巧在您的情况下似乎不起作用,因此您必须以某种方式强制使用 TCP 套接字。正如您自己解释的那样,在命令行上调用 mysql 时,您使用了 --protocol tcp 选项。

如解释here ,从 SQLAlchemy,您可以使用 connect_args 关键字参数将相关选项(如果有)作为 URL 选项传递给您的驱动程序。

例如使用 PyMySQL,在我为此目的设置的测试系统(MariaDB 10.0.12、SQLAlchemy 0.9.8 和 PyMySQL 0.6.2)上,我得到了以下结果:

>>> engine = create_engine(
      "mysql+pymysql://sylvain:passwd@localhost/db?host=localhost?port=3306")
#                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
#                               Force TCP socket. Notice the two uses of `?`
#                               Normally URL options should use `?` and `&`  
#                               after that. But that doesn't work here (bug?)
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54164',)]

# Same result by using 127.0.0.1 instead of localhost: 
>>> engine = create_engine(
      "mysql+pymysql://sylvain:passwd@127.0.0.1/db?host=localhost?port=3306")
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54164',)]

# Alternatively, using connect_args:
>>> engine = create_engine("mysql+pymysql://sylvain:passwd@localhost/db",
                       connect_args= dict(host='localhost', port=3306))
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost:54353',)]

如您所见,两者都将使用 TCP 连接(我知道这是因为主机名后的端口号)。另一方面:

>>> engine = create_engine(
      "mysql+pymysql://sylvain:passwd@localhost/db?unix_socket=/path/to/mysql.sock")
#                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#                               Specify the path to mysql.sock in
#                               the `unix_socket` option will force
#                               usage of a UNIX socket

>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

# Same result by using 127.0.0.1 instead of localhost: 
>>> engine = create_engine(
      "mysql+pymysql://sylvain:passwd@127.0.0.1/db?unix_socket=/path/to/mysql.sock")
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

# Alternatively, using connect_args:
>>> engine = create_engine("mysql+pymysql://sylvain:passwd@localhost/db",
                       connect_args= dict(unix_socket="/path/to/mysql.sock"))
>>> conn = engine.connect()
>>> conn.execute("SELECT host FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = CONNECTION_ID()").fetchall()
[('localhost',)]

主机名 后没有端口:这是一个 UNIX 套接字。

关于python - 如何使用Python+SQLAlchemy远程连接MySQL数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29355674/

相关文章:

javascript - Pymongo .eval() 与 Mongo shell --eval

python - 如何在优先考虑其中一个维度的同时对二维列表进行排序

php - 如何在 PHP 和 mySQL 中创建票证引用号

sockets - Dart 将 TCP ServerSocket 客户端传递给 Isolate

java - 当客户端套接字连接到本地 IP 而不适用于全局 IP 时,客户端-服务器套接字连接有效。 (超过 4G 连接)

python - Django错误: Caught NoReverseMatch while rendering

python - 在 Mac OS 上从 transformers 类导入管道函数时,Jupyter 内核死机

java 无法保留一个实体,可能是因为 boolean 字段

PHP输入mysql数据库

python - 如何在Python中完成套接字文件传输?