Menggunakan go-mssqldb dengan Azure SQL Database

Driver go-mssqldb mendukung koneksi ke Azure SQL Database, Azure SQL Managed Instance, dan database SQL di Microsoft Fabric. Artikel ini membahas konfigurasi, autentikasi, batas koneksi, dan pemecahan masalah khusus Azure yang berbeda dari SQL Server lokal.

Menyambung ke Azure SQL Database

Azure SQL Database memerlukan koneksi terenkripsi secara default. Tentukan encrypt=true dan TrustServerCertificate=false secara eksplisit sehingga koneksi menggunakan TLS dan memvalidasi sertifikat server:

db, err := sql.Open("sqlserver",
    "sqlserver://<user>:<password>@<server>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Note

Saat Anda menghilangkan encrypt, driver tidak secara otomatis menambahkan pengaturan TLS khusus Azure. Simpan encrypt=true&TrustServerCertificate=false dalam string koneksi Azure SQL.

Autentikasi Microsoft Entra ID menghilangkan kata sandi dari string koneksi Anda. ActiveDirectoryDefault Secara otomatis memilih kredensial terbaik yang tersedia untuk lingkungan, yang membuatnya nyaman untuk pengembangan:

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 nyaman untuk pengembangan, tetapi dapat menambahkan latensi koneksi karena menyelidiki beberapa sumber kredensial. Untuk layanan produksi, lebih pilih metode eksplisit seperti ActiveDirectoryManagedIdentity atau ActiveDirectoryServicePrincipal.

Cara ActiveDirectoryDefault menyelesaikan kredensial

ActiveDirectoryDefault mencoba sumber kredensial berikut secara berurutan dan menggunakan yang pertama yang berhasil:

Order Sumber kredensial Lingkungan khas
1 Variabel lingkungan (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET) Pipa CI/CD, kontainer Docker
2 Identitas beban kerja Pod Kubernetes dengan Azure Workload Identity
3 Identitas yang dikelola Azure VM, App Service, Aplikasi Kontainer, Azure Functions
4 Azure CLI (az login) Pengembangan lokal
5 Azure Developer CLI (azd auth login) Pengembangan lokal

Rantai kredensial ini memudahkan ActiveDirectoryDefault selama pengembangan, tetapi pemeriksaan berurutan menambahkan latensi ke setiap koneksi baru. Untuk produksi, tentukan metode autentikasi yang tepat (seperti ActiveDirectoryManagedIdentity) sehingga driver melewati pemeriksaan yang tidak perlu.

Aplikasi yang dihosting di Azure (App Service, Container Apps, Azure Functions, atau Azure VM) harus menggunakan identitas terkelola dengan nilai eksplisit.fedauth Pendekatan ini menghindari overhead rantai kredensial dan menghapus dependensi apa pun pada variabel lingkungan atau status CLI.

Identitas terkelola yang ditetapkan sistem:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&encrypt=true&TrustServerCertificate=false

Identitas terkelola yang ditetapkan pengguna (tentukan ID klien):

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryManagedIdentity&user id=<client-id>&encrypt=true&TrustServerCertificate=false

Berikan akses identitas dalam database

Setelah mengonfigurasi identitas terkelola pada sumber daya Azure, buat pengguna database mandiri:

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];

Untuk identitas yang ditetapkan sistem, gunakan nama sumber daya Azure. Untuk identitas yang ditetapkan pengguna, gunakan nama identitas.

Prinsipal layanan untuk otomatisasi

Untuk alur CI/CD atau autentikasi layanan-ke-layanan:

sqlserver://<server>.database.windows.net?database=<database>&fedauth=ActiveDirectoryServicePrincipal&user id=<client-id>&password=<client-secret>&encrypt=true&TrustServerCertificate=false

Untuk semua jenis kredensial, lihat autentikasi Microsoft Entra ID.

Konfigurasikan firewall Azure

Azure SQL Database menggunakan firewall tingkat server. Anda harus mengizinkan alamat IP publik klien Anda, atau menggunakan titik akhir privat.

Kesalahan: Tidak dapat membuka server

Pesan kesalahan ini menunjukkan bahwa firewall Azure memblokir alamat IP klien Anda:

mssql: login error: Cannot open server '<server>' requested by the login.
Client with IP address '<client-ip>' is not allowed to access the server.

