驅動go-mssqldb程式支援連接 Azure SQL Database、Azure SQL 受控執行個體 以及 Microsoft Fabric 中的 SQL 資料庫。 本文將介紹 Azure 專屬的設定、認證、連線限制,以及與本地 SQL Server 不同的故障排除。
連接到 Azure SQL 資料庫
Azure SQL Database 預設需要加密連線。 明確指定 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 依序嘗試以下憑證來源,並使用第一個成功的憑證來源:
| 訂單 | 憑證來源 | 典型環境 |
|---|---|---|
| 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 Database 使用伺服器層級防火牆。 你必須允許客戶的公開 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 server>Networking>新增防火牆規則。
- 如果你的應用程式在 Azure 中運行,請啟用允許 Azure 服務與資源存取此伺服器。
- 若要私有連線,請設定 私有端點。
錯誤:連線逾時
如果連線逾時,卻未出現明確的錯誤訊息,很可能是防火牆在未回報任何錯誤的情況下封鎖了該連線。 先確認防火牆規則。
依服務層級劃分的連線限制
Azure SQL Database 會根據服務層級強制執行每個資料庫的連線限制。 超過限制會導致新連線的認證失敗。 完整限制表請參見 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 Database 可以限制連線和查詢。 限速表現為特定的錯誤編號。
常見降頻錯誤
| 錯誤編號 | 訊息模式 | 原因 |
|---|---|---|
| 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 Database 偶爾會重新配置伺服器以進行更新、故障轉移和負載平衡。 這些事件會使現有連線中斷,並表現為 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)
})
請參閱 錯誤處理與重試模式 以了解實 RetryFunc 作。
Azure SQL 受控執行個體
Azure SQL 受控執行個體 支援與本地 SQL Server 相同的驅動功能,但有幾項差異:
| Feature | Azure SQL Database | Azure SQL 受控執行個體 |
|---|---|---|
| SQL Server Agent(SQL伺服器代理) | 無法提供 | Available |
| 跨資料庫查詢 | 無法提供 | Available |
| 連結的伺服器 | 無法提供 | Available |
| 具名管道 | 無法提供 | 不可用(僅限 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 會將每個開啟的連線計入層級限制。 讓 MaxOpenConns 保持在界限內。 |
啟用 encrypt=strict |
為了達到最強的安全性,請使用 TDS 8.0 加密: encrypt=strict。 Azure SQL Database 支援嚴格模式。 |
使用 ApplicationIntent=ReadOnly |
將大量讀取的查詢導向讀取複本:ApplicationIntent=ReadOnly 提供於高級、商業關鍵及超大規模等級。 |
| 監控 DTU/vCore 使用情況 | CPU 高、IO 或工作者使用率高,代表你的 Tier 可能規模不足。 使用 Azure 監視器 來追蹤資源使用率。 |
| 保持交易簡短 | Azure SQL 會終止交易超過資源門檻的會話(錯誤 40549)。 |
| 使用區域端點 | 將應用程式放在與資料庫相同的 Azure 區域,以減少延遲。 |
Azure SQL 疑難排解檢查清單
| 癥狀 | 可能的原因 | 解決方法 |
|---|---|---|
Cannot open server |
缺少防火牆規則 | 新增你的 IP 或啟用 Azure 服務存取權限。 |
Login failed |
錯誤的憑證或缺少資料庫使用者 | 確認登入是否存在且有資料庫存取權限。 |
| 連線會間歇性超時 | 伺服器重新設定或故障轉移 | 實作重試邏輯和連線輪換。 |
Resource limit reached |
太多同時連線 | 立即調低 MaxOpenConns 並關閉連線。 |
The service is currently busy |
Azure SQL 節流 | 使用指數退避進行重試。 考慮擴大規模。 |
| 正常運作後查詢速度變慢 | DTU/vCore耗盡 | 檢查 Azure 監視器 的指標。 擴大或優化查詢。 |