mssql-django 的连接选项

本文将介绍您的 Django OPTIONS 配置中的 DATABASES 字典设置。 这些设置控制如何mssql-django通过 ODBC 驱动程序连接到SQL Server。

ODBC 驱动程序选择

mssql-django 1.7 开始,后端默认为 ODBC Driver 18 for SQL Server。 如果未安装 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. 这会告知后端直接使用 HOSTPORT,而不是在 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 进行连接。

连接超时和重试

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

选项 默认 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)

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