mssql-django 的连接选项

本文将介绍您的 Django OPTIONS 配置中的 DATABASES 字典设置。 这些设置控制了如何mssql-django连接到 SQL Server。

Python数据库驱动选择

mssql-django 2.0及更高版本通过pyodbc(默认)或 Microsoft 的 mssql-python 驱动程序进行连接。 使用 python_driver 选项为数据库别名选择 mssql-python:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<database>",
        "USER": "<user_id>",
        "PASSWORD": "<password>",
        "HOST": "<server>",
        "PORT": "1433",
        "OPTIONS": {
            "python_driver": "mssql_python",
        },
    },
}

不要在此路径上设置 driver。 mssql-python 路径会忽略 driver、dsn、host_is_server 和 unicode_results 选项,根据允许列表验证 extra_params,并且不启用 MARS。 有关行为差异的完整列表,请参见 MSSQL-django 的“选择数据库驱动程序”。 除非另有说明,本文其余部分介绍的是默认的 pyodbc 路径。

ODBC 驱动程序选择

在 pyodbc 路径上,后端默认使用 SQL Server 的 ODBC Driver 18。 如果未安装 ODBC 驱动程序 18,后端会自动回退到 ODBC 驱动程序 17。 显式配置的驱动不会回退。

Note

ODBC 驱动程序 18 默认启用 Encrypt=yes 并验证服务器证书。 在 Driver 17 中可正常工作的连接可能会因 SSL/TLS 信任错误而失败。 若要解决故障,请执行以下命令:

  • 对于本地SQL Server,请从客户端已信任的证书颁发机构安装服务器证书,或将现有服务器证书导入到每个客户端信任存储中。 有关说明,请参阅配置用于加密连接的SQL Server 数据库引擎。
  • 如果通过 IP 地址或与证书主题或主题备用名称(SAN)不匹配的别名进行连接,请将 HostNameInCertificate=<name-from-certificate> 添加到 extra_params。

如需在本地开发中使用自签名证书,请参阅 TrustServerCertificate中的 。

可以显式指定驱动程序:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 17 for SQL Server",
        },
    },
}

在 Linux 上,还可以指定驱动程序库的完整路径:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.0.so.1.1",
        },
    },
}

DSN 与 HOST

你可以使用 HOST 名称或命名 DSN(数据源名称)进行连接。

使用 HOST 进行连接

大多数配置直接使用 HOST 设置:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

使用 DSN 进行连接

使用在 ODBC 数据源中配置的已命名 DSN:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "OPTIONS": {
            "dsn": "MyDataSourceName",
        },
    },
}

FreeTDS 支持

若要将 FreeTDS 用作 ODBC 驱动程序,请设置为 host_is_serverTrue. 这会告知后端直接使用 HOST 和 PORT,而不是在 freetds.conf 中查找数据服务器名称:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "FreeTDS",
            "host_is_server": True,
        },
    },
}

有关使用 FreeTDS 的无 DSN 连接的详细信息,请参阅 FreeTDS 用户指南。

额外的 ODBC 参数

使用 extra_params 传递其他 ODBC 连接字符串参数。 该值是一个以分号分隔并附加到连接字符串中的字符串:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>.database.windows.net",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "TrustServerCertificate=yes;ApplicationIntent=ReadOnly",
        },
    },
}

此设置还用于Microsoft Entra身份验证关键字。

连接到 Azure SQL 数据库、Azure SQL 托管实例、Microsoft Fabric 中的 SQL 数据库、可用性组侦听器或故障转移群集实例时,请将 MultiSubnetFailover=Yes 添加到 extra_params。 当服务器名称解析到多个IP地址时,驱动程序会同时连接到所有这些地址,并使用第一个响应的地址。 如果没有它,驱动程序会一次尝试一个地址,而某个地址如果没有响应,就会消耗掉剩余的身份验证超时时间,之后驱动程序才会继续尝试下一个地址。 当DNS解析到单一地址时,驱动会尝试一次连接,因此该设置可以安全保持。

MultiSubnetFailover=Yes 具有以下限制:

  • 你不能通过TCP以外的协议使用它。

  • 连接到配置超过64个IP地址的SQL Server实例会失败。

  • 你不能用它来配合数据库镜像。 当连接字符串指定Failover_Partner时,驱动程序会返回错误,同时服务器报告数据库已镜像。 所有支持的 SQL Server 版本均已弃用数据库镜像。 请使用 Always On 可用性组来替代其他解决方案。

注意

TrustServerCertificate=yes仅用于具有自签名证书的本地开发。 请勿在生产环境中使用它。 它禁用证书链验证并增加中间攻击者的风险。 在服务器上安装受信任的证书,并使用 TrustServerCertificate=no 进行连接。

关闭火星

