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

이 페이지에서는 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

다음 단계