Sql-Server-2008

SQL Server 動態記憶體管理

  • July 12, 2021

我正在閱讀 Christian Bolton、Brent Ozar 和已故 Ken Henderson 撰寫的一本關於 SQL 2008 內部原理和故障排除的書,我對 SQL Server 的動態記憶體管理器感到困惑和好奇。

有人可以確認我對 SQL Server 的動態記憶體管理的理解是正確的嗎?

在 SQL Server 2005/2008/2008R2 x64 中

a) 鎖佔用的最大記憶體量限制為緩衝池記憶體(最大伺服器記憶體)的 60%。通過禁用鎖升級並執行大量插入,我可以看到 SQL Server 在拋出錯誤號 1204 之前可以佔用緩衝池記憶體的 60%(記憶體不足用於鎖)

b) 計劃記憶體大小限制為

a) Number of plans in cache -- 160K 

b) Plan Cache upper limit: 75% of server memory from 0-4GB + 10% of server memory from 4Gb-64GB + 5% of server memory > 64GB.  

一旦達到此門檻值,SQL Server 將開始從記憶體中逐出執行計劃,直到 SQL Server 停止看到內部計劃記憶體壓力

c) 工作空間記憶體限制為最大伺服器記憶體的 75%,並且單個查詢不能超過(可用最大工作空間記憶體的 75%)的 25%,除非被資源管理器覆蓋。

我的問題是

在惰性寫入器開始將頁面逐出記憶體之前,數據庫頁面記憶體佔用的最大記憶體是否有限制?它是如何控制的?通過查看緩衝區中的空閒頁數……**

在將日誌刷新到磁碟之前,sql server 如何控制“事務日誌記憶體”佔用的記憶體?

提前致謝。

這不是一個完整的答案,因為我承認我不知道完整的答案,但無法發表評論。

繞道而行——關於 SQLOS 記憶體,有大量資訊來自一個從事 SQL Server 儲存團隊內部工作的人 - Slava Oks。他在 MSDN 部落格上有很多關於 SQLOS 記憶體管理器的文章,它們都值得一讀。現在我知道我們正在使用 SQL Server 2012,但這些資訊仍然很有價值。

現在,關於您的第一個問題,如果 db 頁面記憶體在被清除之前佔用的最大記憶體有限制,以及它是如何控制的,我會引用他的話。

從文章SQLOS 的記憶體管理器和 SQL Server 的緩衝池

緩衝池按需送出頁面。根據內部記憶體需求和外部記憶體狀態,它計算它的目標,它認為它應該在進入記憶體壓力之前送出的記憶體量。為了使系統遠離分頁目標,不斷地重新計算。目標記憶體不能超過表示最大伺服器記憶體設置的最大記憶體。即使您將 min server memory 設置為 max server memory 緩衝池也只會按需送出其記憶體。您可以通過監視相應的分析器事件來觀察此行為。

本文評論中,我了解到 SQL Server 使用 LRU 算法(LRU = 最近最少使用)。如果你真的需要深入,SQL Server 的 LRU 算法在下面的研究論文中有特別描述:The LRU-K Page Replacement Algorithm For Database Disk Buffering

現在,對於您的第二個問題,日誌記憶體並未真正公開,因此無法更改/調整它們,因為它們是 SQLOS 內部記憶體結構的一部分。引用MSDN 論壇的回答

本質上,每個數據庫都有一個用於其事務日誌的日誌緩衝區/記憶體,這是一個小的連續記憶體分配,大小為 60K,供活動事務使用,並在事務送出或緩衝區空間填滿時刷新。多個活動事務可以在日誌緩衝區中交錯,如果任何一個事務送出,則緩衝區記憶體由日誌寫入器寫入事務日誌文件。如果空間已滿,則內容將刷新到磁碟,從而允許重用緩衝區/高速記憶體。這就是為什麼日誌 IO 的範圍可以從 512 字節到 64K(實際上是 60K),但它始終是連續的,因此不同的寫入大小並不重要。日誌記錄的格式不同於 BOL ( http://msdn.microsoft.com/en-us/library/ms190925.aspx ) 中記錄的數據頁),因此日誌記錄的大小是可變的,但日誌緩衝區/記憶體的大小是一致的。

剛剛完成答案,我在 SQL Server: Logging, Recovery, and the Transaction Log course 中看到 Paul Randal 記錄到 Pluralsight,每個數據庫有 128 個日誌緩衝區,每個緩衝區大小為 60KB。因此,當一個日誌塊結束(記錄送出、中止或填滿 60K)時,它被複製到 128 個日誌緩衝區之一,而不是非同步寫入磁碟,受未完成的 I/O 限制。

大小仍然固定,但每個數據庫的大小為 128 x 60K = 7680K。

我希望它有幫助;)

引用自:https://dba.stackexchange.com/questions/29365