在 pyodbc 路径中,后端在 Windows 上使用 Microsoft ODBC 驱动程序时,会默认启用多个活动结果集(MARS)。 一些端点拒绝该MARS_Connection关键词,包括 Microsoft Fabric Warehouse。 要连接到这些端点之一,在该别名extra_params中设置MARS_Connection=no:

DATABASES = {
    "warehouse": {
        "ENGINE": "mssql",
        "NAME": "<database>",
        "USER": "<user_id>",
        "PASSWORD": "<password>",
        "HOST": "<server>.datawarehouse.fabric.microsoft.com",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryServicePrincipal;MARS_Connection=no",
        },
    },
}

从 mssql-django 2.0 开始,会尊重显式指定的 MARS_Connection 值,且匹配时忽略大小写,因此后端不会追加一个与之冲突的默认值。 在1.8.0及更早版本中,Windows默认覆盖了显式值,导致连接失败。

禁用 MARS 时,QuerySet.iterator() 会先将整个结果集读入内存,然后再返回各行,以便嵌套查询可以复用该连接。 将大型查询集的内存开销考虑在内。

对于其他认证方法,保留对应的认证设置,并附加 MARS_Connection=no 于 extra_params。 该连接设置并不意味着对 Django 迁移或其他 SQL Server 功能有完全的 Microsoft Fabric Warehouse 支持 。

mssql-python路径不启用MARS并拒绝该MARS_Connection关键词,因此该设置仅pyodbc适用于。

连接超时和重试

使用超时和重试设置配置连接弹性:

选项 默认 Description
connection_timeout 0 (已禁用) 等待连接的最大秒数。
connection_retries 5 连接失败时重试次数。
connection_retry_backoff_time 5 每次重试之间等待的秒数。
query_timeout 0 (已禁用) 等待查询完成的最大秒数。

示例:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "connection_timeout": 30,
            "connection_retries": 3,
            "connection_retry_backoff_time": 10,
            "query_timeout": 120,
        },
    },
}

connection_timeout=0 是MSSQL-Django的默认设置。 由于 pyodbc 仅在你提供正值时才会调用 SQLSetConnectAttr(SQL_ATTR_LOGIN_TIMEOUT, ...),因此将采用 依赖于驱动程序的默认值(对于 Microsoft ODBC Driver for SQL Server,为 15 秒)。 设置一个明确的值,让无响应的连接尝试会被预测失败。

如果目标是 Azure SQL 数据库无服务器且已启用自动暂停,请至少使用60。 自动暂停的数据库在首次连接尝试时恢复,该尝试可能因错误40613而失败,而数据库则继续。 由于超时时间较短,第一次连接尝试会在恢复完成之前超时。 connection_retries 最终成功了,但第一个请求需要多次超时才连接。 更多信息请参见 自动暂停和自动恢复。

Collation

为文本字段查找设置自定义排序规则:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "collation": "Chinese_PRC_CI_AS",
        },
    },
}

多个数据库连接

Django 支持同时连接到多个数据库。 这对于只读副本、跨数据库查询或按隔离级别分隔工作负荷非常有用。

配置多个数据库

定义设置中的每个 DATABASES 连接:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "app_db",
        "HOST": "<your-primary-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
    "readonly": {
        "ENGINE": "mssql",
        "NAME": "app_db",
        "HOST": "<your-readonly-replica>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Encrypt=yes;ApplicationIntent=ReadOnly",
        },
    },
    "analytics": {
        "ENGINE": "mssql",
        "NAME": "analytics_db",
        "HOST": "<your-analytics-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "isolation_level": "READ UNCOMMITTED",
        },
    },
}

注意

READ UNCOMMITTED 允许脏读。 仅将此隔离级别用于不需要绝对准确性的报告或分析查询。 有关详细信息,请参阅 事务管理。

使用数据库路由器对查询进行路由

创建数据库路由器以将读取和写入操作定向到相应的连接:

class ReadReplicaRouter:
    """Route read queries to the readonly replica, writes to the primary."""

    def db_for_read(self, model, **hints):
        return "readonly"

    def db_for_write(self, model, **hints):
        return "default"

    def allow_relation(self, obj1, obj2, **hints):
        return True

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return db == "default"

在 settings.py 中注册路由器:

DATABASE_ROUTERS = ["myproject.routers.ReadReplicaRouter"]

将路由器类保存在文件中,例如 myproject/routers.py。

直接查询特定数据库

using()使用该方法查询特定的数据库别名:

# Explicit read from analytics database
reports = AnalyticsReport.objects.using("analytics").filter(date__gte="2025-01-01")

# Write to default
Product.objects.create(name="Widget", price=9.99)

有关按连接划分的数据库中的隔离级别的详细信息,请参阅 在不发生阻塞的情况下读取数据。