使用 mssql-odbc 驱动(预览版)

mssql-python 加载两个原生ODBC提供商之一:

Provider 它是什么 Status
msodbcsql18 Microsoft ODBC 驱动 18 for SQL Server,成熟的 C++ 驱动程序 默认,未变
mssql-odbc 一个用Rust编写的新ODBC驱动 预览,选择启用

本文涵盖mssql-odbc0.3.0版本、当前由mssql-python使用的版本,以及它与msodbcsql18的不同之处。

Note

mssql-odbc 正在积极开发和验证中。 它还不是 Microsoft ODBC Driver 18 的完全替代品。 暂时保持 msodbcsql18 作为生产默认。 开发团队计划在即将发布的版本中弥补预览空白,但本文中明确指出的有意排除项除外。

Availability

驱动程序以预构建的 wheel 包形式包含在 mssql-python-rs 软件包中,适用于 CPython 3.10 及更高版本:

Platform Architectures
Windows x64;CPython 3.11+ 上的 ARM64
macOS Universal 2(x86_64 + arm64),macOS 15 或更高版本
Linux (glibc) x86_64,aarch64—— manylinux_2_28 和 manylinux_2_34
Linux(musl) x86_64,aarch64 — musllinux_1_2

启用驱动程序

该 mssql-python 软件包依赖于 mssql-python-rs,因此正常安装会附带 Rust 驱动:

pip install mssql-python

如果你用 --no-deps 安装,或从私有索引安装,也要明确安装 mssql-python-rs 。

在 第一个连接之前选择提供者,可以使用环境变量:

PowerShell:

$env:MSSQL_PYTHON_NATIVE_PROVIDER = "mssql-odbc"

Bash 或 Zsh:

export MSSQL_PYTHON_NATIVE_PROVIDER=mssql-odbc

或者在 Python 中:

import mssql_python

mssql_python.native_provider = "mssql-odbc"

使用应用程序现有的连接字符串进行连接。 保持启用证书验证(Encrypt=yes;TrustServerCertificate=no)。 关于认证和证书设置,请参见 连接字符串 和 加密与证书。

connection = mssql_python.connect(connection_string)

驱动程序在选择提供程序时适用以下规则:

  • MSSQL_PYTHON_NATIVE_PROVIDER环境变量优先于native_provider。 冲突的属性赋值会输出RuntimeWarning。
  • 选择在连接字符串验证后且在构建原生连接之前变得固定。 后续的连接失败不会清除该选择。 早期的连接字符串解析错误或缺少提供程序包并不能修复所选内容。 选择被固定后,将 native_provider 更换为其他供应商会发出 RuntimeWarning 信号,且不会产生任何影响。 重新启动该流程以切换提供程序。
  • 未识别的服务提供商名称会引发 ValueError;驱动程序不会回退到默认提供商。 给 native_provider 分配未知名称时会立即引发错误。 当你尝试连接时,环境变量中存在未知名称会引发错误。
  • 将 native_provider 设置为 None,以在属性选择固定之前将其清除。 环境变量依然优先。

调用 mssql_python.get_native_provider_info() 以检查所选提供程序、选择来源,以及选择是否固定。 连接前,这会报告选择情况,而不是本地驱动成功加载的证明。

要返回,可以将变量设置为 msodbcsql18,或者取消设置,并从代码中移除任何对 native_provider 的赋值(或将其设置为 "msodbcsql18")。 然后重新开始这个过程。

当前可行的做法

mssql-odbc驱动程序实现了mssql-python调用的所有 ODBC 函数,因此大多数应用可以在不修改代码的情况下切换提供程序。 查看 已知问题 以了解剩余差异。

