Connection Pooling คือกลไกที่ ADO.NET ใช้จัดการ Database Connections โดยเก็บ Connection ที่ปิดแล้วไว้ใน "Pool" เพื่อนำกลับมาใช้ใหม่ (Reuse) แทนการสร้าง Connection ใหม่ทุกครั้ง ซึ่งมีค่าใช้จ่ายสูง (Expensive)
ทำไมต้องมี Connection Pooling?
- เปิด/ปิด Connection จริง (Physical) ใช้เวลาและ Resource มาก (TCP Handshake, Auth, SSL)
- Pooling เก็บ Connection ไว้ใน Process Memory พร้อมใช้งาน
- ลด Latency และ CPU/Memory Overhead อย่างมาก
การทำงานของ Pooling
new SqlConnection(connString): สร้าง Connection Object (ยังไม่เปิด)conn.Open(): ดู Pool มี Connection ว่างหรือไม่ → มี = ใช้เลย, ไม่มี = สร้างใหม่conn.Close()หรือDispose(): คืน Connection กลับ Pool (ไม่ปิดจริง)- Pool Manager จัดการ Lifetime, Min/Max Pool Size, Timeout
Connection String Options
Server=myServer;Database=myDB;User=myUser;Password=myPass;
Pooling=true; // Default: true
Min Pool Size=5; // Default: 0
Max Pool Size=100; // Default: 100
Connection Lifetime=300; // วินาที Destroy idle connections
Load Balance Timeout=30; // วินาที
Enlist=true; // Transaction Enlistment
บทบาทของ using Statement
string connString = "Server=...;Pooling=true;";
using (var conn = new SqlConnection(connString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM Users";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read()) { /* ... */ }
}
}
} // conn.Dispose() -> คืน Connection กลับ Pool อัตโนมัติ
// แม้จะมี Exception ก็ยังคืน Pool ได้ (try/finally ภายใน using)
ข้อสำคัญ
usingเรียกDispose()ซึ่งสำหรับSqlConnectionจะคืน Connection กลับ Pool (ไม่ใช่ปิดจริง)- ไม่ต้อง (และไม่ควร) เรียก
conn.Close()แยกต่างหาก หากใช้using - หากไม่ใช้
usingต้องเรียกClose()หรือDispose()เอง เพื่อคืน Pool - Pooling ทำงานต่อ Process (App Domain) ไม่ Share ระหว่าง Process
ปัญหาที่พบบ่อย
- Pool Exhaustion: ไม่ Dispose/Close → Pool เต็ม (Max Pool Size) → Timeout
- Connection Leak: Exception ระหว่าง Open/Execute ไม่มี using → Connection ค้าง
- Stale Connections: Firewall/DB Kill Idle Connections → ใช้
Connection LifetimeหรือValidate Connection
Best Practice
- ใช้
usingเสมอสำหรับSqlConnection,SqlCommand,SqlDataReader - เปิด Connection ช้าสุดที่ทำได้ ปิดเร็วสุดที่ทำได้ (Late Open, Early Close)
- หลีกเลี่ยงเก็บ Connection ไว้ใน Field/Property (Stateful)
- Monitor: Performance Counters (.NET CLR Data / SqlClient)