MSSQLSERVER_701

適用於:SQL Server

詳細資料

屬性
產品名稱 SQL Server
事件識別碼 701
事件來源 MSSQLSERVER
元件 SQLEngine
符號名稱 NOSYSMEM
訊息文字 系統記憶體不足,無法執行此查詢。

注意

本文著重於 SQL Server。 如需針對 Azure SQL Database 記憶體不足問題進行疑難排解的資訊,請參閱 使用 Azure SQL Database 針對記憶體不足錯誤進行疑難排解。

說明

當 SQL Server 無法配置足夠的記憶體來執行查詢時,就會發生錯誤 701。 記憶體不足的原因有一些因素,包括作業系統設定、實體記憶體可用性、其他元件使用 SQL Server 內的記憶體,或目前工作負載的記憶體限制。 在大部分情況下,失敗的交易不是此錯誤的原因。 整體來說,原因可以分成三個:

外部或 OS 記憶體壓力

外部壓力是指來自進程外部元件的高記憶體使用率,導致 SQL Server 記憶體不足。 您必須找出系統上的其他應用程式是否耗用記憶體,並導致記憶體不足。 SQL Server 是少數設計用來藉由減少其記憶體使用量來回應 OS 記憶體壓力的應用程式之一。 這表示,如果某些應用程式或驅動程式要求記憶體,OS 會傳送訊號給所有應用程式釋放記憶體,而 SQL Server 會藉由減少自己的記憶體使用量來回應。 很少有其他應用程式回應,因為它們不是設計來接聽該通知。 因此,如果 SQL 開始縮減其記憶體使用量,則會減少其記憶體集區,而且無論哪些元件需要記憶體,都可能無法取得記憶體。 您開始收到 701 和其他記憶體相關錯誤。 如需詳細資訊,請參閱 SQL Server 記憶體架構

內部記憶體壓力,不是來自 SQL Server

內部記憶體壓力是指 SQL Server 進程內因素所造成的記憶體可用性不足。 SQL Server 進程內可能會執行為 SQL Server 引擎「外部」的元件。 範例包括連結的伺服器、SQLCLR 元件、擴充程式 (XPs) 和 OLE Automation ( sp_OA* ) 等 DLL。 其他包括防毒軟體或其他安全性程式,這些程式會將 DLL 插入程式中以供監視之用。 上述任一元件中的問題或設計不佳可能會導致大量記憶體耗用量。 例如,假設連結的伺服器快取來自外部來源的資料列 2000 萬個數據列到 SQL Server 記憶體中。 就 SQL Server 而言,沒有記憶體 Clerk 會報告高記憶體使用量,但 SQL Server 進程內耗用的記憶體會很高。 例如,此記憶體從連結的伺服器 DLL 成長會導致 SQL Server 開始削減其記憶體使用量(如上圖),並將針對 SQL Server 內的元件建立低記憶體狀況,導致類似 701 的錯誤。

內部記憶體壓力,來自 SQL Server 元件(s)

來自 SQL Server 引擎內元件的內部記憶體壓力也可能導致錯誤 701。 透過記憶體 Clerk 追蹤 的數百個元件會在 SQL Server 中配置記憶體。 您必須識別哪些記憶體 Clerk(s) 負責最大的記憶體配置,才能進一步解決此問題。 例如,如果您發現OBJECTSTORE_LOCK_MANAGER記憶體 clerk 顯示大型記憶體配置,您需要進一步瞭解鎖定管理員為何耗用這麼多記憶體。 您可能會發常設查詢會取得大量的鎖定,並使用索引加以優化,或縮短長時間保留鎖定的交易,或檢查鎖定擴大是否已停用。 每個記憶體 Clerk 或元件都有唯一的存取和使用記憶體方式。 如需詳細資訊,請參閱 記憶體 Clerk 類型 及其描述。

使用者動作

如果錯誤 701 偶爾出現或短暫出現,可能會有短期記憶體問題自行解決。 在這些情況下,您可能不需要採取動作。 不過,如果錯誤發生多次,在多個連線上,並持續數秒或更長的時間,請遵循步驟以進一步進行疑難排解。

下列清單概述有助於針對記憶體錯誤進行疑難排解的一般步驟。

診斷工具和擷取

可讓您收集疑難排解資料的診斷工具為 效能監視器 sys.dm_os_memory_clerks DBCC MEMORYSTATUS。

使用效能監視器設定及收集下列計數器:

  • Memory:Available MB
  • Process:Working Set
  • Process:Private Bytes
  • SQL Server:Memory Manager:(所有計數器)
  • SQL Server:Buffer Manager:(所有計數器)

