使用SSH隧道从远程服务器上的MariaDB读取数据

时间:2017-01-05 11:32:27

标签: python ssh mariadb spyder ubuntu-server

以下设置:在我的本地Windows机器上,我使用Python 3.5运行Spyder。此外,我有一个带有MariaDB的远程Ubuntu服务器。我想要做的是使用SSH隧道和sqlalchemy将数据从数据库加载到Spyder。

我正在研究的两个解决方案是:

(i)按照here所述,然后在Spyder中使用PuTTY进行SSH隧道到服务器:

import mysql.connector
from sqlalchemy import create_engine

import pandas as pd

engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1/db')
dbconn = engine.connect()

rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()

这在性能方面表现良好,但我已经打开了PuTTY并构建了SSH隧道,作为此过程中的额外步骤。

(ii)使用包sshtunnel,从而避免PuTTY额外步骤:

from sshtunnel import SSHTunnelForwarder

import mysql.connector
from sqlalchemy import create_engine

import pandas as pd

server = SSHTunnelForwarder(
    (hostname, 22),
    ssh_username=un_server, \
    ssh_password=pw_server,
    remote_bind_address=('127.0.0.1', 3306))

server.start()

engine = create_engine('mysql+mysqlconnector://un_db:pw_db@127.0.0.1:' \
    + str(server.local_bind_port) + '/db')
dbconn = engine.connect()

rslt = dbconn.execute("SELECT * FROM table WHERE col1=x AND col2=y;")
df = pd.DataFrame(rslt.fetchall())
df.columns = rslt.keys()

构建SSH隧道工作正常(我认为)但是当我执行查询时,Spyder中的IPython控制台会挂起。

问题:为什么我的用例适用于PuTTY而不适用于sshtunnel包?通过PuTTY的SSH隧道和通过sshtunnel的一个隧道有什么区别吗?

2 个答案:

答案 0 :(得分:0)

您有两种类似的解决方案。

(i)在这种情况下,您将创建转发过程。 (不是python进程)

(ii)在这种情况下server.start()启动新的python转发线程。这个线程做了类似的工作。但它是python线程,线程将一直工作,直到它被停止。也许这就是你遇到问题的原因。

基于这个问题,我可以提出三种解决方案。

  1. 您可以使用sshtunnel创建转发流程,例如PuTTY。来自自述文件:python -m sshtunnel -U username -P password -L :3306 -R 127.0.0.1:3306 -p 22 localhost

  2. 您可以使用server.stop()来停止sshtunnel转发线程。

  3. 您还可以使用with语句语法进行自动停止 (sshtunnel#example-2

答案 1 :(得分:0)

我将驱动程序从mysql.connector切换到MySQLdb,新的解决方案(ii)现在可以使用:

from sshtunnel import SSHTunnelForwarder
import MySQLdb as mdb
import pandas as pd

server = SSHTunnelForwarder(
    (hostname, 22),
    ssh_username=un_server, \
    ssh_password=pw_server,
    remote_bind_address=('127.0.0.1', 3306))

server.start()

con = mdb.connect('127.0.0.1', un_db, pw_db, port=server.local_bind_port)

df = pd.read_sql("SELECT * FROM table WHERE col1=x AND col2=y", con)

con.close()
server.stop()