Python中如何使用pymysql连接需要通过SSH跳转的数据库

MySQL 的数据库所在的服务器需要通过一个跳板机才能连接

像 Sequel Pro 这种软件可以提供这样的功能,但是我现在想用 Python 脚本做一些事情,需要登录数据库,查了一下 pymysql 的方法,好像没看到有这样的支持

不知道有没有什么办法


Python中如何使用pymysql连接需要通过SSH跳转的数据库
6 回复

很简单
打开 google (bing 和 baidu 未测试)
输入关键字 python mysql ssh
点击搜索


import pymysql
from sshtunnel import SSHTunnelForwarder
import paramiko

def connect_via_ssh():
    """
    通过SSH隧道连接数据库的完整示例
    需要先安装:pip install pymysql sshtunnel paramiko
    """
    
    # SSH服务器配置
    ssh_host = 'ssh_server_ip'      # SSH服务器IP
    ssh_port = 22                   # SSH端口,默认22
    ssh_username = 'ssh_user'       # SSH用户名
    ssh_password = 'ssh_password'   # SSH密码(或使用密钥)
    
    # 数据库服务器配置(在SSH服务器内部网络)
    db_host = '127.0.0.1'          # 数据库在SSH服务器本机
    db_port = 3306                 # 数据库端口
    db_user = 'db_user'            # 数据库用户名
    db_password = 'db_password'    # 数据库密码
    db_name = 'database_name'      # 数据库名
    
    # 创建SSH隧道
    # local_bind_address: 本地监听的地址和端口
    # remote_bind_address: 远程数据库的地址和端口
    with SSHTunnelForwarder(
        (ssh_host, ssh_port),
        ssh_username=ssh_username,
        ssh_password=ssh_password,
        remote_bind_address=(db_host, db_port),
        local_bind_address=('127.0.0.1', 3307)  # 本地端口,避免与本地MySQL冲突
    ) as tunnel:
        
        print(f"SSH隧道已建立,本地端口: {tunnel.local_bind_port}")
        
        # 通过隧道连接数据库
        # 注意:host要使用隧道本地地址,port要使用隧道本地端口
        connection = pymysql.connect(
            host='127.0.0.1',          # 本地隧道地址
            port=tunnel.local_bind_port,  # 隧道本地端口
            user=db_user,
            password=db_password,
            database=db_name,
            charset='utf8mb4',
            cursorclass=pymysql.cursors.DictCursor
        )
        
        try:
            # 执行查询示例
            with connection.cursor() as cursor:
                sql = "SELECT VERSION()"
                cursor.execute(sql)
                result = cursor.fetchone()
                print(f"数据库版本: {result}")
                
            # 提交事务(如果是写操作)
            connection.commit()
            
        finally:
            connection.close()

# 使用密钥认证的版本(更安全)
def connect_via_ssh_with_key():
    """
    使用SSH密钥连接(推荐生产环境使用)
    """
    ssh_private_key = paramiko.RSAKey.from_private_key_file(
        '/path/to/private_key.pem'
    )
    
    with SSHTunnelForwarder(
        ('ssh_server_ip', 22),
        ssh_username='ssh_user',
        ssh_pkey=ssh_private_key,
        remote_bind_address=('127.0.0.1', 3306),
        local_bind_address=('127.0.0.1', 3307)
    ) as tunnel:
        
        connection = pymysql.connect(
            host='127.0.0.1',
            port=tunnel.local_bind_port,
            user='db_user',
            password='db_password',
            database='db_name'
        )
        
        # ... 数据库操作代码

if __name__ == '__main__':
    connect_via_ssh()

核心原理:

  1. sshtunnel 创建一个本地端口转发,把本地端口映射到远程数据库
  2. pymysql 连接本地转发端口,数据通过SSH隧道加密传输
  3. SSH隧道建立后,数据库连接就像连接本地服务一样简单

依赖安装:

pip install pymysql sshtunnel paramiko

关键配置说明:

  • remote_bind_address: 数据库在SSH服务器上的地址
  • local_bind_address: 本地监听的地址和端口
  • 连接数据库时,host用127.0.0.1,port用tunnel.local_bind_port

一句话总结:用sshtunnel做端口转发,然后pymysql连本地转发端口。

跳板机的话 你做一个 ssh 隧道不行吗

import sshtunnel

不需要加密: socat 直接转发
需要加密:搜 ssh forwarding
这些工具跟 mysql 无关,有 IP 和端口就行

ssh 转发到本地

回到顶部