메모리 사용량 관리 권장사항

이 페이지에서는 Cloud SQL 인스턴스의 메모리 사용량을 구성하는 방법을 설명합니다.

소개

Cloud SQL 인스턴스를 만들 때 인스턴스의 메모리 양을 선택합니다. PostgreSQL 데이터베이스의 워크로드가 증가하면 인스턴스의 메모리 사용량이 증가합니다. 메모리를 많이 사용하는 인스턴스에서 때때로 메모리 부족 문제를 초래하는 성능 병목 현상을 일으킬 수 있습니다.

수요가 증가하여 Cloud SQL 인스턴스의 메모리가 부족해지면 데이터베이스 다운타임이 발생할 수 있습니다. 따라서 인스턴스가 정상적인 상태로 작동하도록 인스턴스 메모리와 메모리 관련 데이터베이스 플래그를 올바르게 구성하고 메모리 사용량을 모니터링하는 것이 중요합니다.

PostgreSQL 메모리 구성요소는 크게 두 개의 섹션으로 나뉩니다.

  • 전역 메모리: 쿼리를 실행하기 위해 모든 프로세스에서 공유됩니다. 예를 들면 shared_buffersmax_connections입니다.
  • 로컬 메모리: 각 연결에 할당된 전용 메모리입니다. 예를 들면, work_mem, maintenance_work_memtemp_buffers입니다.

기타 구성 고려사항은 일반 권장사항운영 가이드라인을 참조하세요.

메모리 사용량 및 플래그

Cloud SQL 인스턴스의 메모리 사용량이 높을 때마다 다음과 같은 질문을 고려해야 할 수 있습니다.

  • 많은 메모리를 사용하는 쿼리 또는 프로세스는 무엇인가요?
  • 메모리 설정이 데이터베이스 활동에 적합한가요?
  • 메모리 설정을 어떻게 변경하나요?

PostgreSQL 데이터베이스가 작동하면 대부분의 메모리 사용량은 다음과 같은 몇 가지 영역에서 발생합니다.

  • 공유 버퍼: PostgreSQL에서 readwrite 작업의 테이블 데이터를 보관하도록 할당하는 공유 메모리입니다. read 작업의 경우 디스크에서 요청된 모든 데이터를 먼저 RAM으로 가져온 후 클라이언트에게 제공합니다. 마찬가지로 PostgreSQL에서도 데이터가 요청되면(예: SELECT * from emp) 먼저 캐싱을 위해 데이터를 디스크에서 shared_buffers로 가져온 다음 클라이언트에 제공합니다. write 작업에서도 마찬가지입니다.

    공유 버퍼는 데이터 캐싱, 연결 캐싱, 데이터 조작 언어(DML) 작업과 같은 데이터베이스 활동에 대한 모든 프로세스 및 연결에 대한 공유 메모리 영역이기도 합니다. 이 영역에서 할당할 수 있는 최댓값은 shared_buffers 플래그로 지정되며 기본값은 인스턴스 메모리의 33%입니다. shared_buffers 값이 높으면 메모리에 캐시된 데이터 크기가 큽니다.

  • 쿼리 작업 메모리: 쿼리가 실행되면 PostgreSQL은 정렬 및 해싱과 같은 각 작업에 로컬 메모리를 할당합니다. 임시 디스크 파일에 쓰기 전에 각 쿼리 작업에 할당할 수 있는 최댓값은 work_mem 플래그로 구성되며 기본값은 4MB입니다. work_mem 값이 높으면 메모리에 정렬할 수 있는 데이터 양이 많습니다.
  • 유지보수 작업 메모리: VACUUM, CREATE INDEX, ALTER TABLE, ADD FOREIGN KEY와 같은 일부 유지보수 작업에는 PostgreSQL이 할당하는 별도의 로컬 메모리가 필요합니다. 이러한 작업에서 사용하는 백엔드 프로세스의 최대 크기는 maintenance_work_mem 플래그로 구성할 수 있으며 기본값은 64MB입니다. autovacuum 작업자도 유지보수 작업 메모리를 사용하며 최댓값은 autovacuum_work_mem 플래그로 재정의할 수 있습니다. maintenance_work_mem 값이 높으면 VACUUM 작업의 성능 속도가 높습니다.
  • 임시 버퍼: 데이터베이스 세션에서 임시 테이블이 사용되는 경우 PostgreSQL은 세션 로컬 임시 테이블을 저장할 임시 버퍼를 할당합니다. 최대 용량은 temp_buffers 플래그로 지정할 수 있으며 기본값은 8MB입니다.
  • 데이터베이스 연결: 클라이언트가 데이터베이스에 연결하면 PostgreSQL은 클라이언트 세션을 제공하기 위한 백엔드 프로세스를 만듭니다. PostgreSQL은 쿼리를 실행할 메모리 외에도 시스템 카탈로그 캐시 및 준비된 쿼리 계획과 같은 정보를 유지관리하기 위해 추가 메모리를 할당합니다. 데이터베이스 서버에 허용되는 최대 동시 연결 수는 max_connections 플래그로 구성할 수 있습니다. 각 유휴 연결은 약 2MB~3MB의 공유 메모리를 사용합니다. max_connections 값이 높으면 인스턴스가 더 많은 연결을 설정할 수 있지만 메모리가 사용됩니다.

