Pengumpulan koneksi SQL Server (ADO.NET)

Berlaku untuk: .NET Framework .NET .NET Standard

Mengunduh ADO.NET

Menyambungkan ke server database biasanya terdiri dari beberapa langkah yang memakan waktu. Saluran fisik seperti soket atau pipa bernama harus dibuat, jabat tangan awal dengan server harus terjadi, informasi string sambungan harus diurai, sambungan harus diautentikasi oleh server, pemeriksaan harus dijalankan untuk mendaftar dalam transaksi saat ini, dan sebagainya.

Dalam praktiknya, sebagian besar aplikasi hanya menggunakan satu atau beberapa konfigurasi berbeda untuk sambungan. Ini berarti bahwa selama eksekusi aplikasi, banyak sambungan identik akan dibuka dan ditutup berulang kali. Untuk meminimalkan biaya pembukaan koneksi, Penyedia Data Microsoft SqlClient untuk SQL Server menggunakan teknik pengoptimalan yang disebut pengumpulan koneksi.

Pooling koneksi mengurangi frekuensi pembukaan koneksi baru. Pengumpul mempertahankan kepemilikan sambungan fisik. Ini mengelola koneksi dengan mempertahankan sekumpulan koneksi aktif untuk setiap konfigurasi koneksi yang ditentukan. Setiap kali pengguna memanggil Open pada sebuah koneksi, pooler akan mencari koneksi yang tersedia dalam pool. Jika sambungan gabungan tersedia, sambungan itu kembali ke pemanggil alih-alih membuka koneksi baru. Ketika aplikasi memanggil Close sambungan, pengumpul mengembalikannya ke kumpulan sambungan aktif, bukan menutupnya. Setelah koneksi dikembalikan ke pool, koneksi siap digunakan kembali pada pemanggilan Open berikutnya.

Hanya sambungan dengan konfigurasi yang sama yang dapat dikumpulkan. Penyedia Data Microsoft SqlClient untuk SQL Server menyimpan beberapa kumpulan secara bersamaan, satu untuk setiap konfigurasi. Sambungan dipisahkan menjadi kumpulan berdasarkan string sambungan, dan oleh identitas Windows saat keamanan terintegrasi digunakan. Koneksi juga dikelompokkan dalam pool berdasarkan apakah koneksi tersebut tergabung dalam suatu transaksi. Saat menggunakan ChangePassword, instance SqlCredential memengaruhi pool koneksi. Instans yang berbeda SqlCredential akan menggunakan kumpulan sambungan yang berbeda, bahkan jika ID pengguna dan kata sandinya sama.

Mengumpulkan sambungan dapat secara signifikan meningkatkan performa dan skalabilitas aplikasi Anda. Secara default, pengumpulan koneksi diaktifkan di Penyedia Data Microsoft SqlClient untuk SQL Server. Kecuali Anda menonaktifkannya secara eksplisit, pooler mengoptimalkan koneksi saat koneksi dibuka dan ditutup dalam aplikasi Anda. Anda juga dapat menyediakan beberapa pengubah string koneksi untuk mengontrol perilaku pengumpulan sambungan. Untuk informasi selengkapnya, lihat "Mengontrol Pengumpulan Koneksi dengan Kata Kunci String Koneksi" selanjutnya dalam topik ini.

Penting

Ketika pooling koneksi diaktifkan, dan jika terjadi kesalahan waktu habis atau kesalahan login lainnya, pengecualian akan dimunculkan dan upaya koneksi berikutnya akan gagal selama 5 detik, "blocking period". Jika aplikasi mencoba tersambung dalam periode pemblokiran, pengecualian pertama akan dilemparkan lagi. Kegagalan berikutnya setelah periode pemblokiran berakhir akan mengakibatkan periode pemblokiran baru yang dua kali lebih lama dari periode pemblokiran sebelumnya, hingga maksimum 1 menit.

Catatan

Mekanisme "blocking period" tidak berlaku untuk Azure SQL Server secara default. Perilaku ini dapat diubah dengan memodifikasi PoolBlockingPeriod properti di ConnectionString kecuali untuk .NET Standard.

