2015-03-30 7 views
7

Ich habe Probleme beim Zugriff auf MySQL aus der Ferne. Ich benutze SSH-Tunnel und möchte die Datenbank MySQL mit Python + SQLALchemy verbinden.Wie verbinde ich MySQL-Datenbank mit Python + SQLAlchemy remote?

Wenn ich MySQL-Client in meiner Konsole verwenden und "ptotocol=TCP" angeben, dann ist alles in Ordnung! Ich benutze Befehl:

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

ich Zugriff auf Remote-Datenbank über einen SSH-Tunnel bekommen.

Wenn ich jedoch eine Verbindung zur Datenbank mit Python + SQLAchemy herstellen möchte, kann ich keine solche Option wie —protocol=TCP finden. Ansonsten habe ich nur eine Verbindung zu lokalen MySQL-Datenbanken. Sag mir bitte, gibt es eine Möglichkeit, es mit SQLAlchemy zu tun.

+0

Richten Sie einen SSH-Tunnel ein, und zeigen Sie dann Ihren lokalen MySQL-Server auf den Tunnel-Port des lokalen Computers. mysql wird nicht wissen, dass es getunnelt wird, und ssh kümmert sich darum, alles dorthin umzuleiten, wo es hingehört. –

+0

Tunnel ist bereits installiert von X.X.X.X: 3306 -> localhost: 3306 Vielleicht muss ich tunnel zu einem anderen Port, zum Beispiel localhost: 3307? – strevg

+0

@strevg Um die Dinge zu klären: Sie haben einen MySQL Server auf Ihrem lokalen Rechner. Und ein zweiter MySQL-Server, auf den remote über einen SSH-Tunnel zugegriffen wird. Beide laufen gleichzeitig? Welcher Server ist an welchen Port Ihres lokalen Hosts gebunden? –

Antwort

12

Die klassische Antwort auf diese Frage ist 127.0.0.1 oder die IP der Host- oder die Hostnamen anstelle des „besonderen Namen“ localhost zu verwenden. Vom documentation:

[...] Verbindungen auf Unix zu localhost eine Unix-Socket-Datei standardmäßig

Und später verwenden gemacht:

Unter Unix MySQL-Programme behandeln den Hostnamen localhost speziell, in einer Weise, die wahrscheinlich anders ist als erwartet im Vergleich zu anderen Netzwerk- basierte Programme. Bei Verbindungen mit localhost versuchen MySQL-Programme, eine Verbindung zum lokalen Server herzustellen, indem sie eine Unix-Socket-Datei verwenden. Dies geschieht auch dann, wenn eine Option --port oder -P angegeben wird, um eine Portnummer anzugeben. Um sicherzustellen, dass der Client eine TCP/IP-Verbindung zum lokalen Server herstellt, verwenden Sie --host oder -h, um einen Hostnamen von 127.0.0.1 oder die IP-Adresse oder den Namen des lokalen Servers anzugeben.


Doch dieser einfache Trick erscheint nicht in Ihrem Fall zu arbeiten, so dass Sie irgendwie Kraft die Verwendung eines TCP-Socket haben. Wie Sie es selbst erklärt haben, verwenden Sie beim Aufruf von mysql in der Befehlszeile die Option --protocol tcp.

Wie erklärt here, von SQLAlchemy, können Sie die entsprechenden Optionen (falls vorhanden), um Ihre Fahrer entweder als URL-Optionen oder mit dem connect_args Stichwort Argumente übergeben.

Zum Beispiel mit PyMySQL, auf einem Testsystem I-Setup haben zu diesem Zweck (MariaDB 10.0.12, SQLAlchemy 0.9.8 und 0.6.2 PyMySQL) Ich habe folgende Ergebnisse:

>>> 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',)] 

Wie Sie bemerkt haben, verwenden beide eine TCP-Verbindung (das weiß ich wegen der Portnummer nach dem Hostnamen).Auf der anderen Seite:

>>> 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',)] 

Kein Anschluss nach dem Hostnamen: Dies ist ein UNIX-Socket.

+1

Schön. Dies funktionierte auch für mich mit einer lokalen mysql-Installation (ohne root), wo ich einen nicht standardmäßigen 'port' und' unix_socket' hatte, den ich einstellen musste. –

+0

Leider scheint MySQLdb strenger geworden zu sein. Jetzt erhalten Sie einen TypeError, weil SQLAlchemy den Port als String übergeben wird und MySQLdb einen int erwartet. :/ –

5

In meinem Setup (ich benutze mysql-python) nur mit 127.0.0.1 anstelle von localhost in der MySQL SQLAlchemy URL funktioniert. Die vollständige URL verwende ich genau für dieses Szenario (Tunnel mit lokal Port 3307) ist:

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

Ich bin mit SQLAlchemy 1.0.5, aber ich denke, das spielt keine Rolle, zu viel ...

+2

Tatsächlich ist 127.0.0.1 localhost, @ BK435, aber es funktioniert nicht mit localhost anstelle von 127.0.0.1. Dies scheint darauf zurückzuführen zu sein, dass musql sich mit "localhost" beschäftigt und darauf besteht, dass er sich über Dateisystem-Sockets anstatt über TCP-Sockets verbindet. Deshalb wird die Option --protocol = tcp für mysql in der Frage erwähnt. Aber es scheint, dass 127.0.0.1 den Trick macht und einfacher als die aktuelle Antwort ist. – jgbarah