Solusi:

  1. Tambahkan aturan firewall di portal Azure:Jaringan SQL>Server>Tambahkan aturan firewall.
  2. Aktifkan Izinkan layanan dan sumber daya Azure untuk mengakses server ini jika aplikasi Anda berjalan di Azure.
  3. Untuk konektivitas privat, konfigurasikan titik akhir privat.

Kesalahan: Waktu koneksi habis

Jika waktu koneksi habis tanpa kesalahan yang jelas, firewall kemungkinan akan memblokir koneksi secara diam-diam. Verifikasi aturan firewall terlebih dahulu.

Batas koneksi menurut tingkat layanan

Azure SQL Database memberlakukan batas koneksi per database berdasarkan tingkat layanan. Melebihi batas menyebabkan kegagalan autentikasi untuk koneksi baru. Untuk tabel batas penuh, lihat Batas sumber daya database tunggal DTU dan batas sumber daya database tunggal vCore.

Atur MaxOpenConns agar sesuai dengan tingkat Anda

Selalu atur MaxOpenConns ke nilai di bawah batas koneksi untuk tingkat Azure SQL Anda:

// 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

Jika beberapa aplikasi berbagi database yang sama, bagi batas koneksi di semua aplikasi. Misalnya, jika tiga layanan berbagi database S2 (maksimal 60 pekerja), alokasikan 15-20 koneksi per layanan.

Menangani pembatasan laju Azure SQL

Azure SQL Database dapat membatasi koneksi dan kueri saat database mendekati batas sumber daya (CPU, IO, memori, atau jumlah sesi). Pembatasan laju ditunjukkan oleh kode kesalahan tertentu.

Kesalahan umum terkait pelambatan

Nomor kesalahan Pola pesan Penyebab
10928 Resource ID: %d. The %s limit for the database is %d and has been reached. Batas sesi atau pekerja tercapai.
10929 Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d. Pembatasan pengatur sumber daya.
40501 The service is currently busy. Pembatasan laju umum. Coba lagi.
40544 The database has reached its size quota. Batas ukuran database tercapai. Tingkatkan kapasitas atau ruang kosong sebelum mencoba lagi.
40549 Session is terminated because you have a long-running transaction. Transaksi melebihi batas waktu.
40550 Session is terminated because of too many locks. Akuisisi kunci yang berlebihan.
40551 Session is terminated because of excessive tempdb usage. Penggunaan tempdb yang berlebihan.
40552 Session is terminated because of excessive transaction log usage. Ruang log transaksi terlampaui.
40553 Session is terminated because of excessive memory usage. Konsumsi memori yang berlebihan.
40613 Database '%.*ls' on server '%.*ls' is not currently available. Database sedang dipindahkan atau dikonfigurasi ulang.
49918 Cannot process request. Not enough resources to process request. Kelelahan sumber daya.
49919 Cannot process create or update request. Terlalu banyak operasi buat/perbarui yang berlangsung bersamaan.
49920 Cannot process request. Too many operations in progress. Batas operasi simultan telah tercapai.

Coba kembali permintaan yang terkena pembatasan laju

Sebagian besar kesalahan pembatasan dan ketersediaan Azure SQL dalam tabel sebelumnya bersifat sementara dan harus dicoba kembali dengan backoff eksponensial. Kesalahan 40544 tidak bersifat sementara. Ini berarti database mencapai kuota ukurannya, sehingga operasi tidak akan berhasil sampai Anda meningkatkan skala database atau menghapus data.

Untuk implementasi coba lagi lengkap, lihat Penanganan kesalahan dan pola coba lagi.

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
}

Ketahanan koneksi

Azure SQL Database terkadang mengonfigurasi ulang server untuk pembaruan, failover, dan penyeimbangan beban. Kejadian ini memutus koneksi yang ada, yang ditampilkan sebagai kesalahan driver: bad connection. Konfigurasikan pool Anda agar pulih secara otomatis:

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

Gateway Azure SQL menutup koneksi yang menganggur selama sekitar 30 menit. Atur ConnMaxIdleTime jauh di bawah ambang batas ini untuk menghindari kesalahan driver: bad connection pada kueri pertama setelah periode tidak aktif. Untuk panggilan non-transaksional, database/sql coba ulang secara otomatis pada koneksi baru. Untuk panggilan transaksional, kode Anda harus menangkap kesalahan dan mencoba kembali seluruh transaksi.

Koneksi ulang setelah failover