PostgreSQL의 메모리 구성요소의 전체 목록은 PostgreSQL 문서를 참조하세요. 이 섹션에 나열된 플래그를 변경하거나 수정하려면 데이터베이스 플래그 구성을 참조하세요.

메모리 사용량 모니터링

Cloud Monitoring에서 인스턴스 메모리를 정기적으로 모니터링하고, 메모리 한도 미만으로 유지합니다. 6시간 동안 사용량이 한도의 90%를 초과할 경우 알림을 받도록 Cloud Monitoring에서 알림을 설정하는 것이 좋습니다. 이 알림은 메모리 사용량이 한도에 지속적으로 가까워질 때 경고를 보낼 수 있습니다.

또한 메모리 부족 이슈를 모니터링합니다. 이를 위해 Cloud Monitoring에서 server process .* was terminated by signal 9: Killed 메시지에 대해 로그 기반 측정항목을 설정하여 메모리 부족 이벤트를 계산한 다음 이벤트가 발생할 때마다 알림을 보냅니다.

인스턴스가 메모리 한도의 90% 이상으로 계속 작동하거나 메모리 부족 이벤트가 발생하는 경우 인스턴스의 메모리를 늘릴 수 있습니다. 또는 데이터베이스 연결 수를 제한하거나 shared_buffers, work_mem, max_connections 등의 데이터베이스 플래그를 낮춰 메모리 사용량을 줄일 수 있습니다. 이러한 플래그를 낮추면 인스턴스의 성능이 제한될 수 있습니다.

메모리 부족

데이터베이스 워크로드를 처리할 메모리가 부족한 경우 최후의 수단으로 기본 Linux 운영체제가 out-of-memory (OOM) killer를 사용하여 메모리 해제 프로세스를 종료합니다. Cloud SQL은 OOM killer가 PostgreSQL 작업자 프로세스만 대상으로 지정하도록 구성됩니다. 이 경우 데이터베이스의 무결성을 보호하기 위해 모든 기존 데이터베이스 연결을 종료하고 복구를 실행하기만 하면 되도록 postmaster 프로세스가 보존됩니다. 이 경우 데이터베이스에 서비스 중단 및 다운타임이 발생합니다. PostgreSQL 데이터베이스 로그에 다음과 같은 메시지가 표시됩니다.

2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed
2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col
2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes
2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process
2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command.
2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab"
...
2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode
...
2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing
...
2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC
2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress
2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400
2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508
2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00
2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections

다음 단계