数据库
首页 > 数据库> > 如何远程使用Python SQLAlchemy连接MySQL数据库?

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

作者:互联网

我无法远程访问MySQL.我使用SSH隧道,并希望使用Python SQLALchemy连接数据库MySQL.

当我在我的控制台中使用MySQL-client并指定“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,您可以将相关选项(如果有)作为URL选项或使用connect_args关键字参数传递给驱动程序.

例如,在我为此设置的测试系统上使用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,mysql,tcp,sqlalchemy,ssh-tunnel
来源: https://codeday.me/bug/20191005/1855910.html