在受影響的 SQL Server 上收集此查詢的定期輸出

SELECT pages_kb, type, name, virtual_memory_committed_kb, awe_allocated_kb
FROM sys.dm_os_memory_clerks
ORDER BY pages_kb DESC

Pssdiag 或 SQL LogScout

擷取這些資料點的替代方式是使用 PSSDIAG SQL LogScout 之類的 工具。

  • 如果您使用 Pssdiag,請設定 來擷取 Perfmon 收集器和 自訂診斷\SQL 記憶體錯誤 收集器
  • 如果您使用 SQL LogScout,請設定 來擷取 記憶體 案例

下列各節說明每個案例的更詳細步驟 - 外部或內部記憶體壓力。

外部壓力:診斷和解決方案

  • 若要診斷 SQL Server 進程外部系統上的記憶體不足狀況,請收集效能監視器計數器。 查看下列計數器,調查 SQL Server 以外的應用程式或服務是否耗用此伺服器上的記憶體:

    • Memory:Available MB
    • Process:Working Set
    • Process:Private Bytes

    以下是使用 PowerShell 的 Perfmon 記錄收集範例

    clear
    $serverName = $env:COMPUTERNAME
    $Counters = @(
       ("\\$serverName" +"\Memory\Available MBytes"),
       ("\\$serverName" +"\Process(*)\Working Set"),
       ("\\$serverName" +"\Process(*)\Private Bytes")
    )
    
    Get-Counter -Counter $Counters -SampleInterval 2 -MaxSamples 1 | ForEach-Object  {
    $_.CounterSamples | ForEach-Object 	  {
       [pscustomobject]@{
          TimeStamp = $_.TimeStamp
          Path = $_.Path
          Value = ([Math]::Round($_.CookedValue, 3)) }
    }
    }
    
  • 檢閱系統事件記錄檔,並尋找記憶體相關錯誤(例如,低虛擬記憶體)。

  • 檢閱應用程式事件記錄檔中是否有應用程式相關的記憶體問題。

    以下是查詢關鍵字 「memory」 之 System and Applicaiton 事件記錄檔的範例 PowerShell 腳本。 您可以隨意使用其他字串,例如搜尋的「資源」:

    Get-EventLog System -ComputerName "$env:COMPUTERNAME" -Message "*memory*"
    Get-EventLog Application -ComputerName "$env:COMPUTERNAME" -Message "*memory*"
    
  • 解決較不重要的應用程式或服務的任何程式碼或組態問題,以減少其記憶體使用量。

  • 如果 SQL Server 以外的應用程式耗用資源,請嘗試停止或重新排程這些應用程式,或考慮在不同的伺服器上執行它們。 這些步驟會移除外部記憶體壓力。

內部記憶體壓力,不是來自 SQL Server:診斷和解決方案