Di luar transaksi, database/sql dapat secara transparan mencoba kembali pemanggilan yang dimulai pada koneksi yang bermasalah saat driver menandai koneksi tersebut sebagai tidak dapat digunakan. Perilaku ini bukan merupakan kebijakan percobaan ulang yang lengkap untuk kegagalan sementara seperti pelambatan, failover, atau kesalahan SQL lain yang dapat dicoba ulang. Bungkus pemanggilan database Anda dengan fungsi percobaan ulang untuk menangani skenario tersebut:

var count int
err := RetryFunc(ctx, DefaultRetryConfig, func(ctx context.Context) error {
    return db.QueryRowContext(ctx, "SELECT COUNT(*) FROM HumanResources.Employee").Scan(&count)
})

Lihat Penanganan kesalahan dan pola coba lagi untuk implementasi RetryFunc .

Azure SQL Managed Instance

Azure SQL Managed Instance mendukung fitur driver yang sama dengan SQL Server lokal, dengan beberapa perbedaan:

Feature Azure SQL Database Azure SQL Managed Instance
SQL Server Agent (Agen dari SQL Server) Tidak tersedia Available
Kueri lintas basis data Tidak tersedia Available
Server yang ditautkan Tidak tersedia Available
Pipa bernama Tidak tersedia Tidak tersedia (khusus TCP)
Memori bersama Tidak tersedia Tidak tersedia (khusus TCP)
Autentikasi Windows (SSPI) Tidak tersedia Tersedia dalam VNet terkelola

Menyambungkan ke Managed Instance:

sqlserver://<user>:<password>@<instance>.database.windows.net?database=<database>&encrypt=true&TrustServerCertificate=false

Database SQL di Microsoft Fabric

Important

Database SQL di Fabric memerlukan autentikasi Microsoft Entra ID. Autentikasi SQL Server tidak didukung.

Untuk beban kerja produksi, gunakan mode eksplisit fedauth alih-alih ActiveDirectoryDefault untuk menghindari overhead pemeriksaan rantai kredensial pada koneksi baru.

Database SQL di Fabric mendukung go-mssqldb driver dengan autentikasi Microsoft Entra ID:

db, err := sql.Open("azuresql",
    "sqlserver://<server>.database.fabric.microsoft.com?database=<database>&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Tips kinerja Azure SQL

Tip Rincian
Gunakan pengumpulan koneksi Azure SQL menghitung setiap koneksi yang terbuka sebagai bagian dari batas tingkat layanan. Jaga agar MaxOpenConns tetap terbatas.
Aktifkan encrypt=strict Untuk keamanan terkuat, gunakan enkripsi TDS 8.0: encrypt=strict. Azure SQL Database mendukung mode ketat.
Gunakan ApplicationIntent=ReadOnly Arahkan kueri yang didominasi operasi baca ke replika baca: ApplicationIntent=ReadOnly. Tersedia di tingkat Premium, Business Critical, dan Hyperscale.
Memantau penggunaan DTU/vCore Penggunaan CPU, IO, atau worker yang tinggi menunjukkan bahwa paket Anda mungkin terlalu kecil. Gunakan Azure Monitor untuk melacak pemanfaatan sumber daya.
Jaga agar transaksi tetap singkat Azure SQL mengakhiri sesi dengan transaksi yang melebihi ambang batas sumber daya (kesalahan 40549).
Menggunakan endpoint regional Tempatkan aplikasi Anda di wilayah Azure yang sama dengan database untuk meminimalkan latensi.

Daftar periksa pemecahan masalah Azure SQL

Gejala Kemungkinan penyebabnya Solusi
Cannot open server Aturan firewall hilang Tambahkan IP Anda atau aktifkan akses layanan Azure.
Login failed Kredensial yang salah atau pengguna database yang hilang Verifikasi login ada dan memiliki akses database.
Koneksi sesekali mengalami timeout Konfigurasi ulang server atau failover Terapkan logika percobaan ulang dan rotasi koneksi.
Resource limit reached Terlalu banyak koneksi bersamaan Turunkan MaxOpenConns dan tutup koneksi segera.
The service is currently busy Pembatasan Azure SQL Coba lagi dengan backoff eksponensial. Pertimbangkan untuk meningkatkan skala.
Kueri melambat setelah sebelumnya berfungsi dengan baik Kelelahan DTU/vCore Periksa metrik Azure Monitor. Tingkatkan skala atau optimalkan kueri.