Python通过SSH隧道连接Oracle 19c数据库失败求助
Python连接Oracle 19c(SSH隧道)失败排查方案
问题梳理
- 已通过SQL Developer/DBeaver的SSH隧道成功连接Oracle 19c
- Python连接尝试均失败:
- Thin模式:SSH隧道创建成功,但Oracle连接报错
- Thick模式:程序无响应卡住
- 使用sshtunnel库改写代码后仍出现不同错误
分场景排查与修复
1. Thin模式报错修复
核心检查点
- 验证本地映射端口未被占用:
Windows执行netstat -ano | findstr "本地映射端口号";Linux/Mac执行lsof -i :本地映射端口号 - 确保Oracle连接字符串格式正确(19c优先用service_name而非SID):
import cx_Oracle # 替换为实际本地端口、Oracle service_name dsn = cx_Oracle.makedsn("localhost", 15210, service_name="ORCL") conn = cx_Oracle.connect(user="你的Oracle用户名", password="你的Oracle密码", dsn=dsn) - 确认cx_Oracle版本兼容:Oracle 19c需搭配cx_Oracle 8.0+,执行
pip show cx_Oracle查看版本 - 若报错
ORA-12514:从SQL Developer的连接属性中复制准确的service_name(不要自行猜测)
典型错误修复示例
报错
ORA-12541: TNS:no listener
修复:确认SSH隧道映射的是Oracle监听的默认端口1521,且隧道未意外断开
2. Thick模式卡住修复
核心检查点
- 正确加载对应版本的Oracle Instant Client:
import cx_Oracle # 替换为本地19c Instant Client的路径 cx_Oracle.init_oracle_client(lib_dir=r"C:\instantclient_19_18") - 保证客户端与Oracle服务器主版本一致(必须用19c客户端连接19c服务器)
- 临时关闭本地防火墙/杀毒软件:部分安全软件会拦截Thick模式的底层连接
- 开启调试日志定位问题:
查看日志中是否有超时、权限受限等提示import logging cx_Oracle.init_oracle_client(lib_dir=r"...") logging.basicConfig(level=logging.DEBUG)
3. sshtunnel库使用修复
正确代码模板
from sshtunnel import SSHTunnelForwarder import cx_Oracle # 替换为实际SSH与Oracle服务器信息 with SSHTunnelForwarder( ("SSH服务器IP", 22), ssh_username="SSH用户名", ssh_password="SSH密码", # 若用密钥登录,替换为ssh_pkey="/path/to/私钥文件" remote_bind_address=("Oracle服务器内网IP", 1521), local_bind_address=("localhost", 15210) ) as tunnel: dsn = cx_Oracle.makedsn("localhost", tunnel.local_bind_port, service_name="ORCL") conn = cx_Oracle.connect("Oracle用户名", "Oracle密码", dsn) # 测试连接 cursor = conn.cursor() cursor.execute("SELECT * FROM dual") print(cursor.fetchone()) conn.close()
常见问题修复
- 不要用
localhost作为SSH服务器地址,改用公网/内网IP - 在SSH服务器上执行
telnet Oracle服务器IP 1521,验证SSH用户是否有权限访问Oracle监听端口
终极验证步骤
- 本地执行
telnet localhost 15210,能连通说明隧道正常,问题出在Oracle连接配置 - 用SQL Developer直接连接本地映射端口(无需SSH),若成功则排除Oracle端问题
- 尝试用
oracledb(cx_Oracle的升级版本)连接:import oracledb oracledb.init_oracle_client(lib_dir=r"...") conn = oracledb.connect(user="...", password="...", dsn="localhost:15210/ORCL")
内容的提问来源于stack exchange,提问作者Nándor Zaja
相关产品推荐
相关产品推荐