若要診斷 SQL Server 內部模組 (DLL) 所造成的內部記憶體壓力,請使用下列方法:

  • 如果 SQL Server 不是* 使用 記憶體 中鎖定的頁面 (AWE API),則大部分的記憶體都會反映在 效能監視器中的 Process:Private Bytes 計數器 ( SQLServr 實例) 中。 SQL Server 引擎內的整體記憶體使用量會 反映在 SQL Server:Memory Manager:Total Server Memory (KB) 計數器中。 如果您在 Process:Private Bytes SQL Server:Memory Manager 值 之間發現顯著差異:總伺服器記憶體 (KB), 則差異可能來自 DLL(連結的伺服器、XP、SQLCLR 等)。 例如,如果 Private 位元組 為 300 GB,且 伺服器記憶體 總計為 250 GB,則進程中大約 50 GB 的整體記憶體來自 SQL Server 引擎外部。

  • 如果 SQL Server 使用記憶體中鎖定的頁面 (AWE API),則識別問題比較困難,因為效能監視器不提供 AWE 計數器來追蹤個別進程的記憶體使用量。 SQL Server 引擎內的整體記憶體使用量會 反映在 SQL Server:Memory Manager:Total Server Memory (KB) 計數器中。 一般 Process:Private Bytes 值整體可能會有所不同,介於 300 MB 和 1-2 GB 之間。 如果您發現 Process:Private Bytes 的使用量 超出此一般用途,則差異可能來自 DLL(連結的伺服器、XP、SQLCLR 等)。 例如,如果 Private bytes 計數器是 5-4 GB,且 SQL Server 使用記憶體中的鎖定頁面 (AWE),則大部分的私人位元組可能來自 SQL Server 引擎外部。 這是近似技術。

  • 使用 Tasklist 公用程式來識別在 SQL Server 空間內載入的任何 DLL:

    tasklist /M /FI "IMAGENAME eq sqlservr.exe"
    
  • 您也可以使用此查詢來檢查載入的模組 (DLL),並查看是否有預期的內容

    SELECT * FROM sys.dm_os_loaded_modules
    
  • 如果您懷疑連結伺服器模組造成大量記憶體耗用量,則可以藉由停用 [ 允許處理中] 選項,將它設定為用盡進程 。 如需詳細資訊,請參閱 建立連結的伺服器 。 並非所有連結的伺服器 OLEDB 提供者都可能用盡進程;如需詳細資訊,請連絡產品製造商。

  • 在罕見的情況下,使用 OLE 自動化物件 ( sp_OA* ), 您可以設定物件,只設定 內容 = 4 (Local (.exe) OLE 伺服器,以在 SQL Server 外部的進程中執行。 如需詳細資訊,請參閱 sp_OACreate

SQL Server 引擎的內部記憶體使用量:診斷和解決方案

  • 開始收集 SQL Server:SQL Server: Buffer Manager SQL Server:Memory Manager 的效能監視器計數器。

  • 查詢 SQL Server 記憶體 Clerks DMV 多次,以查看引擎內記憶體耗用量最高的位置:

    SELECT pages_kb, type, name, virtual_memory_committed_kb, awe_allocated_kb
    FROM sys.dm_os_memory_clerks
    ORDER BY pages_kb DESC
    
  • 或者,您可以觀察更詳細的 DBCC MEMORYSTATUS 輸出,以及當您看到這些錯誤訊息時變更的方式。

    DBCC MEMORYSTATUS
    
  • 如果您在記憶體 Clerk 中識別出明確的罪犯,請專注于解決該元件的記憶體耗用量細節。 以下是數個範例:

    • 如果MEMORYCLERK_SQLQERESER加值稅IONS記憶體 clerk 耗用記憶體,請識別使用大量記憶體授與的查詢,並透過索引加以優化、重寫它們(例如移除 ORDER,或套用查詢提示。
    • 如果快取大量的臨機操作查詢計劃,則CACHESTORE_SQLCP記憶體 clerk 會使用大量的記憶體。 識別無法重複使用查詢計劃的非參數化查詢,並藉由轉換成預存程式或使用 sp_executesql 或使用 FORCED 參數化來參數化它們。
    • 如果物件計畫快取存放區CACHESTORE_OBJCP耗用大量記憶體,請執行下列動作:識別哪些預存程式、函式或觸發程式使用大量記憶體,並可能重新設計應用程式。 通常,這可能是因為具有數百個程式的大量資料庫或架構所造成。
    • 如果OBJECTSTORE_LOCK_MANAGER記憶體 clerk 顯示大型記憶體配置,請識別套用許多鎖定的查詢,並使用索引加以優化。 縮短在特定隔離等級中造成鎖定長時間無法釋放的交易,或檢查鎖定擴大是否已停用。

快速緩解可能會讓記憶體可用

下列動作可能會釋放一些記憶體,並將其提供給 SQL Server 使用:

  • 請檢查下列 SQL Server 記憶體組態參數,並考慮盡可能增加 伺服器記憶體 上限:

    • 最大伺服器記憶體

    • 最小伺服器記憶體

      請注意不尋常的設定。 視需要更正它們。 考慮增加的記憶體需求。 預設設定會列在 [伺服器記憶體組態選項 ] 中

  • 如果您尚未 設定最大伺服器記憶體 ,特別是記憶體中鎖定的頁面,請考慮將 設定為特定值,以允許 OS 的某些記憶體。 請參閱 記憶體 伺服器組態中鎖定的頁面選項。

  • 檢查查詢工作負載:並行會話數目,目前正在執行查詢,並查看是否有較不重要的應用程式可能暫時停止或移至另一個 SQL Server。

  • 如果您在虛擬機器 (VM) 上執行 SQL Server,請確定 VM 的記憶體未過度認可。 如需如何設定 VM 記憶體的想法,請參閱此部落格 虛擬化 – 過度認可記憶體,以及如何在 VM 內偵測它,以及如何 針對 ESX/ESXi 虛擬機器效能問題進行疑難排解 (記憶體過度認可)

  • 您可以執行下列 DBCC 命令來釋放數個 SQL Server 記憶體快取。

    • DBCC FREESYSTEMCACHE

    • DBCC FREESESSIONCACHE

    • DBCC FREEPROCCACHE

  • 如果您使用資源管理員,建議您檢查資源集區或工作負載群組設定,並查看它們是否不會大幅限制記憶體。

  • 如果問題持續發生,您必須進一步調查,並可能增加伺服器資源 (RAM)。