다음을 통해 공유


SQL Server는 큰 일괄 처리를 실행할 때 701 "이 쿼리를 실행할 메모리가 부족합니다"라고 보고합니다.

이 문서에서는 SQL Server에서 대규모 작업 일괄 처리를 실행할 때 발생할 수 있는 701 오류에 대해 설명합니다. 701 오류의 다른 원인은 MSSQLSERVER_701 참조하세요.

원래 제품 버전: SQL Server
원래 KB 번호: 2001221

증상

SQL Server에서 RPC(원격 프로시저 호출)의 대규모 일괄 처리를 실행하는 경우(예: 단일 일괄 처리에서 수만 개의 삽입) SQL Server 오류 로그에 보고된 다음 오류로 작업이 실패할 수 있습니다.

2020-07-04 13:30:45.78 spid56 Error: 701, Severity: 17, State: 193. 
2020-07-04 13:30:45.78 spid56 There is insufficient system memory to run this query.

701 오류 메시지의 오류 로그에 자동으로 기록되는 DBCC MEMORYSTATUS 의 출력을 확인하면 다음과 같은 항목을 찾을 수 있습니다.

2020-07-04 13:30:45.74 spid56 Failed allocate pages: FAIL_PAGE_ALLOCATION 1 
2020-07-04 13:30:45.76 spid58
Memory Manager 
VM Reserved = 1657936 KB 
VM Committed = 66072 KB 
AWE Allocated = 2351104 KB ==> ~2.2 GB 
Reserved Memory = 1024 KB 
Reserved Memory In Use = 0 KB 

2020-07-04 13:30:45.76 spid56
USERSTORE_SXC (Total) 

VM Reserved = 0 KB 
VM Committed = 0 KB 
AWE Allocated = 0 KB 
SM Reserved = 0 KB 
SM Committed = 0 KB 
SinglePage Allocator = 1127848 KB==> ~1.07 GB 
MultiPage Allocator = 0 KB 

2020-07-04 13:30:45.78 spid56 Error: 701, Severity: 17, State: 193. 
2020-07-04 13:30:45.78 spid56 There is insufficient system memory to run this query. 

참고 항목

캐시 USERSTORE_SXC에 대한 대용량 할당을 확인합니다.

또한 일괄 처리가 실행되는 동안 sys.dm_os_memory_clerkssingle_pages_kb하는 경우 캐시의 열 USERSTORE_SXC 은 701 오류를 생성하는 기간 동안 지속적으로 증가합니다.

잠재적으로 이 동작을 나타낼 수 있는 애플리케이션의 예는 자세한 내용을 참조하세요.

원인

SQL Server에 요청을 저장하기 위해 할당된 메모리 양은 다음에 따라 달라집니다.

  • 일괄 처리 크기(요청당 RPC 수)입니다.
  • 매개 변수 수입니다.
  • 매개 변수의 형식입니다.

특정 유형의 매개 변수(예: sql_variant)의 경우 SQL Server는 잠재적으로 비효율적인 방식으로 메모리에 요청을 저장할 수 있습니다. 클라이언트가 이러한 유형의 매개 변수를 사용하는 대량의 요청을 보내는 경우 여러 RPC를 하나의 요청으로 보낼 수 있습니다. 이 시나리오에서는 서버가 실행되기 전에 전체 요청을 메모리에 누적합니다. 이로 인해 증상에 설명된 701 오류가 발생할 수 있습니다.

이 문제는 이전 버전의 SQL Server에서 훨씬 더 널리 퍼져 있습니다(특히 데이터 형식을 사용하는 sql_variant 경우). SQL Server 2008 이상 버전에는 특정 경우에 사용되는 메모리 양을 줄이고 전반적으로 더 효율적인 몇 가지 디자인 개선 사항이 있습니다.

해결

오류를 해결하려면 다음 방법 중 하나를 사용합니다.

  • 일괄 처리 크기를 줄입니다.
  • 매개 변수 형식을 변경합니다. 예를 들어 다른 형식으로 대체 sql_variant 합니다.

USERSTORE_SXC 캐시는 RPC 매개 변수 및 준비된 핸들과 연결된 메모리와 같은 연결 관리 수준 할당에 사용됩니다. 클라이언트가 많은 RPC 호출 일괄 처리가 포함된 요청을 보낼 때 각각과 같은 sql_variant많은 수의 특정 형식의 매개 변수를 사용할 수 있으므로 이 캐시에서 과도한 할당이 발생하여 사용 가능한 모든 메모리가 소모될 수 있습니다.

또한 애플리케이션을 모니터링하여 준비된 핸들을 적시에 닫아야 합니다. 이러한 핸들을 닫지 않으면 SQL Server가 서버 쪽의 연결된 개체에 대한 메모리를 해제하지 못하게 됩니다.

자세한 정보

이 문서에서 설명하는 문제를 재현하려면 다음 코드를 사용하여 애플리케이션을 만들고 프로그램이 실행될 때 캐시가 USERSTORE_SXC 증가하고 축소되는지 확인합니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace RPCBatching
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable t = new DataTable();
            t.Columns.Add("a", typeof(int));

            for(int i=0;i<100000;i++)
                t.Rows.Add(1);

            // pre-create the table with "CREATE TABLE t (a sql_Variant)" in a database named as test
            using (SqlConnection conn = new SqlConnection("server=tcp:localhost; integrated security=true; database=test"))
            {
               conn.Open();
                SqlDataAdapter da = new SqlDataAdapter(null, conn);
                da.InsertCommand = new SqlCommand("INSERT INTO t VALUES (@a)", conn);
                da.InsertCommand.Parameters.Add("@a", SqlDbType.Variant, 0, "a");
                da.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
                da.UpdateBatchSize = 100000;
                da.InsertCommand.CommandTimeout = 12000;
                da.Update(t);
            }
        }
    }
}