今天踩了一個坑,用了一個static對象,存儲了Connection,導致了並發量大時(35/s)出現單個連接的數據庫請求堆積,以及並發Open導致的異常,最終使服務下線。
排查中發現有些概念不清的地方,做了一下梳理。
1、在項目啟動后,首次獲取數據庫連接的時候(SqlConnection conn = new SqlConnection(strConnection)),ADO.net會創建一個連接池(連接數量可用Min Pool Size設定),並返回一個連接。
2、在拿到連接后,需打開連接(Connection.Open()),才可以進行數據庫操作。但注意未Close時,調用2次Open會報異常。
3、在操作完成后,必須要關閉連接(Connection.Close()),將連接還回連接池中。調用多次Close()是不會報異常的。
4、若還有查詢操作,可以重新Open,並進行操作。
5、操作完記得Close。
6、最后在完全使用完畢后,調用Connection.dispose(),將conn對象置null(但此時物理連接並沒有釋放,而是存在於連接池中)。
7、當並發數較多,連接池中的連接數不夠用時,會創建新的鏈接,但當達到連接池的Max Pool Size時,會進行等待,等待可通過SqlConnection.ConnectionTimeout設置超時時間。
8、當服務停止時,會將連接池中的物理連接釋放;或可通過將Pooling設置為True,調用close的時候就會釋放物理連接。
close和dispose的異同:
1、close是關閉連接,會將連接還回連接池,dispose也一樣
2、dispose是對close的調用,額外的操作是將Connection置null。
原本的構想是很美好的,想要控制對同一個庫的鏈接數,盡量使用一個連接進行操作,不用重新new Connection對象,較少部分消耗(但實際的大部分消耗是在Open、close上)。
但是沒考慮到並發數多的情況。還是測試不到位,考慮不周全。