適用於:Linux 上的 SQL Server
本文介紹 Linux 上 Linux 上的 SQL Server 的記憶體配置,包括mssql-conf記憶體限制、控制群組(cgroup)設定、Docker 容器記憶體範例,以及交換空間的考量。
Note
關於儲存、核心、CPU 與網路的建議,請參見 Performance 最佳實務:Linux 上的 SQL Server 的儲存、核心、CPU 與網路。
使用 mssql-conf 設定記憶體限制
為了確保 Linux 作業系統有足夠的實體記憶體,SQL Server 程序預設只使用物理 RAM 的 80%。 對於某些擁有大量實體記憶體的系統來說,20% 可能是一個顯著的數字。 例如,在有 1 TB 記憶體的系統上,預設設定會留下約 200 GB 記憶體未被使用。 在此情況下,您可能會想要將記憶體限制設定為較高的值。
你可以用 mssql-conf 工具或 MSSQL_MEMORY_LIMIT_MB 環境變數調整這個數值。 更多資訊請參閱 memory.memorylimitmb 設定,該設定控制 SQL Server 可見的記憶體(以 MB 為單位)。 如需詳細的大小調整指引,請參閱 Linux 及容器記憶體限制設定指引。
控制群組(Cgroup)v2 支援
SQL Server 偵測並執行控制群組(cgroup)v2 約束,從 SQL Server 2025(17.x)及 SQL Server 2022(16.x)累積更新(CU)20 開始。 這些限制在 Linux 核心中提供對 CPU 與記憶體資源的細緻控制,並改善 Docker 、Kubernetes 與 OpenShift 環境中的資源隔離。
在早期版本中,Kubernetes 叢集上的容器化部署(例如 Azure Kubernetes Service v1.25+)可能會因 SQL Server 未強制執行容器規範中定義的記憶體限制而出現記憶體外(OOM)錯誤。 支援 cgroup v2 解決了這個問題。
檢查 cgroup 版本
stat -fc %T /sys/fs/cgroup
結果如下:
| Result | Description |
|---|---|
cgroup2fs |
你用的是 cgroup v2 |
cgroup |
你用的是 cgroup v1 |
切換到 cgroup v2
最簡單的方法是選擇開箱即用的支援 cgroup v2 的發行版。
如果你需要手動切換,請在你的 GRUB 配置中加入以下參數:
systemd.unified_cgroup_hierarchy=1
然後更新 GRUB。 例如,在 Ubuntu 上,執行:
sudo update-grub
在 Red Hat Enterprise Linux(RHEL)上,執行:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
使用 cgroup v2 進行 CPU 限制報告
當你用 cgroup v2 設定 CPU 限制時,SQL Server 不會在錯誤日誌中顯示已設定的 CPU 核心數量。 取而代之的是,它持續報告主機 CPU 的總數。
為了使 SQL Server 排程器與查詢計畫(例如平行性決策)與 cgroup v2 中定義的 CPU 數量對齊,請套用以下設定。
設定處理器親和力
明確設定 SQL Server 處理器親和力與 cgroup 執行配額相符。 以下範例中,cgroup 配額是在八核心主機上分配了四個 CPU:
ALTER SERVER CONFIGURATION
SET PROCESS AFFINITY CPU = 0 TO 3;
此配置確保 SQL Server 只為預定數量的 CPU 建立排程器。 欲了解更多資訊,請參閱 ALTER SERVER CONFIGURATION 以及 針對節點和/或 CPU 使用 PROCESS AFFINITY。
啟用追蹤旗標 8002(建議)
啟用追蹤標誌 8002,以便在 SQLPAL 層使用軟親和性:
sudo /opt/mssql/bin/mssql-conf traceflag 8002 on
預設情況下,排程器會綁定到親和遮罩中定義的特定 CPU。 追蹤旗標 8002 允許排程器在 CPU 之間移動,這通常能提升效能,同時仍遵循親和性與 cgroup 約束。 如需詳細資訊,請參閱 DBCC TRACEON - 追蹤旗標。
啟用追蹤旗標後重新啟動 SQL Server。
預期行為
重啟後:
SQL Server 只會建立由親和設定定義的排程器數量(例如四個排程器)。
Linux 核心持續執行 cgroup v2 CPU 執行配額。
查詢優化與平行度決策是基於預期的 CPU 數量,而非總主機 CPU。
Note
SQL Server 錯誤日誌可能會持續顯示總主機 CPU 數量。 這種日誌和顯示行為不會影響實際的 CPU 使用率、排程器的建立,或是 cgroup v2 或處理器親和力的 CPU 強制執行。
如需詳細資訊,請參閱下列資源:
Linux 及容器中設定記憶體限制的指引
Linux 上的 SQL Server 有多個記憶體控制,分別在不同層級運作。 下表與示意圖展示了每個層級如何縮小可用記憶體範圍,從主機 RAM 到緩衝池。
| 等級 | 設定者 | Description |
|---|---|---|
| 主機 | 硬體/虛擬機設定 | 伺服器或虛擬機(VM)上的實體記憶體。 |
cgroup 限額(docker run --memory、systemd或手動) |
容器執行時間、 systemd 切片或手動 cgroup 設定 |
cgroup中所有處理程序的核心強制執行上限(memory.max)。 裸機 Linux 上是可選的。 |
SQL Server 程序 (memorylimitmb / MSSQL_MEMORY_LIMIT_MB) |
mssql-conf 或環境變數 |
所有 SQL Server 元件的總記憶體。 必須低於 cgroup 限制(若有)或主機記憶體。 |
緩衝池 (max_server_memory) |
sp_configure |
8 KB 資料頁面的快取。 必須低於 memorylimitmb。 |
| 頭部空間 | 已計算(界限之間的差距) |
cgroup 限制值(或主機記憶體)與 memorylimitmb 之間的差額,保留給作業系統額外負荷和輔助程序。 |
在設定 Linux SQL Server 記憶體限制時,請參考以下指引:
在容器部署中,用
cgroup來限制容器可用的整體記憶體。 此設定確立了容器內所有程序的上界。記憶體限制(無論是由
memorylimitmbMSSQL_MEMORY_LIMIT_MBLinux 或環境變數設定)控制 SQL Server 在所有元件間可分配的總記憶體,例如緩衝池、SQLPAL、SQL Server 代理程式、LibOS、PolyBase、Full-Text 搜尋,以及 Linux SQL Server 載入的其他程序。MSSQL_MEMORY_LIMIT_MB環境變數的優先級高於在memorylimitmb中定義的mssql.conf。memorylimitmb不能超過主機系統的實際實體記憶體。設定
memorylimitmb低於主機系統記憶體及cgroup(如果有)的限制,以確保 Linux 作業系統有足夠的實體空間。 如果您未明確指定memorylimitmb,SQL Server 會使用系統總記憶體與cgroup限制(如果有設定)兩者中較小值的 80%。max_server_memory伺服器設定選項僅限制 SQL Server 緩衝池的大小,並不管理 Linux 上 SQL Server 的整體記憶體使用量。 務必將此值設為低於
memorylimitmb,以確保前一個項目符號中所述的其他元件仍有足夠的記憶體可用。
SQL Server 與容器記憶體限制之間的記憶體餘裕
當在已設定記憶體限制的容器中執行 SQL Server 時(例如,cgroup 設定 memory.max),請在 memory.memorylimitmb 與容器記憶體限制之間保留餘裕。 這些餘裕可供容器內的作業系統額外負載及輔助處理程序使用。
大多數部署中,應保留 10% 至 20% 的容器記憶體給作業系統及非 SQL Server 程序,並設定
memory.memorylimitmb在剩餘容量以下。對於大型記憶體配置,百分比式緩衝區可能會保留超過必要的記憶體。 例如,256 GB 容器的 10% 約為 25 GB,這對作業系統的開銷來說是合理的。 然而,512 GB 容器的 10% 約為 51 GB,這很可能超出作業系統的需求。 在這種情況下,建議使用固定緩衝區,並根據你的工作負載和作業系統開銷調整大小,其餘部分則分配給 SQL Server。
根據工作負載特性、容器中運行的其他服務以及主機設定來調整緩衝區。
Note
沒有任何單一的建議餘裕值適用於所有環境。 透過測試驗證記憶體設定,確保系統在尖峰負載下的穩定性。
避免設定高於可用記憶體的記憶體限制
不要設定 memory.memorylimitmb 超過主機可用的實體記憶體,也不要設定超過容器強制的記憶體上限。 如果要這麼做,SQL Server 可能會大幅消耗記憶體,導致作業系統和支援程序的容量不足。 此配置可產生:
- 記憶壓力增加。
- 系統穩定性降低及意外服務中斷。
- 作業系統因記憶體不足(OOM)情況而終止
sqlservr程序
將 SQL Server 記憶體限制設於主機或容器可用有效記憶體以下,並預留足夠的緩衝空間給作業系統與執行時服務。
Docker 記憶體配置範例
docker run --memory 選項會設定容器的 cgroup 記憶體限制。 此限制即為核心強制的所有容器程序的硬上限。
MSSQL_MEMORY_LIMIT_MB(或memory.memorylimitmb)控制 SQL Server 能使用多少記憶體。 如 前述指引所述,必須設定 MSSQL_MEMORY_LIMIT_MB 低於容器記憶體限制,以保留作業系統及輔助程序的餘裕。
以下範例使用擁有 16 GB RAM 的主機。 根據你的環境調整數值。
不建議:沒有容器記憶體限制
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" \
-e "MSSQL_MEMORY_LIMIT_MB=14336" \
-p 1433:1433 \
-d mcr.microsoft.com/mssql/server:2022-latest
沒有 --memory,容器就沒有 cgroup 天花板。
MSSQL_MEMORY_LIMIT_MB限制 SQL Server,但容器內的其他程序仍可能佔用無界主機記憶體。
不建議:記憶體限制等於 SQL Server 記憶體限制
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" \
-e "MSSQL_MEMORY_LIMIT_MB=12288" \
--memory 12g \
-p 1433:1433 \
-d mcr.microsoft.com/mssql/server:2022-latest
兩個限制都設定為 12 GB(--memory 12g = 12,288 MB)。 已沒有可供作業系統開銷或輔助程序使用的餘裕,這可能導致因 OOM 而遭終止。
不建議:SQL Server 記憶體限制超過容器限制
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" \
-e "MSSQL_MEMORY_LIMIT_MB=14336" \
--memory 12g \
-p 1433:1433 \
-d mcr.microsoft.com/mssql/server:2022-latest
MSSQL_MEMORY_LIMIT_MB (14 GB)超過容器容量限制(12 GB)。 此情境會導致如 避免將記憶體限制設定為高於可用記憶體 中所述的 OOM 狀況。
建議:容器限制值,並為作業系統預留餘裕
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=<password>" \
-e "MSSQL_MEMORY_LIMIT_MB=10240" \
--memory 12g \
-p 1433:1433 \
-d mcr.microsoft.com/mssql/server:2022-latest
容器容量限制為 12 GB(--memory 12g),而 SQL Server 則設定最多可使用 10 GB(MSSQL_MEMORY_LIMIT_MB=10240)。 剩餘的 2 GB(約 17%)則提供作業系統及其他程序的餘裕。
交換空間注意事項
當你在容器中執行 SQL Server 時,請在主機層啟用交換空間,以幫助保護作業系統及非 SQL Server 程序。 不過,請設定 SQL Server 在其設定的記憶體限制內運作,且在正常運作時不要依賴交換。
請遵循記憶體限制指引,確保 SQL Server 運作於實體記憶體或適用
cgroup的記憶體限制內。若啟用交換功能,應將其視為主機暫時記憶體壓力的安全網,而非穩定狀態 SQL Server 工作負載的容量。
Important
如果記憶體壓力導致交換,SQL Server 效能可能會大幅下降。 適當的記憶體大小調整是防止記憶體相關故障的主要機制。