Как подключить базу данных MySQL с помощью Python+SQLAlchemy удаленно?

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

когда я использую MySQL-client в моей консоли и указываю"

2 ответов


классический ответ на этот вопрос-использовать 127.0.0.1 или IP хоста или хоста вместо "имя" localhost. От документация:

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

и затем:

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


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

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

используя 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-соединение (я знаю, что из-за номера порта после имени хоста). С другой стороны:--14-->

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

нет порта после хоста: это сокет UNIX.


в моей настройке (я использую mysql-python) просто используя 127.0.0.1 вместо localhost в MySQL SQLAlchemy url работает. Полный url, который я использую именно для этого сценария (туннель с локальным портом 3307):

mysql:/user:passwd@127.0.0.1:3307/

Я использую SQLAlchemy 1.0.5, но я думаю,что это не имеет большого значения...