MSSQLSERVER_701
적용 대상: SQL Server
세부 정보
attribute | 값 |
---|---|
제품 이름 | SQL Server |
이벤트 ID | 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 구성 요소, XP(확장 프로시저) 및 OLE 자동화(sp_OA*
)와 같은 DLL이 있습니다. 그 외에는 모니터링 목적으로 프로세스 내에 DLL을 삽입하는 바이러스 백신 또는 기타 보안 프로그램이 포함됩니다. 이러한 구성 요소 중에서 문제가 발생하거나 설계가 잘못되면 메모리 사용량이 커질 수 있습니다. 예를 들어 외부 원본에서 SQL Server 메모리로 2천만 개의 행 데이터를 캐싱하는 연결된 서버를 고려해 보세요. SQL Server의 경우 메모리 클럭은 높은 메모리 사용량을 보고하지 않지만 SQL Server 프로세스 내에서 사용되는 메모리는 높아집니다. 예를 들어 연결된 서버 DLL의 메모리 증가로 인해 SQL Server가 메모리 사용량을 줄이게 되고(위 참조) SQL Server 내의 구성 요소에 대한 메모리 부족 조건이 만들어져 701과 같은 오류가 발생합니다.
SQL Server 구성 요소에서 발생하는 내부 메모리 압력
SQL Server 엔진 내부 구성 요소에서 발생하는 내부 메모리 압력으로 인해 오류 701이 발생할 수도 있습니다. SQL Server에서 메모리를 할당하는 sys.dm_os_memory_clerks 통해 추적되는 수백 개의 구성 요소가 있습니다. 이 문제를 추가로 해결할 수 있도록 가장 큰 메모리 할당을 담당하는 메모리 클럭을 식별해야 합니다. 예를 들어 OBJECTSTORE_LOCK_MANAGER 메모리 클럭에 대용량 메모리 할당이 표시되는 경우 Lock Manager가 너무 많은 메모리를 사용하는 이유를 더 잘 파악해야 합니다. 많은 수의 잠금을 획득하고 인덱스를 사용하여 최적화하거나 장기간 잠금을 보유하는 트랜잭션을 줄이거나 잠금 에스컬레이션이 비활성화되었는지 확인하는 쿼리가 있을 수 있습니다. 각 메모리 클럭 또는 구성 요소에는 메모리에 액세스하고 사용하는 고유한 방법이 있습니다. 자세한 내용은 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
이러한 데이터 요소를 캡처하는 또 다른 자동화된 방법은 PSSDIAG 또는 SQL LogScout와 같은 도구를 사용하는 것입니다.
- Pssdiag를 사용하는 경우 Perfmon 수집기 및 Custom Diagnostics\SQL Memory Error 수집기를 캡처하도록 구성합니다.
- 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" 키워드를 쿼리하는 샘플 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: Total Server Memory (KB) 간에 상당한 차이가 있는 경우 이러한 차이는 DLL(연결된 서버, XP, SQLCLR 등)에서 발생할 수 있습니다. 예를 들어 전용 바이트가 300GB이고 총 서버 메모리가 250GB인 경우 프로세스의 전체 메모리 중 약 50GB가 SQL Server 엔진 외부에서 제공됩니다.SQL Server가 메모리의 잠금 페이지(AWE API)를 사용하는 경우 성능 모니터가 개별 프로세스에 대한 메모리 사용량을 추적하는 AWE 카운터를 제공하지 않으므로 문제를 식별하는 것이 더 어렵습니다. SQL Server 엔진 내에서 발생하는 전체 메모리 사용량은 SQL Server:Memory Manager: Total Server Memory (KB) 카운터에 반영됩니다. 일반적인 프로세스:프라이빗 바이트 값은 전체적으로 300MB에서 1-2GB 사이일 수 있습니다. 이 일반적인 사용량 이상으로 Process:Private Bytes를 많이 사용하는 경우 DLL(연결된 서버, XP, SQLCLR 등)에서 차이가 발생할 수 있습니다. 예를 들어 프라이빗 바이트 카운터가 5-4GB이고 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 자동화 개체가 사용되는 경우() 컨텍스트 = 4(로컬(
sp_OA*
.exe) OLE 서버만 설정하여 SQL Server 외부의 프로세스에서 실행되도록 개체를 구성할 수 있습니다. 자세한 내용은 sp_OACreate를 참조하세요.
SQL Server 엔진별 내부 메모리 사용량: 진단 및 솔루션
SQL Server:SQL Server:Buffer Manager, SQL Server: Memory Manager에 대한 성능 모니터 카운터 수집을 시작합니다.
SQL Server 메모리 클럭 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
메모리 클럭 중 명확한 위반자를 식별하는 경우 해당 구성 요소의 메모리 사용량 세부 사항을 해결하는 데 집중합니다. 다음은 몇 가지 예입니다.
- MEMORYCLERK_SQLQERESERVATIONS 메모리 클럭이 메모리를 사용하는 경우 대규모 메모리 부여를 사용하는 쿼리를 식별하여 인덱스를 통해 최적화하거나, 다시 작성하거나(예: ORDER 제거) 쿼리 힌트를 적용합니다.
- 많은 수의 임시 쿼리 계획이 캐시되는 경우 CACHESTORE_SQLCP 메모리 클럭은 많은 양의 메모리를 사용합니다. 쿼리 계획을 다시 사용할 수 없는 매개 변수가 없는 쿼리를 식별하고 저장 프로시저로 변환하거나 FORCED 매개 변수화를 사용하여
sp_executesql
매개 변수화합니다. - 개체 계획 캐시 저장소 CACHESTORE_OBJCP가 많은 메모리를 사용하는 경우 다음을 수행합니다. 많은 메모리를 사용하는 저장 프로시저, 함수 또는 트리거를 식별하고 애플리케이션을 재설계할 수 있습니다. 일반적으로 이 오류는 각각에 수백 개의 프로시저가 있는 많은 양의 데이터베이스 또는 스키마로 인해 발생할 수 있습니다.
- OBJECTSTORE_LOCK_MANAGER 메모리 클럭이 큰 메모리 할당을 표시하는 경우 많은 잠금을 적용하는 쿼리를 식별하고 인덱스를 사용하여 최적화합니다. 특정 격리 수준에서 잠금이 오랫동안 해제되지 않도록 하는 트랜잭션을 줄이거나 잠금 에스컬레이션이 비활성화되었는지 확인합니다.
메모리를 사용할 수 있도록 하는 빠른 완화
다음 작업은 일부 메모리를 해제하고 SQL Server에서 사용할 수 있도록 할 수 있습니다.
다음 SQL Server 메모리 구성 매개 변수를 확인하고 가능한 경우 최대 서버 메모리를 늘리는 것이 좋습니다.
최대 서버 메모리
최소 서버 메모리
비정상적인 설정을 확인합니다. 필요에 따라 수정합니다. 메모리 요구 사항 증가를 고려합니다. 기본 설정은 서버 메모리 구성 옵션에 나열되어 있습니다.
특히 메모리의 잠금 페이지를 사용하여 최대 서버 메모리를 구성하지 않은 경우 OS에 대한 일부 메모리를 허용하도록 특정 값으로 설정하는 것이 좋습니다. 메모리 서버 구성 옵션의 페이지 잠금을 참조하세요.
쿼리 워크로드: 동시 세션 수, 현재 실행 중인 쿼리를 확인하고 일시적으로 중지하거나 다른 SQL Server로 이동할 수 있는 덜 중요한 애플리케이션이 있는지 확인합니다.
VM(가상 머신)에서 SQL Server를 실행하는 경우 VM의 메모리가 과도하게 커밋되지 않았는지 확인합니다. VM 메모리를 구성하는 방법에 대한 아이디어는 이 블로그 가상화 – 메모리 오버커밋 및 VM 내에서 메모리를 검색하는 방법 및 ESX/ESXi 가상 머신 성능 문제 해결(메모리 오버커밋)을 참조하세요.
다음 DBCC 명령을 실행하여 여러 SQL Server 메모리 캐시를 해제할 수 있습니다.
DBCC FREESYSTEMCACHE
DBCC FREESESSIONCACHE
DBCC FREEPROCCACHE
Reource Governor를 사용하는 경우 리소스 풀 또는 워크로드 그룹 설정을 확인하고 메모리를 너무 크게 제한하지 않는지 확인하는 것이 좋습니다.
문제가 지속되면 추가적인 조사를 수행하고 서버 리소스(RAM)를 줄여야 할 수 있습니다.