ARM架构Linux连接SQL Server 2012时ODBC驱动SSL协议不兼容问题
问题场景
在ARM架构的Linux服务器上,使用Python结合SQLAlchemy连接Windows Server上的远程SQL Server 2012数据库,连接代码如下:
import urllib from sqlalchemy import create_engine import os from dotenv import load_dotenv from sqlalchemy.orm import sessionmaker load_dotenv() class Database: server = str(os.getenv('DB_HOST')) + "," + str(os.getenv('DB_PORT')) database = os.getenv('DB_DATABASE') username = os.getenv('DB_USER') password = os.getenv('DB_PASSWORD') params = ('DRIVER={ODBC Driver 18 For SQL Server};SERVER=' + server + ';DATABASE=' + str(database) + ';UID=' + username + ';PWD=' + password+";Encrypt=no;TrustServerCertificate=yes") engine = create_engine("mssql+pyodbc:///?odbc_connect=%s" % params, pool_size=10, max_overflow=20) def connection(self): db = sessionmaker(bind=self.engine) conn = db() return conn
所有认证信息存储在.env文件中,连接时出现如下报错:
sqlalchemy.exc.OperationalError: (pyodbc.OperationalError) ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:0A000102:SSL routines::unsupported protocol] (-1) (SQLDriverConnect)')
尝试安装ODBC Driver 17 for SQL Server,但该驱动不支持ARM架构Linux系统。目标SQL Server版本为:
Microsoft SQL Server 2012 - 11.0.2218.0 (X64) Jun 12 2012 13:05:25 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.2 (Build 9200: ).
解决方案
方案一:使用FreeTDS作为替代ODBC驱动(推荐)
微软官方ODBC Driver 17不支持ARM Linux,Driver 18虽支持但默认禁用了SQL Server 2012依赖的旧SSL协议,而FreeTDS是跨平台开源驱动,完美支持ARM架构,适配旧版SQL Server:
安装依赖包
- Debian/Ubuntu系统:
sudo apt update && sudo apt install freetds-dev unixodbc-dev - CentOS/RHEL系统:
sudo yum install freetds-devel unixODBC-devel
- Debian/Ubuntu系统:
修改连接代码
将连接字符串中的DRIVER替换为{FreeTDS},并添加TDS_Version=7.3(SQL Server 2012对应TDS版本为7.3):params = ('DRIVER={FreeTDS};SERVER=' + server + ';DATABASE=' + str(database) + ';UID=' + username + ';PWD=' + password + ";TDS_Version=7.3;Encrypt=no")其余代码保持不变,重新测试连接即可。
方案二:调整ODBC Driver 18的SSL兼容配置(不推荐)
如果坚持使用微软ODBC Driver 18,可通过强制启用旧SSL协议解决,但会降低安全性:
- 在连接字符串中添加
Protocol=7.3,或修改系统OpenSSL配置文件(如/etc/ssl/openssl.cnf),添加允许TLS 1.0/1.1的配置,但此方法有安全风险,仅用于临时场景。
内容的提问来源于stack exchange,提问作者Hernandez Sinsel Jesus Emmanue

