如何远程使用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