共用方式為


MSSQLSERVER_701

適用於:SQL Server

詳細資料

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

注意

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

說明

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

使用者動作

如果錯誤 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

擷取這些數據點的替代方式是使用 PSSDIAGSQL 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 和 Application 事件記錄檔的範例 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 計數器 (SQLServrinstance) 中。 SQL Server 引擎內的整體記憶體使用量會 反映在 SQL Server:Memory Manager:Total Server Memory (KB) 計數器中。 如果您在 Process:Private BytesSQL 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
    
  • 如果您懷疑連結伺服器模組造成大量記憶體耗用量,則可以藉由停用 [ 允許處理中] 選項,將它設定為用盡進程 。 如需詳細資訊,請參閱建立連結的伺服器 (SQL Server 資料庫引擎)。 並非所有連結的伺服器OLEDB提供者都用盡進程;如需詳細資訊,請連絡產品製造商。

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

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

  • 開始收集 SQL Server:SQL Server:Buffer ManagerSQL 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_SQLQERESERVATIONS記憶體 clerk 耗用記憶體,請識別使用大量記憶體授與的查詢,並透過索引加以優化、重寫它們(例如移除 ORDER,或套用查詢提示。
    • 如果快取大量的臨機操作查詢計劃,則CACHESTORE_SQLCP記憶體 clerk 會使用大量的記憶體。 識別無法重複使用其查詢計劃的非參數化查詢,並藉由轉換成預存程式或使用 ,或使用 sp_executesql強制參數化來將其參數化。
    • 如果物件計劃快取存放區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)。