Area 备注
连接生命周期 连接、close()、with 块、登录超时、诊断以及更改当前数据库。 连接字符串设置包括 IpAddressPreference、PacketSize、KeepAlive、ConnectRetryCount、 / 和 ConnectRetryIntervalMultiSubnetFailoverApplicationIntent(空闲连接弹性)。
Authentication SQL 认证(UID / PWD);Windows 身份验证(Trusted_Connection=Yes,在 Windows 上使用 SSPI,在 Linux 和 macOS 上使用 Kerberos);以及 Microsoft Entra 交互式、设备代码、服务主体、托管身份、默认凭据和访问令牌。 Entra 集成和密码身份验证不受支持;参见已知问题。
TLS Encrypt、TrustServerCertificate、HostnameInCertificate 和 ServerCertificate。
查询执行 直接执行、预处理执行、预处理计划的重复使用、qmark 参数,以及 pyformat 转换 mssql-python 的执行。
ODBC 转义语法 函数、日期/时间、外连接、GUID、LIKE ... {escape ...}、区间和 {encrypt ...} 转义形式。
存储过程 用 T-SQL 或通过 execute() 的位置语法 {call ...} 调用它们,读取结果集,然后用 nextset() 推进。
输入参数 标量参数、SQL NULL、SQL setinputsizes() 以及混合的常规/流式参数。
较大参数 大文本和二进制参数通过普通绑定路径传输到服务器;XML和UDT参数的限制如下。
executemany() 使用 ODBC 参数数组批量处理。 包含流式值的行会回退为逐行执行。
行提取 fetchone(), fetchmany(), fetchall(), 迭代, fetchval(), 类型转换,以及大文本/二进制流式。
箭头获取 arrow_batch()、 arrow()和 arrow_reader()。 需要 pyarrow。
多个结果集 nextset(),包括参数数组产生的结果。
Transactions 自动提交、提交、回滚、在块 with connect(...) 结束时发生的自动提交(或如果有错误时回滚),以及读未提交、读已提交、可重复读、可序列化和快照隔离级别。
查询超时 将 Connection.timeout(以秒为单位)设置为该连接的游标所执行语句的时间限制;到期时会引发 OperationalError。 0 表示没有超时。 此设置与通过 connect(timeout=...) 传递的登录超时是分开的。
连接池 内置mssql-python连接池,包括从池中获取连接时重置连接,以及针对每个 Microsoft Entra 标识的独立池。
元数据 API tables()、、columns()、primaryKeys()foreignKeys()、statistics()、rowIdColumns()、rowVerColumns()、、 procedures()和getTypeInfo()。
编码与转换工具 默认宽字符编码和输出转换器。 自定义窄字符解码和非Unicode参数转换的限制列于已知问题。

数据类型

你可以读取所有 SQL Server 数据类型,驱动也支持 mssql-python 绑定的所有参数类型。 驱动程序将 xml、vector 和 vector 值作为 str 返回(geometry 作为 JSON 数组),并将 geography、hierarchyid 和 bytes 等 CLR 类型作为 json 返回。 关于其他 Python 映射,请参见数据类型映射。 关于类型特定的限制,请参见 已知问题。

已知问题

在从 msodbcsql18 切换工作负载前,先检查这些差异。

