개요
시스템의 메모리사용량 증가로 인한 문제는 기본적으로 응용프로그램(User) 및 메모리테이블스페이스의 데이터 증가에 의해 발생한다. 응용프로그램에서 사용되는 쿼리로 인해 데이터베이스의 메모리적재가 일어나고 이로인해 가용메모리의 부족이 발생할수 있으며, Altibase의 고성능 데이터 처리를 위해 메모리테이블스페이스로 데이터를 관리할때 누적된 데이터로 인한 저장공간이 늘어나고 이로인한 가용메모리의 부족이 발생할수 있다.
본 문서에서는 Altibase가 점유하는 메모리영영의 부분들을 살펴보고 비정상적으로 메모리를 사용할 경우 어떤 형태로 해결할지에 대해 설명한다.
아래의 문서들을 미리 참고할 것을 권장한다.
1. 『Altibase 개발자 가이드』
2. 『Altibase SQL Tuning Guide』
3. 『Altibase 모니터링 쿼리가이드』
4. 『Altibase 메모리테이블스페이스 관리』
5. 『Altibase MVCC & GC』
본 문서의 테스트 환경은 다음과 같다.
- Altibase : Altibase 7 이상 버전
- OS : Linux ( 2.6.32-504.el6.x86_64 )
Memory 사용량 일상적 점검
서비스 운영 중에 갑작스런 메모리 부족에 의한 서비스 지연이 발생할 수 있는데 이 과정에서 지속적으로 메모리 부족 현상이 발생할 때 사용자가 확인할 부분과 해결방안에 대해 설명한다.
OS별 시스템 메모리/Swap 확인 방법
장비의 여유 메모리가 부족한지 여부는 OS명령어를 이용하여 가용 메모리를 확인 할 수 있다.
아래의 OS 명령어를 통해 메모리 사용 부분을 확인해 볼 수 있다.
AIX
항목(붉은 박스) 설명 size 전체 물리적 메모리의 페이지 개수를 의미한다. 실제 1page는 4,096byte임으로 7936M의 메모리를 갖는 시스템임. inuse (Computational + Persistent)의 실제 사용 중인 물리적인 메모리의 페이지 개수 free 물리적 메모리에서 사용 중이지 않은 페이지 개수 pin Swap out할 수 없는 물리적 메모리의 페이지 개수 virtual VMM (Virtual Memory Manager)에 의해 생성된 페이지 개수 pg space Paging space 공간의 사용량 HP-UX
# glance -> m 메모리 확인
현재 물리적인 메모리 32.0GB - 시스템 9.6GB + 유저 13.8GB + 파일캐쉬 722MB - 버퍼캐쉬 0GB + 프리 7.9GB (사용가능한 메모리량)
Linux
Linux에서는 메모리 사용 현황을 top 명령으로 조회할수 있으며, 아래는 top 결과 샘플이고 샘플내의 여러 항목들 중에서 free 와 cached의 값이 주요 항목이다.
linux에서 가용메모리 계산은 free + buffers + cached로 할수 있다.
위의 top 명령 결과로 메모리 용량을 분석해 본다면,
- 전제 물리 메모리 : 16630888k - 실제 사용중인 메모리(used - cached - buffers) : 16559108k - 16034200k - 100516k = 424392k - 실제 가용한 메모리 (free + buffers + cached) : 71780k + 100516k + 16034200k = 16206496k - 전체 메모리(실제 사용중인메모리 + 실제 가용한메모리) : 424392k + 16206496k = 16630888k
아래는 free명령을 통해 조회한 결과이다.(-m 옵션은 MB단위 출력지정)
일상적 점검 사항
사용자는 현재의 메모리 사용량에 대한 정상유무를 판단하기 위해 다음의 이력관리가 필요하다. 이것은 문제상황이 발생할 때 정상 대비 증가된 부분을 분석하여 원인을 추적하는데 중요한 정보로 활용이 가능하다.
항목 | 수집 방안 |
---|---|
시간대별/일별 메모리사용률 | OS가 제공하는 Altibase 프로세스의 메모리사용률 획득방법을 통해 주기적으로 기록/관리한다. |
시간대별/일별 트랜잭션 처리량 | 응용프로그램의 트랜잭션 처리량을 기록/관리한다. 이것이 어려울 경우 ALTIBASE에서 제공하는 V$SYSSTAT 을 통해 다음과 같은 정보를 주기적으로 획득하여 기록/관리한다. select * from v$memstat order by alloc_size desc; |
서비스쓰레드의 증감여부 | 평소보다 세션의 증가 혹은, 업무량의 증가로 인해 서비스쓰레드가 증가하는 경우가 있는데 이런 패턴이 발생하는지를 체크한다. SELECT COUNT(*) AS THREAD FROM V$SERVICE_THREAD; SELECT COUNT(*) AS SESSION FROM V$SESSION; |
아래와 같은 shell script를 이용하여 일정 간격으로 수집된 정보를 파일로 기록하는 방식이 좀 더 간편할 수 있다.
v$sysstat로 구해지는 EXECUTE COUNT는 누적값이므로 단위 시간당 증가량을 구하기 위해서는 단위시간 증가값 = ( 최근값 - 이전값 ) 과 같은 방식으로 계산해야 한다.
위의 shell script를 실행하였을 때는 아래와 같이 출력될 수 있다.
V$MEMSTAT
V$MEMSTAT는 Altibase가 제공하는 내부 모듈 별 메모리 사용량에 대한 Performance View이다.
Altibase 프로세스가 점유하고있는 메모리가 클경우 V$MEMSTAT 를 통해 Altibase의 메모리 사용부분을 세부적으로 확인할수 있다.
Altibase 프로세스 메모리 사용량 증가에 대한 원인과 조치
Altibase의 메모리가 아닌 다른 프로세스로 인하여 증가된 메모리는 여기에서 다루지 않고, Altibase의 프로세스 메모리의 증가부분에 대한 조치방법을 설명한다.
앞서 설명한 '일상적 점검' 항목을 기준으로 Altibase의 메모리 증가 부분은 다음과 같이 정리할 수 있다.
- 메모리 테이블의 데이터가 증가에 의한 경우
- 실행되는 SQL 문장의 수가 증가하는 경우
- MVCC(Multi Version Concurrency Control)기법에 의해 증가되는 경우
- Aging 대상정보의 삭제가 지연 처리되는 경우
위와 같은 대표적인 경우들에 대해 원인과 조치방법에 대해 자세히 살펴보도록 한다.
메모리 테이블의 데이터 증가
아래의 SQL 문장으로 메모리 데이터 사용량 증가 추이를 살펴본다.
위 질의에서 나온 결과 중 'Alloc의 공간은 데이터가 저장된 공간 및 사용 가능한 공간을 모두 포함한다. ('Used'는 데이터가 저장된 공간만 의미한다.)
사용자가 '1G'의 데이터를 적재한 후 '900M'정도를 삭제했다면 해당 테이블에는 '1G'의 Alloc된 공간이 존재하며 '100M'의 Used공간이 포함되어 있고 나머지 '900M'는 해당 테이블만이 사용 가능한 빈 공간으로 존재하게 된다.
Altibase를 사용하는 사용자의 대다수가 혼동하는 부분은 바로 이 '900M'에 대한 부분이다. 데이터가 삭제되었으니 'Altibase 혹은 OS시스템에서 이 공간이 'Free'되어 메모리 사용량이 줄어들어야 정상이 아닌가?' 라는 의문을 갖는다.
OS의 메모리관리 구조는 대부분 한번 할당된 메모리에 대해 프로그램이 Free하여도 즉시 OS로 반납하지 않는다. 실제로는 메모리상의 Reserved영역에 할당해 놓은 후 다른 응용프로그램이 메모리가 부족한 시점에 Free된 영역을 사용하는 알고리즘을 일반적으로 사용한다. 즉, 메모리를 할당하고 해제하는 과정의 비용이 크기 때문에 빈번한 메모리 할당/해제를 가급적 하지 않는다.
이러한 알고리즘 개념은 Altibase에도 마찬가지로 적용된다. Altibase 역시 한 번 사용된 공간은 데이터가 삭제되어도 테이블 내 재사용할 공간으로 유지한다.
사용자가 이러한 테이블을 발견했을 경우 조치방법은 다음과 같다.
해당 테이블을 Compaction한다.
메모리 테이블은 메모리 테이블스페이스로부터 공간을 할당 받게 된다. 하지만 하나의 테이블의 대량의 데이터 적재/삭제로 공간이 증가하면 동일 메모리 테이블스페이스에 존재하는 다른 테이블들이 할당 받을 공간이 부족해질 수 있음으로 더 이상 사용하지 않는 테이블의 공간을 동일 메모리테이블스페이스 내의 다른 테이블이 가용할 수있도록 반납할 수 있는데 이를 Compaction이라한다.- Altibase를 재구동한다.
위와 같은 조치를 취하면 동일 메모리테이블스페이스 내의 다른 테이블들이 공간을 할당 받을 수 있도록 1 차적인 조치가 가능하다. 그러나 여전히 OS에서 점유한 메모리 사용량은 줄어들지 않는다. 이 경우 Altibase를 재 구동하게 되면 메모리 사용량을 줄이는 것과 같은 효과를 나타낼 수 있는데 이는 다음과 같은 이유로 가능하다.
원래의 재 구동과정에서는 모든 메모리 테이블스페이스의 데이터페이지를 메모리로 적재하지만 실제 데이터가 쓰여지지 않는 빈 페이지들은 메모리로 올리지 않기 때문에 메모리 사용량을 감소시키는 효과를 볼 수 있다.
만일, 사용자가 일일이 테이블에 대한 Compaction을 하기 힘들다면 정기적인 PM과정에서 Altibase를 재 구동을 통해 Compaction 효과를 볼수 있다.
실행되는 SQL 문장의 수 증가
주기적으로 v$statement에 기록된 질의의 개수를 통해 확인이 가능하다. v$statement에 기록된 질의들은 현재 접속된 세션에서 수행한 질의만을 기록하기 때문에 정확하지 않으나 개략적인 개수를 파악하는 것에는 도움이 된다.
이 경우 업무적으로 필요한 질의의 증가임으로 사용자가 특별히 조치할 만한 사항은 없으나 다음의 사항을 개발자와 함께 확인할 경우들이 종종 발생할 수 있다.
모든 질의는 사용 후 Close되는지 여부의 확인
일반적으로 질의가 사용된 후에는 해당 질의에 대한 객체를 종료해야 한다.위의 짧은 코드에서 만일, 'ps.close'와 같은 구문이 존재하지 않으면 ALTIBASE 내부 모듈 중 'Query_Prepare'등에 해당 질의에 대한 정보유지를 위해 메모리를 지속적으로 유지하고 이러한 상황이 반복되면 세션이 종료되지 않는 이상 메모리는 계속 사용되게 된다.
한번 사용된 메모리는 Altibase자체적으로 Free시켜도 실제 OS에서 바로 회수하지 않기 때문에 결과적으로 메모리 사용량이 늘어난 상태로 운영되게 된다.
따라서, 질의수행에 사용된 객체가 정상적으로 해제되는지 여부를 확인하도록 해야 한다.비슷한 질의가 계속 사용되는 경우의 확인
다음의 예를 살펴보자.위 질의는 “SELECT 1 FROM DUAL WHERE C1 = ?”과 같은 구문으로 대체하고 조회 조건의 변수 값만 바뀌는 형태로 개발하면 하나의 문장으로 해결할 수 있다.
위와 같은 비슷한 질의들을 누적해서 실행할 경우 Altibase의 현재 버전에서는 각각 다른 질의로 분석하여 메모리를 할당하게 된다.
MVCC(Multi Version Concurrency Control) 기법에 의한 증가
MVCC기법은 조회/변경연산이 서로 대기하지 않도록 하여 성능을 높이는 DBMS의 일반적 동시성 제어기법을 의미한다. 현재 Altibase메모리 테이블은 변경연산 시점에 레코드의 복제 본을 생성하고 그 복제 본에 변경된 정보를 기록하는 형태로 동작한다.
따라서, 레코드에 대한 변경시점에는 원본과 복제 본이 함께 존재하는 형태가 된다.
(삭제 시점에는 위와 같은 메모리증가는 없으며 Aging지연에 의한 증가가 발생할 수 있다.)
이는, 대량의 변경작업을 수행하면 변경작업 대상 레코드의 개수만큼 복제 본이 생성된다는 것을 의미한다. (빠른 성능만큼 리소스의 사용이 증가되는 trade-off관계를 가진다.)
이러한 복제 본의 생성은 해당 테이블의 공간에 생성하게 된다. 따라서, 대량의 변경작업이 발생하면 해당 테이블의 사용량이 증가하게 된다. 만일, 테이블에 빈 공간이 존재하면 해당 공간이 사용되게 되고 부족하거나 없다면 테이블스페이스로부터 공간을 할당 받아 사용하게 된다.
사용자는 테이블 별 사용량 결과를 이용하여 지나치게 Alloc/Used의 차이가 현격한 테이블을 선별하고 업무적으로 사용량에 대한 이상징후가 발견되면 조치하도록 해야한다. 조치할 수 있는 방안은 앞서 설명한 테이블 Compaction이나 혹은 재 구동과 같은 방법을 사용해야 한다. 또한, 일반적으로 DBMS 작업과정에서 대량의 변경작업은 권장하는 작업방식이 아니기 때문에 일정 레코드 단위로 변경작업을 수행할 것을 권장한다.
예를 들어, 천만 건의 레코드를 변경해야 한다면 몇 만 건씩 단위작업으로 나누어 변경작업을 수행하도록 한다. (LIMIT절 사용)
Aging 지연에 의한 증가
앞서 설명한 MVCC에 의해 생성된 복제 본이 Commit시점에는 최종 레코드가 될 것임으로 원본 레코드는 삭제 대상이 된다. 만일, Rollback이 되면 복제 본은 삭제 대상이 된다. (이러한 삭제 대상 레코드를 “Old Version” 혹은 “Garbage Data”라고 하며 삭제 하는 작업을 내부적으로 Aging이라는 용어를 사용하고 GC (Garbage Collector)라는 내부 모듈이 담당)
문제는 이러한 삭제 대상을 어떠한 이유로 삭제하지 못하는 경우가 있을 수 있는데 이런 상태가 지속되면 계속 삭제 대상이 누적될 것임으로 메모리 사용량 증가를 유발할 수 있게 된다.
GC가 정상적으로 Aging을 하는지 여부는 다음의 질의를 통해 확인이 가능하다.
“add_oid_cnt”는 트랜잭션들이 Aging대상으로 넘겨준 대상을 의미한다. 즉, Aging을 요청한 트랜잭션의 수와도 같으며 “gc_oid_cnt”는 GC가 처리한 Aging대상의 개수를 의미한다.
위 수치가 계속 변경된다면 처리속도의 지연이 있더라도 GC가 정상적으로 작업을 한다고 볼 수 있다. 그러나 특정시점에 “gc_oid_cnt”가 증가되지 않는다면 문제가 발생한 것으로 간주할 수 있다.
GC모듈은 삭제대상 레코드가 어떠한 트랜잭션에 의해서도 참고되지 않아야 삭제할 수 있으며 삭제 대상 목록이 요청된 순서대로만 삭제처리를 진행할 수 있다. 따라서, GC에
문제가 있다고 판단되면 어떤 트랜잭션이 여전히 종료되지 않은 상태로 남아 있는 유형의 문제임으로 해당 트랜잭션을 찾아 정리할 필요가 있다. 이러한 질의는 다음과 같은 질의로 찾을 수 있다.
위 질의를 수행하면 해당 질의를 포함하여 문제가 되는 질의정보를 보여준다.
모니터링질의를 제외한 다른 질의가 나타난다면 해당 질의의 수행시간이 과도한 경우라면 튜닝 하거나 혹은, 사용자가 질의 수행 후 정상 종료를 하지 않았을 경우임으로 해당 프로그램의 소스를 확인하여 정상 종료가 가능하도록 조치해야 한다.
※ MVCC, GC와 관련된 메모리 증가유형은 메모리테이블에 한정된다.