2015-03-30 18 views
7

Mam problemy z dostępem do MySQL zdalnie. Korzystam z tunelu SSH i chcę połączyć bazę danych MySQL za pomocą Python + SQLALchemy.Jak zdalnie podłączyć bazę danych MySQL za pomocą Python + SQLAlchemy?

Kiedy używam klienta MySQL w mojej konsoli i określam "ptotocol=TCP", wszystko jest w porządku! używam polecenia:

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

uzyskać dostęp do bazy danych za pośrednictwem SSH tunel.

Jednak, gdy chcę połączyć się z bazą danych za pomocą Python + SQLAchemy, nie mogę znaleźć takiej opcji, jak —protocol=TCP W przeciwnym razie, mam tylko połączyć się z lokalnymi bazami danych MySQL. Powiedz mi, proszę, czy istnieje sposób, aby to zrobić za pomocą SQLAlchemy.

+0

skonfiguruj tunel ssh, a następnie wskaż lokalny mysql w porcie tunelu na komputerze lokalnym. mysql nie będzie wiedział, że jest tunelowany, a ssh zajmie się przekierowaniem wszystkiego, co powinno. –

+0

Tunel został już zainstalowany z X.X.X.X: 3306 -> localhost: 3306 Może muszę ustawić tunel na inny port, na przykład localhost: 3307? – strevg

+0

@strevg W celu wyjaśnienia rzeczy: masz serwer MySQL uruchomiony na lokalnym hoście. I drugi serwer MySQL dostępny zdalnie przez tunel SSH. Oba działają jednocześnie? Który serwer jest powiązany z jakim portem na lokalnym hoście? –

Odpowiedz

12

Klasyczny odpowiedzią na ten problem jest użycie 127.0.0.1 lub IP hosta lub nazwę hostazamiast „specjalną nazwą” localhost. Z documentation:

[...] połączenia w systemie UNIX do localhost wykonane są przy użyciu pliku gniazda Unix domyślnie

a później:

W systemie UNIX Programy MySQL traktują nazwę hosta localhost specjalnie, w sposób, który prawdopodobnie różni się od tego, czego się spodziewasz w porównaniu do innych sieci. oparte programy. W przypadku połączeń z lokalnym hostem, programy MySQL próbują połączyć się z serwerem lokalnym za pomocą pliku gniazda uniksowego. Dzieje się tak, nawet jeśli podano opcję --port lub -P w celu określenia numeru portu. Aby upewnić się, że klient tworzy połączenie TCP/IP z serwerem lokalnym, użyj parametru -host lub -h, aby określić wartość nazwy hosta 127.0.0.1 lub adres IP lub nazwę lokalnego serwera.


Jednak ten prosty trik nie wydaje się działać w Twoim przypadku, więc trzeba jakoś siły użycie gniazda TCP. Jak sam wyjaśniłeś, podczas wywoływania mysql w wierszu poleceń, używasz opcji --protocol tcp.

Jak wyjaśniono here z SQLAlchemy, można przekazać odpowiednie opcje (jeśli w ogóle) do sterownika albo jako opcje URL lub używając argumentu connect_args słowa kluczowego.

na przykład stosując PyMySQL na systemie testowym mam ustawić w tym celu (MariaDB 10.0.12, SQLAlchemy 0.9.8 i 0.6.2) PyMySQL Mam następujące wyniki:

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

Jak zauważyłeś, oba będą używać połączenia TCP (wiem to z powodu numeru portu po nazwie hosta).Z drugiej strony:

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

nr portu po hosta: Jest to gniazdo UNIX.

+1

Nice. To również zadziałało dla mnie, pracując z lokalną (nie rootem) instalacją mysql, gdzie miałem niestandardowy "port" i "unix_socket", które musiałem ustawić. –

+0

Niestety, wydaje się, że MySQLdb stał się bardziej restrykcyjny. Teraz dostajesz TypeError, ponieważ SQLAlchemy przechodzi przez port jako łańcuch, a MySQLdb oczekuje int. :/ –

5

W moim setupie (używam mysql-python) używam 127.0.0.1 zamiast localhost w url MySQL SQLAlchemy. Kompletny url używam właśnie dla tego scenariusza (tunel z lokalnego portu 3307) jest:

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

Używam SQLAlchemy 1.0.5, ale myślę, że nie ma znaczenia zbyt wiele ...

+2

Rzeczywiście, 127.0.0.1 to localhost, @ BK435, ale nie działa z localhost zamiast z 127.0.0.1. Wydaje się, że wynika to z tego, jak musql radzi sobie z "localhostem", nalegając na łączenie się przez gniazda systemu plików zamiast gniazd TCP. Dlatego w pytaniu wspomniano o opcji --protocol = tcp dla mysql. Ale wygląda na to, że 127.0.0.1 robi lewę i jest prostsze niż obecna odpowiedź. – jgbarah

Powiązane problemy