我无法远程访问MySQL。我使用SSH隧道,并希望使用Python + SQLALchemy连接数据库MySQL。
当我在我的控制台中使用MySQL-client并指定" ptotocol=TCP
"时,一切都很好!
我用命令:
mysql -h localhost —protocol=TCP -u USER -p
我可以通过SSH隧道访问远程数据库。
但是,当我想使用Python + SQLAchemy连接到数据库时,我找不到像—protocol=TCP
这样的选项
否则,我只连接到本地MySQL数据库。
请告诉我,有没有办法使用SQLAlchemy。
答案 0 :(得分:16)
此问题的经典答案是使用127.0.0.1
或主机的 IP 或主机名而不是"特殊名称& #34; localhost
。来自documentation:
[...] Unix上与 localhost 的连接默认使用Unix套接字文件进行
后来:
在Unix上,MySQL程序特别将主机名 localhost 视为,其方式可能与您预期的与其他基于网络的程序相比有所不同。对于与localhost的连接,MySQL程序尝试使用Unix套接字文件连接到本地服务器。即使给出--port或-P选项指定端口号,也会发生这种情况。要确保客户端与本地服务器建立TCP / IP连接,请使用--host或-h指定主机名值127.0.0.1,或本地服务器的IP地址或名称。
但是,这个简单的技巧似乎并不适用于您的情况,因此您必须以某种方式强制使用TCP套接字。正如您自己解释的那样,在命令行上调用mysql
时,您使用--protocol tcp
选项。
正如here所述,来自SQLAlchemy,您可以使用connect_args
关键字参数将相关选项(如果有)作为URL选项或传递给您的驱动程序。 / p>
例如使用 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',)]
hostname 之后没有端口:这是一个UNIX套接字。
答案 1 :(得分:7)
在我的设置中(我使用的是mysql-python)只是在MySQL SQLAlchemy url中使用127.0.0.1而不是localhost。我正在使用的完整网址(具有本地端口3307的隧道)是:
mysql:/user:passwd@127.0.0.1:3307/
我正在使用SQLAlchemy 1.0.5,但我想这并不重要......
答案 2 :(得分:4)
这对我有用:
import pandas as pd
import pymysql
from sqlalchemy import create_engine
cnx = create_engine('mysql+pymysql://<username>:<password>@<host>/<dbname>')
df = pd.read_sql('SELECT * FROM <table_name>', cnx) #read the entire table
将凭据添加到mysql数据库中的位置是这样的:
CREATE USER '<username>' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON *.* TO '<username>' WITH GRANT OPTION;
FLUSH PRIVILEGES;