You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyODBC通过AAD认证连接Azure SQL Server的重复连接失败问题

解决pyodbc+AAD认证连接Azure SQL首次成功后续失败的问题

我之前在类似的环境里碰到过这个问题,结合你的场景(Python 2.7.14 + Debian 9 + SQL Server ODBC驱动 + Azure SQL AAD认证),这个08开头的错误大概率和连接池复用过期AAD令牌、驱动资源未正确释放有关,下面是几个亲测有效的解决办法:

1. 显式禁用pyodbc连接池

pyodbc默认会启用连接池,但在AAD认证场景下,连接池可能会复用已经过期的AAD令牌,导致后续连接失败。你可以在创建连接时直接关闭连接池:

import pyodbc

def get_db_connection():
    conn_str = (
        'DRIVER={ODBC Driver 17 for SQL Server};'
        'SERVER=your-server.database.windows.net;'
        'DATABASE=your-database;'
        'UID=your-aad-account@your-tenant.com;'
        'PWD=your-password;'
        'Authentication=ActiveDirectoryPassword;'
        'Pooling=False'  # 关键:禁用连接池,避免复用过期令牌
    )
    conn = pyodbc.connect(conn_str)
    return conn

# 使用后务必关闭连接
conn = get_db_connection()
# 执行数据库操作...
conn.close()

一定要记得每次使用完连接后显式调用close(),确保资源被释放。

2. 升级ODBC驱动到最新兼容版本

Debian 9上的旧版ODBC驱动(比如13.x版本)存在AAD认证连接复用的bug,建议升级到支持Debian 9的最新ODBC驱动(比如17.x版本),升级后重新测试多次连接的场景。

3. 手动管理AAD令牌(非密码认证场景适用)

如果你的场景是用服务主体、托管身份等非密码方式做AAD认证,可以手动获取AAD令牌并传入连接字符串,跳过驱动内部的令牌缓存逻辑:

import pyodbc
import adal

# 手动获取AAD访问令牌
auth_context = adal.AuthenticationContext('https://login.microsoftonline.com/your-tenant-id')
token_response = auth_context.acquire_token_with_client_credentials(
    resource='https://database.windows.net/',
    client_id='your-service-principal-client-id',
    client_secret='your-service-principal-secret'
)
access_token = token_response['accessToken']

# 使用令牌建立连接
conn_str = (
    'DRIVER={ODBC Driver 17 for SQL Server};'
    'SERVER=your-server.database.windows.net;'
    'DATABASE=your-database;'
    'UID=;'
    'PWD=' + access_token + ';'
    'Authentication=ActiveDirectoryAccessToken;'
    'Pooling=False'
)
conn = pyodbc.connect(conn_str)

这种方式每次连接都会获取全新的有效令牌,从根源上避免了令牌过期导致的连接失败。

4. 检查全局ODBC配置

查看系统级的ODBC配置文件/etc/odbcinst.ini,确保对应驱动的配置里没有全局启用连接池。可以在驱动的配置段添加:

[ODBC Driver 17 for SQL Server]
Description=Microsoft ODBC Driver 17 for SQL Server
Driver=/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.1.1
UsageCount=1
Pooling = No  # 全局禁用该驱动的连接池

你可以用下面的脚本测试多次连接的情况,验证解决方案是否生效:

import pyodbc

def test_connection():
    try:
        conn = pyodbc.connect(
            'DRIVER={ODBC Driver 17 for SQL Server};'
            'SERVER=your-server.database.windows.net;'
            'DATABASE=your-database;'
            'UID=your-aad-account;'
            'PWD=your-password;'
            'Authentication=ActiveDirectoryPassword;'
            'Pooling=False'
        )
        cursor = conn.cursor()
        cursor.execute("SELECT GETDATE()")
        print(f"连接成功,当前数据库时间:{cursor.fetchone()[0]}")
        conn.close()
    except Exception as e:
        print(f"连接失败: {str(e)}")

# 测试5次连续连接
for i in range(5):
    print(f"\n第{i+1}次连接测试")
    test_connection()

内容的提问来源于stack exchange,提问作者Hassan Mehmood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:26:53