2015-03-30 163 views
7

我在遠程訪問MySQL時遇到困難。我使用SSH隧道並希望使用Python + SQLALchemy連接數據庫MySQL。如何使用Python + SQLAlchemy遠程連接MySQL數據庫?

當我在我的控制檯中使用MySQL客戶端,並指定「ptotocol=TCP」,那麼一切都很好! 我使用命令:

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

我可以通過SSH隧道訪問遠程數據庫。

然而,當我想連接到使用Python + SQLAchemy數據庫中找不到這樣的選擇像—protocol=TCP 否則,我只有連接到本地MySQL數據庫。 請告訴我,有沒有辦法使用SQLAlchemy來做到這一點。

+0

設置了一個ssh隧道,然後將本地mysql指向本地機器的隧道端口。 mysql不會知道它正在隧道中,而ssh將負責將它應該去的所有東西重定向。 – 2015-03-30 20:30:25

+0

隧道已經從X.X.X.X安裝:3306 - > localhost:3306 也許我需要設置隧道到另一個端口,例如localhost:3307? – strevg 2015-03-31 19:49:52

+0

@strevg爲了澄清事情:您的本地主機上運行有MySQL服務器。另一臺通過SSH隧道遠程訪問的MySQL服務器。兩者都在同時運行?哪臺服務器綁定到本地主機上的哪個端口? – 2015-03-31 21:20:51

回答

12

經典的回答這個問題是使用127.0.0.1IP主機的或主機名而不是「特殊名稱」 localhost。從documentation

[...]在UNIX到本地主機連接使用Unix套接字文件默認

後來又做:

在Unix上, MySQL程序將主機名localhost專門處理爲,其方式可能與您期望的不同,基於程序。對於連接到本地主機,MySQL程序試圖通過使用Unix套接字文件連接到本地服務器。即使給出了--port或-P選項來指定端口號,也會發生這種情況。要確保客戶端與本地服務器建立TCP/IP連接,請使用--host或-h指定主機名值127.0.0.1或本地服務器的IP地址或名稱。


然而,這種簡單的伎倆不會出現在你的情況下工作,所以你必須以某種使用TCP套接字的。正如您自己解釋的那樣,在命令行上調用mysql時,可以使用--protocol tcp選項。

由於使用connect_args關鍵字參數解釋here,從SQLAlchemy的,你可以通過相關選項(如果有的話)到你的驅動程序或者作爲URL選項

例如使用PyMySQL,在測試系統上我設置爲目的(MariaDB的10.0.12,SQLAlchemy的0.9.8和0.6.2 PyMySQL)我得到以下結果:

>>> engine = create_engine(
     "mysql+pymysql://sylvain:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/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套接字。

+1

不錯。這也適用於我使用本地(非root)mysql安裝,在那裏我需要設置一個非標準的'port'和'unix_socket'。 – 2016-03-23 11:37:32

+0

不幸的是,MySQLdb似乎變得更加嚴格。現在你得到一個TypeError,因爲SQLAlchemy傳遞的是一個字符串,MySQLdb期望一個int。 :/ – 2018-02-14 19:39:49

5

在我的設置中(我使用的是mysql-python)只是使用127.0.0.1而不是本地主機的MySQL SQLAlchemy url工程。我使用的正是該方案的完整URL(隧道本地端口3307)是:

mysql:/user:[email protected]:3307/ 

我使用SQLAlchemy的1.0.5,但我想這並不重要太多...

+2

的確,127.0.0.1是localhost,@ BK435,但它不能與localhost而不是127.0.0.1一起使用。這似乎是由於musql如何處理「localhost」,堅持通過文件系統套接字而不是TCP套接字進行連接。這就是爲什麼在問題中提到mysql的選項--protocol = tcp。但似乎127.0.0.1做到了這一點,並且比當前的答案簡單。 – jgbarah 2015-06-12 07:38:16

相關問題