Penulis Tamu :Michael J Swart (@MJSwart)
Kami baru-baru ini dikejutkan oleh sejumlah pengecualian yang dilemparkan oleh aplikasi kami. Aplikasi kami gagal saat mencoba Membuka SqlConnection. Pengecualiannya terlihat seperti ini:
Kesalahan System.InvalidOperationException:Waktu tunggu habis. Periode batas waktu berlalu sebelum mendapatkan koneksi dari kumpulan. Ini mungkin terjadi karena semua koneksi gabungan sedang digunakan dan ukuran kumpulan maksimum telah tercapai.
Kumpulan Koneksi
Ingatlah bahwa .Net menggunakan kumpulan koneksi untuk membantu menghindari biaya tambahan untuk membuat koneksi pada setiap kueri. Kumpulan koneksi dipertahankan untuk setiap string koneksi dan secara default jumlah koneksi di kumpulan dibatasi hingga seratus. Seratus koneksi biasanya cukup. Kami tidak pernah memiliki masalah dengan pengecualian ini sebelumnya dan server kami tidak lebih sibuk dari biasanya, jadi kami ragu untuk meningkatkan nilai MaxPoolSize. Kami mulai mencurigai adanya kebocoran koneksi database.
Kebocoran Koneksi Basis Data
Sama seperti kebocoran memori, kebocoran koneksi database dapat terjadi jika Anda tidak membuang koneksi database Anda pada waktu yang tepat. SqlConnections adalah IDisposable jadi ini adalah praktik terbaik untuk menggunakan pernyataan using:
using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); // etc... }
Segera setelah Anda selesai dengan SqlConnection, itu dibuang dan koneksi yang sebenarnya segera kembali ke kumpulan koneksi sehingga dapat digunakan oleh orang lain. Jika tidak, koneksi tetap digunakan hingga proses berakhir atau pengumpulan sampah membersihkannya.
Menemukan Kebocoran Koneksi Anda
Jadi, jika aplikasi Anda mengalami waktu tunggu koneksi karena kebocoran koneksi database, pelacakan tumpukan mungkin tidak membantu Anda. Sama seperti pengecualian kehabisan memori karena kebocoran memori, jejak tumpukan memiliki informasi tentang korban, tetapi bukan akar masalahnya. Jadi di mana Anda dapat menemukan kebocorannya?
Meskipun kebocoran koneksi database adalah masalah klien, Anda dapat menemukan bantuan dari server database. Di server database, lihat koneksi per proses per database untuk mendapatkan perkiraan kasar ukuran setiap kumpulan:
select count(*) as sessions, s.host_name, s.host_process_id, s.program_name, db_name(s.database_id) as database_name from sys.dm_exec_sessions s where is_user_process = 1 group by host_name, host_process_id, program_name, database_id order by count(*) desc;
Nama program, nama host, id proses, dan nama database biasanya cukup baik untuk mengidentifikasi koneksi yang berasal dari kumpulan koneksi yang sama.
Ini membuat saya mengajukan beberapa pertanyaan lagi tentang kumpulan dengan banyak koneksi. Diberikan kumpulan, apakah ada sesi yang telah tidur untuk sementara waktu dan, jika demikian, sudah berapa lama mereka tidur dan apa pernyataan SQL terakhir yang mereka jalankan?
declare @host_process_id int = 1508; declare @host_name sysname = N'SERV4102'; declare @database_name sysname = N'My_Database'; select datediff(minute, s.last_request_end_time, getdate()) as minutes_asleep, s.session_id, db_name(s.database_id) as database_name, s.host_name, s.host_process_id, t.text as last_sql, s.program_name from sys.dm_exec_connections c join sys.dm_exec_sessions s on c.session_id = s.session_id cross apply sys.dm_exec_sql_text(c.most_recent_sql_handle) t where s.is_user_process = 1 and s.status = 'sleeping' and db_name(s.database_id) = @database_name and s.host_process_id = @host_process_id and s.host_name = @host_name and datediff(second, s.last_request_end_time, getdate()) > 60 order by s.last_request_end_time;
Teks sekarang dapat digunakan untuk mencari basis kode aplikasi Anda untuk menemukan di mana Anda mungkin mengalami kebocoran koneksi database.
Kueri ini berguna untuk memecahkan masalah kebocoran koneksi database dan juga dapat digunakan untuk membuat monitor atau pemeriksaan kesehatan.
Buang barang sekali pakai Anda, gunakan kegunaan itu, tutup kebocorannya!