MySQLにリモートでアクセスするのが困難です。 SSHトンネルを使用し、Python + SQLALchemyを使用してデータベースMySQLに接続したい。
コンソールでMySQLクライアントを使用し、「ptotocol=TCP
」を指定すると、すべて正常です。私はコマンドを使用します:
mysql -h localhost —protocol=TCP -u USER -p
SSHトンネルを介してリモートデータベースにアクセスできます。
ただし、Python + SQLAchemyを使用してデータベースに接続する場合、—protocol=TCP
のようなオプションは見つかりません。そうしないと、ローカルMySQLデータベースにしか接続できません。教えてください、SQLAlchemyを使用してそれを行う方法はありますか。
この問題に対する古典的な答えは、「特殊名」localhost
の代わりに127.0.0.1
またはホストのIPまたはホスト名を使用することです。 ドキュメント から:
[...] Unix上のlocalhostへの接続は、デフォルトでUnixソケットファイルを使用して行われます。
以降:
Unixでは、MySQLプログラムはホスト名localhostを特別に処理します。他のネットワークベースのプログラム。 localhostへの接続の場合、MySQLプログラムはUnixソケットファイルを使用してローカルサーバーへの接続を試みます。これは、ポート番号を指定するために--portまたは-Pオプションが指定されている場合でも発生します。クライアントがローカルサーバーにTCP/IP接続を行うようにするには、-Hostまたは-hを使用して、ホスト名の値127.0.0.1、またはIPアドレスまたはローカルサーバーの名前を指定します。
ただし、この単純なトリックはあなたのケースでは機能しないように見えるため、何らかの方法でforceを使用する必要がありますTCPソケット。コマンドラインでmysql
を呼び出すときは、--protocol tcp
オプションを使用します。
here で説明したように、SQLAlchemyから、connect_args
キーワード引数を使用して、関連オプション(ある場合)をURLオプションとしてドライバーに渡すことができますまたは。
たとえば、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:[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: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接続を使用します(ホスト名の後のポート番号のためにそれを知っています)。
>>> 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:[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: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',)]
hostnameの後にポートがありません:これはUNIXソケットです。