2015-03-30 4 views
7

У меня возникли трудности с удаленным доступом к MySQL. Я использую SSH-туннель и хочу подключить базу данных MySQL с помощью Python + SQLALchemy.Как подключить базу данных MySQL с помощью Python + SQLAlchemy удаленно?

Когда я использую MySQL-клиент в своей консоли и указываю «ptotocol=TCP», тогда все в порядке! Я использую команду:

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

я получить доступ к удаленной базе данных через SSH-туннель.

Однако, когда я хочу подключиться к базе данных с помощью Python + SQLAchemy, я не могу найти такую ​​опцию, как —protocol=TCP В противном случае я подключаюсь только к локальным базам данных MySQL. Скажите, пожалуйста, есть ли способ сделать это с помощью SQLAlchemy.

+0

настройте туннель ssh, затем укажите локальный mysql в порту туннеля на локальной машине. mysql не будет знать, что он туннелирован, и ssh позаботится о перенаправлении всего, куда он должен идти. –

+0

туннель уже установлен из X.X.X.X: 3306 -> localhost: 3306 Возможно, мне нужно настроить туннель на другой порт, например localhost: 3307? – strevg

+0

@strevg Чтобы уточнить, у вас есть сервер MySQL, работающий на вашем локальном хосте. И второй сервер MySQL, доступный удаленно через SSH-туннель. Оба работают одновременно? Какой сервер связан с каким портом на вашем локальном хосте? –

ответ

12

Классический ответ на этот вопрос заключается в использовании 127.0.0.1 или IP хост или имя хоста вместо «специального названия» localhost. Из documentation:

[...] соединения на Unix для локального хоста сделаны с использованием файла сокета Unix по умолчанию

И далее:

На Unix, Программы MySQL обрабатывают имя хоста localhost специально, что может отличаться от ожидаемого по сравнению с другими сетевыми ресурсами, основанные программы. Для соединений с localhost программы MySQL пытаются подключиться к локальному серверу с помощью файла сокета Unix. Это происходит, даже если задана опция -port или -P для указания номера порта. Чтобы клиент установил TCP/IP-соединение с локальным сервером, используйте -host или -h, чтобы указать значение имени узла 127.0.0.1 или IP-адрес или имя локального сервера.


Однако этот простой трюк, как представляется, не работать в вашем случае, так что вы должны каким-то образом силу использование сокета TCP. Как вы объяснили это самостоятельно, при вызове mysql в командной строке вы используете опцию --protocol tcp.

Как пояснил here, из SQLAlchemy, вы можете передать соответствующие параметры (если таковые имеются) в драйвере либо в качестве опции URL или используя аргумент connect_args ключевое слово.

Например, используя 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, где у меня были нестандартные «порт» и «unix_socket», которые мне нужно было установить. –

+0

К сожалению, MySQLdb, похоже, стал более строгим. Теперь вы получаете TypeError, beacuse SQLAlchemy передает в порт строку, а MySQLdb ожидает int. :/ –

5

В моей настройке (я использую mysql-python), используя 127.0.0.1 вместо localhost в MySQL SQLAlchemy url works. Полный 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. Вот почему в вопросе упоминается опция -protocol = tcp для mysql. Но похоже, что 127.0.0.1 делает трюк и проще, чем текущий ответ. – jgbarah

 Смежные вопросы

  • Нет связанных вопросов^_^