该go-mssqldb驱动程序支持连接 Azure SQL 数据库、Azure SQL 托管实例 以及 Microsoft Fabric 中的 SQL 数据库。 本文涵盖了Azure特有的配置、认证、连接限制以及与本地SQL Server不同的故障排除。
连接到 Azure SQL 数据库
Azure SQL 数据库 默认需要加密连接。 明确指定 encrypt=true 和 TrustServerCertificate=false 以便连接使用 TLS 并验证服务器证书:
db, err := sql.Open("sqlserver",
"sqlserver://<user>:<password>@<server>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false")
if err != nil {
panic(err)
}
Note
如果你省略encrypt了 ,驱动不会自动添加 Azure 特定的 TLS 设置。 在 Azure SQL 连接字符串中保留 encrypt=true&TrustServerCertificate=false。
建议使用无密码认证
Microsoft Entra ID认证会消除连接字符串中的密码。
ActiveDirectoryDefault 自动选择最适合环境的可用凭证,使开发变得更方便:
import (
"database/sql"
"log"
_ "github.com/microsoft/go-mssqldb/azuread"
)
func main() {
db, err := sql.Open("azuresql",
"sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
log.Fatal(err)
}
defer db.Close()
}
Important
ActiveDirectoryDefault 这对开发很方便,但由于它会探测多个凭证来源,可能会增加连接延迟。 对于生产服务,偏好显式方法,如 ActiveDirectoryManagedIdentity 或 ActiveDirectoryServicePrincipal。
ActiveDirectoryDefault 如何解析凭证
ActiveDirectoryDefault 按顺序尝试以下凭据源,并使用第一个成功的凭据源:
| Order | 凭证来源 | 典型环境 |
|---|---|---|
| 1 | 环境变量 (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET) |
CI/CD 管道,Docker 容器 |
| 2 | 工作负载标识 | 具有 Azure Workload Identity 的 Kubernetes Pod |
| 3 | 托管标识 | Azure VMs, App Service, Container Apps, Azure Functions |
| 4 | Azure CLI (az login) |
地方发展 |
| 5 | Azure开发人员 CLI (azd auth login) |
地方发展 |
这种凭证链在开发过程中很 ActiveDirectoryDefault 方便,但顺序探测会给每次新连接增加延迟。 对于生产环境,指定精确的认证方法(例如 ActiveDirectoryManagedIdentity),这样驱动程序可以跳过不必要的检查。
用于生产的管理身份(推荐)
托管在 Azure 中的应用(App Service、Container Apps、Azure Functions 或 Azure VMs)应使用带有明确fedauth值的管理身份。 这种方法避免了凭证链的开销,并消除了对环境变量或CLI状态的任何依赖。
系统分配的托管标识:
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false
用户分配的管理身份 (指定客户端ID):
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false
在数据库中授予身份访问权
在配置 Azure 资源的管理身份后,创建一个包含的数据库用户:
CREATE USER [my-app-identity] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-identity];
ALTER ROLE db_datawriter ADD MEMBER [my-app-identity];
对于系统分配标识,请使用 Azure 资源名称。 对于用户分配的身份,使用身份名。
用于自动化的服务主体
对于CI/CD流水线或服务间认证:
sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false
关于所有凭证类型,请参见 Microsoft Entra ID 认证。
配置Azure防火墙
Azure SQL 数据库 使用服务器级防火墙。 你必须允许客户端的公共IP地址,或者使用私有端点。
错误:无法打开服务器
此错误提示表明 Azure 防火墙正在阻挡您的客户端 IP 地址:
mssql: login error: Cannot open server '<server>' requested by the login.
Client with IP address '<client-ip>' is not allowed to access the server.
解决方案:
- 在 Azure 门户中添加防火墙规则:SQL 服务器>网络>添加防火墙规则。
- 如果您的应用运行在 Azure 中,请启用允许 Azure 服务和资源访问该服务器。
- 对于私有连接,配置一个 私有端点。
错误:连接超时
如果连接超时且未出现明确的错误提示,则防火墙很可能在静默阻止该连接。 先验证防火墙规则。
按服务层划分的连接限制
Azure SQL 数据库 根据服务层级为每个数据库强制执行连接限制。 超过限制会导致新连接的认证失败。 完整的限制表请参见 DTU单数据库资源限制 和 vCore单数据库资源限制。
设置MaxOpenConns以匹配你的等级
始终将 MaxOpenConns 设置为低于你的 Azure SQL 层级连接限制的值:
// Example for S2 tier (60 max workers).
// Leave headroom for Azure management connections and other clients.
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(5 * time.Minute)
Tip
如果多个应用程序共享同一数据库,则将连接限制分配到所有应用程序之间。 例如,如果三个服务共享一个S2数据库(最多60名工作者),每个服务分配15-20个连接。
处理 Azure SQL 限制
当数据库接近资源限制(CPU、IO、内存或会话数量)时,Azure SQL 数据库可以限制连接和查询。 限速表现为特定的错误编号。
常见的节流错误
| 错误号 | 消息模式 | 原因 |
|---|---|---|
| 10928 | Resource ID: %d. The %s limit for the database is %d and has been reached. |
会话或工作线程已达上限。 |
| 10929 | Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. |
资源调速器限流。 |
| 40501 | The service is currently busy. |
通用限流。 请重试。 |
| 40544 | The database has reached its size quota. |
数据库大小已达上限。 在重试前先增加容量或剩余空间。 |
| 40549 | Session is terminated because you have a long-running transaction. |
交易已超过时间限制。 |
| 40550 | Session is terminated because of too many locks. |
过度获取锁。 |
| 40551 | Session is terminated because of excessive tempdb usage. |
过度使用tempdb。 |
| 40552 | Session is terminated because of excessive transaction log usage. |
事务日志空间已超限。 |
| 40553 | Session is terminated because of excessive memory usage. |
过度消耗内存。 |
| 40613 | Database '%.*ls' on server '%.*ls' is not currently available. |
数据库正在移动或重新配置。 |
| 49918 | Cannot process request. Not enough resources to process request. |
资源耗尽。 |
| 49919 | Cannot process create or update request. |
太多并发的创建/更新操作。 |
| 49920 | Cannot process request. Too many operations in progress. |
已达到并发操作上限。 |
重试受限制的请求
上表中的大多数 Azure SQL 限制错误和可用性错误都是暂时性错误,应采用指数退避方式重试。 错误 40544 不是瞬态的。 这意味着数据库已达到其大小配额,因此,在扩展数据库或删除数据之前,该操作将无法成功完成。
完整的重试实现,请参见 错误处理和重试模式。
import (
"errors"
mssql "github.com/microsoft/go-mssqldb"
)
func isAzureThrottling(err error) bool {
var mssqlErr mssql.Error
if !errors.As(err, &mssqlErr) {
return false
}
switch mssqlErr.Number {
case 10928, 10929, 40501, 40549, 40550, 40551, 40552, 40553,
40613, 49918, 49919, 49920:
return true
}
return false
}
连接复原能力
Azure SQL 数据库 偶尔会重新配置服务器以进行更新、故障转移和负载均衡。 这些事件会断开现有连接,表现为 driver: bad connection 错误。 将池配置为自动恢复:
db.SetConnMaxLifetime(5 * time.Minute) // Rotate connections so stale ones are replaced.
db.SetConnMaxIdleTime(2 * time.Minute) // Recycle before Azure gateway drops idle connections (30 min).
db.SetMaxIdleConns(10) // Keep warm connections for quick recovery.
Note
Azure SQL 的网关会关闭处于空闲状态约 30 分钟的连接。 将 ConnMaxIdleTime 设置为远低于该阈值,以避免在空闲期后的首次查询时出现 driver: bad connection 错误。 对于非事务调用, database/sql 在新连接时会自动重试。 对于事务调用,你的代码必须捕捉错误并重试整个事务。
故障切换后重新连接
在事务之外,当驱动程序将连接标记为不可用时,database/sql 可以透明地重试在不良连接上发起的调用。 这种行为并不是针对限速、故障切换或其他可重试SQL错误的完整瞬态故障重试策略。 将数据库调用封装在重试函数中,以处理这些情况:
var count int
err := RetryFunc(ctx, DefaultRetryConfig, func(ctx context.Context) error {
return db.QueryRowContext(ctx, "SELECT COUNT(*) FROM HumanResources.Employee").Scan(&count)
})
Azure SQL 托管实例
Azure SQL 托管实例 支持与本地 SQL Server 相同的驱动功能,但有一些不同之处:
| 功能 | Azure SQL 数据库 | Azure SQL 托管实例 |
|---|---|---|
| SQL Server 代理 | 不可用 | 可用 |
| 跨数据库查询 | 不可用 | 可用 |
| 链接的服务器 | 不可用 | 可用 |
| 命名管道 | 不可用 | 不可用(仅限TCP) |
| 共享内存 | 不可用 | 不可用(仅限TCP) |
| Windows 身份验证(SSPI) | 不可用 | 在托管的VNet中提供 |
连接到托管实例:
sqlserver://<user>:<password>@<instance>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false
Microsoft Fabric 中的 SQL 数据库
Important
Fabric 中的 SQL 数据库需要 Microsoft Entra ID 认证。 不支持SQL Server认证。
对于生产工作负载,应优先选择显式的 fedauth 模式,而不是 ActiveDirectoryDefault,以避免在建立新连接时产生凭证链探测开销。
Fabric 中的 SQL 数据库支持使用 Microsoft Entra ID 身份验证的 go-mssqldb驱动程序:
db, err := sql.Open("azuresql",
"sqlserver://<server>.database.fabric.microsoft.com?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
panic(err)
}
Azure SQL 性能提示
| Tip | 详细信息 |
|---|---|
| 使用连接池 | Azure SQL 会将每个打开的连接计入tier limit。 保持 MaxOpenConns 受限。 |
启用 encrypt=strict |
为了获得最强的安全性,可以使用TDS 8.0加密: encrypt=strict。 Azure SQL 数据库 支持严格模式。 |
使用 ApplicationIntent=ReadOnly |
将读取密集型查询路由到只读副本:ApplicationIntent=ReadOnly 适用于 Premium、业务关键和超大规模层级。 |
| 监控DTU/vCore使用情况 | CPU、IO 或工作进程使用率较高表明你的层级规格可能偏低。 使用Azure Monitor来跟踪资源利用率。 |
| 保持交易简短 | Azure SQL 会终止超出资源阈值的会话(错误 40549)。 |
| 使用区域终结点 | 把你的应用放在与数据库相同的Azure区域,以尽量减少延迟。 |
Azure SQL 故障排查清单
| 症状 | 可能的原因 | 解决方案 |
|---|---|---|
Cannot open server |
防火墙规则缺失 | 添加你的 IP 或启用 Azure 服务访问。 |
Login failed |
错误的凭证或数据库用户缺失 | 确认登录是否存在且有数据库访问权限。 |
| 连接会间歇性超时 | 服务器重新配置或故障切换 | 实现重试逻辑和连接轮换。 |
Resource limit reached |
太多并发连接 | 降低 MaxOpenConns 并及时关闭连接。 |
The service is currently busy |
Azure SQL throttling | 使用指数退避重试。 考虑扩大规模。 |
| 正常运行后查询速度变慢 | DTU/vCore 用尽 | 查看 Azure Monitor 的指标。 扩大或优化查询。 |