Pembuatan dan penugasan kumpulan

Saat sambungan pertama kali dibuka, kumpulan sambungan dibuat berdasarkan algoritma pencocokan yang tepat yang mengaitkan kumpulan dengan string koneksi dalam sambungan. Setiap kumpulan sambungan dikaitkan dengan string koneksi yang berbeda. Saat sambungan baru dibuka, jika string koneksi tidak sama persis dengan kumpulan yang ada, kumpulan baru dibuat.

Catatan

Koneksi dikumpulkan per proses, per domain aplikasi, per string koneksi dan saat keamanan terintegrasi digunakan, per identitas Windows. String koneksi juga harus sama persis; kata kunci yang disediakan dalam urutan yang berbeda untuk sambungan yang sama akan dikumpulkan secara terpisah.

Catatan

Jika MinPoolSize tidak ditentukan dalam string koneksi atau ditentukan sebagai nol, sambungan di kumpulan akan ditutup setelah periode tidak aktif. Namun, jika MinPoolSize yang ditentukan lebih besar dari 0, pool koneksi tidak akan dihancurkan sampai AppDomain dilepas dan proses berakhir. Pemeliharaan pool yang tidak aktif atau kosong hanya melibatkan overhead sistem yang minimal.

Catatan

Pool dibersihkan secara otomatis saat terjadi kesalahan fatal, seperti failover.

Dalam contoh C# berikut, tiga SqlConnection objek baru dibuat, tetapi hanya dua kumpulan koneksi yang diperlukan untuk mengelolanya. Perhatikan bahwa string koneksi pertama dan kedua berbeda dengan nilai yang ditetapkan untuk Initial Catalog.

using (SqlConnection connection = new SqlConnection(
    "Integrated Security=SSPI;Initial Catalog=Northwind"))
        {
            connection.Open();
            // Pool A is created.
        }

    using (SqlConnection connection = new SqlConnection(
    "Integrated Security=SSPI;Initial Catalog=pubs"))
        {
            connection.Open();
            // Pool B is created because the connection strings differ.  
        }

    using (SqlConnection connection = new SqlConnection(
    "Integrated Security=SSPI;Initial Catalog=Northwind"))
        {  
            connection.Open();
            // The connection string matches pool A.  
        }

Menambahkan koneksi

Pool koneksi dibuat untuk setiap string koneksi yang unik. Saat kumpulan dibuat, beberapa objek koneksi dibuat dan ditambahkan ke kumpulan sehingga persyaratan ukuran kumpulan minimum terpenuhi. Koneksi ditambahkan ke kumpulan sesuai kebutuhan, hingga ukuran kumpulan maksimum yang ditentukan (100 adalah default). Koneksi dilepaskan kembali ke kumpulan ketika ditutup atau dibuang.

Ketika objek SqlConnection diminta, objek tersebut diambil dari pool jika tersedia koneksi yang dapat digunakan. Agar dapat digunakan, koneksi harus tidak digunakan, memiliki konteks transaksi yang cocok atau tidak terkait dengan konteks transaksi apa pun, dan memiliki link yang valid ke server.

Pengelola pool koneksi memenuhi permintaan koneksi dengan mengalokasikan ulang koneksi saat koneksi tersebut dilepaskan kembali ke dalam pool. Jika ukuran kumpulan maksimum telah tercapai dan tidak ada sambungan yang dapat digunakan yang tersedia, permintaan akan diantrekan. Pooler kemudian mencoba mengambil kembali koneksi yang ada hingga batas waktu habis (defaultnya adalah 15 detik). Jika pengumpul tidak dapat memenuhi permintaan sebelum waktu sambungan habis, pengecualian akan dilemparkan.

Perhatian

Kami sangat menyarankan agar Anda selalu menutup koneksi setelah selesai menggunakannya agar koneksi tersebut dikembalikan ke pool. Anda dapat melakukan ini menggunakan Close atau Dispose metode dari Connection objek, atau dengan membuka semua sambungan di dalam using pernyataan di C#, atau Using pernyataan dalam Visual Basic. Koneksi yang tidak ditutup secara eksplisit mungkin tidak ditambahkan atau dikembalikan ke kumpulan. Untuk informasi selengkapnya, lihat menggunakan Pernyataan atau Cara: Membuang Sumber Daya Sistem untuk Visual Basic.

