關于連接數消耗內存情況
FROM DEEPSEEK
在 MySQL 中,每個單獨的空閑連接所消耗的內存量取決于多個因素,包括連接的線程棧大小(由 `thread_stack` 參數設置)和其他每個連接的緩沖區。根據測試結果來看,對于空閑連接的內存消耗并沒有一個固定的數值,因為它會根據連接的活躍狀態和執行的查詢類型而變化。然而,對于內存規劃目的,推薦平均每個連接計劃約10MB內存。
線程棧(Thread Stack)是操作系統為每個線程分配的一段內存區域,用于存儲線程的局部變量、函數調用信息、返回地址等。在多線程環境中,每個線程都有自己的線程棧,以確保線程之間數據隔離,防止數據競爭和相互干擾。
線程棧的大小:
線程棧的大小對應用程序的性能和資源使用有重要影響。棧太小可能導致棧溢出(Stack Overflow),而棧太大則可能導致內存浪費。
- 棧溢出:如果線程調用的函數太深或局部變量太大,可能會超出棧的限制,導致棧溢出錯誤。
- 程序崩潰:當線程棧溢出時,程序可能會崩潰,導致正在執行的數據庫操作失敗。
- 數據不一致:如果棧溢出發生在事務處理過程中,可能會導致數據不一致,因為事務可能無法正確提交或回滾。
- 資源泄露:棧溢出可能導致資源未能正確釋放,從而引發內存泄露或其他資源管理問題。
- 內存浪費:如果棧大小設置得過大,會浪費內存資源,尤其是在創建大量線程的情況下。
MySQL中的線程棧:
在 MySQL 中,可以通過配置參數
thread_stack
來設置線程棧的大小。這個參數影響 MySQL 服務器為每個新線程分配的內存量。MySQL 5.6 之前的版本中,thread_stack
的默認值通常是 128KB,而在 MySQL 5.7 及更高版本中,這個值增加到了 1MB。
此外,每個 MySQL 連接需要一定量的內存來維護連接狀態、緩存查詢結果和執行計劃等,這個內存量相對較小,可能在幾十KB到幾百KB之間。對于連接池中的空閑連接,它們會占用一定的內存,但這個內存通常遠小于活躍連接時的內存消耗。連接池可以顯著減少創建和銷毀連接的開銷,從而提高數據庫交互的效率。
總的來說,空閑連接的內存消耗相對較小,但隨著連接數量的增加,累積的內存消耗可能會變得顯著。因此,合理地管理數據庫連接,例如通過使用連接池技術,對于優化數據庫性能和資源使用非常重要。
MySQL8.0.28新特性
MySQL 8.0.28開始,新增一個特性,支持監控統計并限制各個連接(會話)的內存消耗,避免大量用戶連接因為執行垃圾SQL消耗過多內存,造成可能被OOM kill的風險。
首先,需要先設置系統選項 global_connection_memory_tracking = 1,之后可以通過系統狀態變量 Global_connection_memory 查看當前所有連接消耗的內存總量
相關參數介紹
global_connection_memory_trackingGlobal_connection_memoryconnection_memory_chunk_sizeconnection_memory_limit
官方文檔:
https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
問題分析
開源 MySQL8.0.37 開啟global_connection_memory_tracking參數
當前有3個連接存在,共消耗內存約1096KB
可以看到當新增一個空閑的連接,內存大概增加了8.05KB左右
并發測試:
待補充.....
可以調整每個會話連接可使用內存上限,由選項 connection_memory_limit
定義其限制,默認值及最大值都是 18446744073709551615,這個默認值太大了,等同于沒有限制。
設置connection_memory_limit =209715即2MB
然后調用存儲過程插入數據時會發現當前會話超出連接內存限制2097152字節,關閉連接
(4082, 'Connection closed. Connection memory limit 2097152 bytes exceeded. Consumed 2563352 bytes.')
。。。。。。?