Issue Details Workaround
Microsoft Entra 集成身份验证 不支持 Authentication=ActiveDirectoryIntegrated。 Windows 身份验证(Trusted_Connection=Yes)不受影响。 使用其他 Microsoft Entra 方法,或者保留 msodbcsql18。
Microsoft Entra 密码身份验证 Authentication=ActiveDirectoryPassword 不支持,也没有计划支持,因为这种方法无法满足多重身份验证。 SQL认证(UID / PWD)不受影响。 可以使用其他 Microsoft Entra 方法,比如服务主体、托管身份或访问令牌。
attrs_before设置 认证、应用意图和多子网故障转移不能作为数字属性设置。 除查询超时外,其他语句属性都不被接受。 使用等效的连接字符串关键词。
连接操作超时 set_attr(SQL_ATTR_CONNECTION_TIMEOUT, ...) 接受并存储该值,但在 0.3.0 中不会强制执行超时机制。 用于 connect(timeout=...) 登录和 Connection.timeout 语句;这两者都不是通用连接操作超时时间。
多地址主机 msodbcsql18 默认启用透明网络 IP 解析(TNIR);mssql-odbc 不支持 TNIR。 mssql-python 在使用任一提供程序时都会拒绝 TransparentNetworkIPResolution 连接字符串关键字。 没有 MultiSubnetFailover=Yes,地址一次只尝试一个,因此无法到达的地址可能会延迟连接。 服务器辅助的DNS缓存和增强路由不会被协商。 为可用性组监听器和其他多地址主机设置 MultiSubnetFailover=Yes。
DNS 暂时性故障 如果DNS查询失败,驱动不会回退到最后成功地址。 (#457) 重试连接。
数据分类 敏感度分类元数据不可用,并且不支持 SQL_COPT_SS_DATACLASSIFICATION_VERSION (1400)。 查询 sys.sensitivity_classifications。
多线程 多线程使用尚未被验证。 为多线程工作负载保留 msodbcsql18。
fork() 连接后 在 Linux 上,父进程连接后 fork 出的进程在使用驱动时可能会卡住,即使使用新的连接。 启用池化后,父节点也会挂起。 (#566) 使用 spawn 启动方法,并在每个工作线程内部连接。
取消正在运行的报表 正在进行的查询或提取不能被中断。 例如,关闭 arrow_reader() 并不会停止另一个线程中正在进行的读取操作。 使用 Connection.timeout 来限制长时间运行的语句。
未读结果 关闭光标或运行另一个语句会读取并丢弃剩余结果,而不是取消这些结果,这可能会很慢。 关闭使用预备语句的光标会忽略 Connection.timeout,并可能在服务器停止响应时挂起。 (#546) 只取你需要的行,例如使用TOP。
大型参数和 UDT 参数 作为 SQL_SS_XML 或通过 SQL_SS_UDT 到 setinputsizes() 绑定的值会缓冲在内存中,而不是以流方式传输。 将 xml 值作为普通字符串绑定。
空 image 值 一个空的、非NULL的SQL Serverimage值被返回为None,而非b""。 阅读 CAST(image_column AS varbinary(max)),或者在空值/NULL 的区别很重要时使用 msodbcsql18。
非Unicode字符串参数 绑定为 char / varchar 到 setinputsizes() 的字符串在代码页 437、代码页 850 和 UTF-8 排序中可能被错误编码。 使用默认字符串绑定。
Windows上的遗留代码页解码 使用 setdecoding(SQL_CHAR, encoding="cp1252") 或其他遗留代码页时,文本可能被错误解码或返回为 bytes,因为驱动程序将 char / varchar 数据作为 UTF-8 返回。 使用默认的: conn.setdecoding(mssql_python.SQL_CHAR)。
Connection.getinfo() SQL_USER_NAME 返回连接字符串 UID,而不是数据库用户。 当没有 UID 到达驱动程序时,它是空的。 某些能力值和基于数据包大小的限制与 msodbcsql18不同。 将 SELECT USER_NAME() 用作数据库用户。
内存耗尽错误 一些驱动程序分配失败会终止 Python 进程,而不是引发MemoryError异常。 (#484) 限制你发送和取回的值大小。
大值读取性能 在一项基准测试中,数据分块读取varchar(max) / nvarchar(max)速度略慢于使用msodbcsql18时。 (#473) 对你的工作负载进行基准测试。

此列表并不详尽。

报告问题

如果遇到缺陷,选择 msodbcsql18,重启进程,检查该行为是否仍然存在。 同时移除任何冲突的 Python 端提供者分配。 这种比较有助于定位问题;它本身并不能证明其根源。 请附上 mssql_python.get_native_provider_info() 的输出、您的平台以及失败的 SQL 或错误信息:

对于 Rust 驱动的诊断,在启动 Python 前先设置这些变量,并在选中 mssql-odbc 的情况下重现问题。 例如,在 PowerShell 中:

$env:MSSQL_TDS_TRACE = "true"
$env:MSSQL_TDS_TRACE_LEVEL = "warn,mssqlodbc=debug"
$env:MSSQL_TDS_TRACE_DIR = "./traces"

MSSQL_TDS_TRACE 启用追踪, MSSQL_TDS_TRACE_LEVEL 选择日志过滤器,并 MSSQL_TDS_TRACE_DIR 写入每个进程的文件而非 stderr。 更改这些设置后重启 Python。 追踪可以包含SQL文本和参数值。 在分享相关摘录前,请审查并遮蔽敏感数据,诊断后关闭追踪功能。