Catatan

Jangan memanggil Close atau Dispose pada Connection, DataReader, atau objek terkelola lainnya dalam metode Finalize kelas Anda. Dalam finalizer, hanya lepaskan sumber daya tak terkelola yang dimiliki langsung oleh kelas Anda. Jika kelas Anda tidak memiliki sumber daya yang tidak dikelola, jangan sertakan metode Finalize dalam definisi kelas Anda. Untuk informasi selengkapnya, lihat Pengumpulan Sampah.

Untuk informasi selengkapnya tentang peristiwa yang terkait dengan sambungan pembukaan dan penutupan, lihat Kelas Peristiwa Masuk Audit dan Kelas Peristiwa Keluar Audit dalam dokumentasi SQL Server.

Hapus koneksi

Jika LoadBalanceTimeout (atau Connection Lifetime) diatur, ketika koneksi dikembalikan ke kumpulan, waktu pembuatannya dibandingkan dengan waktu saat ini dan koneksi dihancurkan jika rentang waktu tersebut (dalam detik) melebihi nilai yang ditentukan oleh LoadBalanceTimeout. Ini berguna dalam konfigurasi berkluster untuk memaksa penyeimbangan beban antara server yang sedang berjalan dan server yang baru saja online.

Jika LoadBalanceTimeout (atau Connection Lifetime) tidak diatur (nilai default = 0), pool koneksi menghapus koneksi dari pool setelah tidak aktif selama sekitar 4-8 menit (secara acak dalam dua tahap), atau jika pool koneksi mendeteksi bahwa koneksi ke server telah terputus.

Catatan

Koneksi terputus hanya dapat dideteksi setelah mencoba berkomunikasi dengan server. Jika ditemukan sambungan yang tidak lagi tersambung ke server, sambungan ditandai sebagai tidak valid. Sambungan yang tidak valid dihapus dari kumpulan sambungan hanya ketika ditutup atau diklaim kembali.

Jika ada sambungan ke server yang telah menghilang, sambungan ini dapat diambil dari kumpulan meskipun pengumpul sambungan belum mendeteksi sambungan terputus dan menandainya sebagai tidak valid. Hal ini terjadi karena overhead untuk memeriksa apakah koneksi masih valid akan menghilangkan manfaat penggunaan pooler dengan menyebabkan satu round trip tambahan ke server. Ketika ini terjadi, upaya pertama untuk menggunakan koneksi akan mendeteksi bahwa koneksi telah terputus, dan pengecualian dilemparkan.

Bersihkan kumpulan

Penyedia Data Microsoft SqlClient untuk SQL Server memperkenalkan dua metode baru untuk menghapus kumpulan: ClearAllPools dan ClearPool. ClearAllPools menghapus kumpulan sambungan untuk penyedia tertentu, dan ClearPool menghapus kumpulan sambungan yang terkait dengan sambungan tertentu.

Catatan

Jika ada koneksi yang sedang digunakan saat panggilan berlangsung, koneksi tersebut akan ditandai sebagaimana mestinya. Saat ditutup, objek tersebut dibuang alih-alih dikembalikan ke pool.

Dukungan transaksi

Koneksi diambil dari kumpulan dan ditetapkan berdasarkan konteks transaksi. Kecuali Enlist=false ditentukan dalam string koneksi, kumpulan sambungan memastikan bahwa sambungan terdaftar dalam konteks Current. Ketika sambungan ditutup dan dikembalikan ke kumpulan dengan transaksi System.Transactions yang terdaftar, sambungan tersebut dikesampingkan sedemikian rupa sehingga permintaan berikutnya ke kumpulan sambungan tersebut dengan transaksi System.Transactions yang sama akan mengembalikan sambungan yang sama jika tersedia. Jika permintaan seperti itu diajukan, dan tidak ada koneksi dalam pool yang tersedia, sebuah koneksi diambil dari bagian pool non-transaksi dan didaftarkan. Jika tidak ada sambungan yang tersedia di kedua area pool, sambungan baru dibuat dan didaftarkan.

Ketika koneksi ditutup, koneksi tersebut dilepaskan kembali ke dalam kumpulan koneksi dan ke subbagian yang sesuai berdasarkan konteks transaksinya. Oleh karena itu, Anda dapat menutup koneksi tanpa menghasilkan kesalahan, meskipun transaksi terdistribusi masih tertunda. Ini memungkinkan Anda meng-commit atau membatalkan transaksi terdistribusi di kemudian hari.

Mengontrol pengumpulan koneksi dengan kata kunci string koneksi

Properti ConnectionString dari objek SqlConnection mendukung pasangan kunci/nilai string koneksi yang dapat digunakan untuk menyesuaikan perilaku logika penyatuan sambungan. Untuk informasi selengkapnya, lihat ConnectionString .

Fragmentasi kumpulan

Fragmentasi pool adalah masalah umum pada banyak aplikasi web, yang memungkinkan aplikasi membuat sejumlah besar pool yang tidak dilepaskan hingga proses berakhir. Ini membuat sejumlah besar sambungan terbuka dan mengonsumsi memori, yang menghasilkan performa yang buruk.

Fragmentasi kumpulan karena keamanan terintegrasi

Sambungan dikumpulkan sesuai dengan string koneksi ditambah identitas pengguna. Oleh karena itu, jika Anda menggunakan Autentikasi Dasar atau Autentikasi Windows pada situs web dan login keamanan terintegrasi, Anda akan mendapatkan satu pool untuk setiap pengguna. Meskipun ini meningkatkan performa permintaan database berikutnya untuk satu pengguna, pengguna tersebut tidak dapat memanfaatkan sambungan yang dibuat oleh pengguna lain. Ini juga menghasilkan setidaknya satu koneksi per pengguna ke server database. Ini adalah efek samping dari arsitektur aplikasi Web tertentu yang harus ditimbang pengembang terhadap persyaratan keamanan dan audit.

Fragmentasi kumpulan karena banyak database

Banyak penyedia layanan Internet meng-hosting beberapa situs Web pada satu server. Mereka dapat menggunakan database tunggal untuk mengonfirmasi masuk autentikasi Formulir lalu membuka sambungan ke database tertentu untuk pengguna atau grup pengguna tersebut. Sambungan ke database autentikasi dikumpulkan dan digunakan oleh semua orang. Namun, ada kumpulan sambungan terpisah ke setiap database, yang meningkatkan jumlah sambungan ke server.

Ini juga merupakan efek samping dari desain aplikasi. Ada cara yang relatif sederhana untuk menghindari efek samping ini tanpa mengorbankan keamanan saat Anda terhubung ke SQL Server. Alih-alih menyambungkan ke database terpisah untuk setiap pengguna atau grup, sambungkan ke database yang sama di server lalu jalankan pernyataan Transact-SQL USE untuk mengubah ke database yang diinginkan.

Fragmen kode berikut menunjukkan pembuatan sambungan awal ke database master lalu beralih ke database yang diinginkan yang ditentukan dalam variabel string databaseName.

// Assume that connectionString connects to master.  
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand())
{
    connection.Open();
    command.Connection = connection;
    command.CommandText = "USE DatabaseName";
    command.ExecuteNonQuery();
}

Peran aplikasi dan pengumpulan koneksi

Setelah peran aplikasi SQL Server diaktifkan dengan memanggil sp_setapprole prosedur tersimpan sistem, konteks keamanan sambungan tersebut tidak dapat direset. Namun, jika pengumpulan diaktifkan, sambungan dikembalikan ke kumpulan, dan kesalahan terjadi saat sambungan terkumpul digunakan kembali.

Alternatif peran aplikasi

Kami menyarankan agar Anda memanfaatkan mekanisme keamanan yang dapat Anda gunakan alih-alih peran aplikasi.