RDS에서 특정 테이블의 변경 이력을 통지하고 싶다면?

RDS Aurora PostgreSQL에서 특정 테이블의 변경사항을 통지하는 방법에 대해 간략하게 알아보는 글입니다.
2024.02.14

안녕하세요 클래스메소드의 수재입니다.
담당 안건 중 하나에서 RDS의 특정 테이블의 변경 전후의 내용을 알고 싶다는 질문이 있었습니다.
이에 대해 조사한 내용을 저도 공부할 겸 공유하고자 합니다.(Aurora PostgreSQL을 사용중이라는 전재하에 글을 작성합니다.)

우선 결론

고객이 이용중인 환경은 Aurora PostgreSQL 이며 제가 제안한 방법은 3가지 였습니다.

  • TRIGGER, RETURN 등을 이용 -- 선분이력 테이블 활용
  • RDS Database Activity Stream 이용

TRIGGER, RETURN 등을 이용

PostgreSQL 뿐만 아니라 다른 엔진에서도 데이터베이스에 어떠한 이벤트가 일어나면 작성한 코드를 실행시키는 기능이 있는데 PostgreSQL은 이를 Trigger(트리거)로 구현할 수 있습니다.
구문은 다음과 같습니다.

CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
    ON table_name
...
    EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )
  • PostgreSQL Trigger 보통 테이블의 감사나 변경 이력을 기록할 때 많이 사용합니다.
    작성한 트리거는 테이블을 삭제할 때 함께 삭제됩니다.

이번 사항의 경우에는 UPDATE가 발생하였을 때 현재 값을 별도의 테이블에 기록하고 업데이트 되는 값을 변경되는 값으로 기록하는 식으로 이용하는 것을 생각하고 있었습니다.

참고가 될 글을 공유드립니다.

RETURN은 어떠한 쿼리가 실행된 결과로 테이블을 반환하는 기능입니다.
구문은 다음과 같습니다.

RETURN expression;
## 예
-- functions returning a scalar type
RETURN 1 + 2;
RETURN scalar_var;

UPDATE, INSERT, UPSERT, DELETE 등 데이터를 조작하는 쿼리를 실행하고 반영된 row만 확인하는 것이 아닌 상세한 값을 확인하고 이를 또다시 활용하는 경우에 사용됩니다.
이번 사항의 경우 UPDATE 후 문제가 없다면 RETURN 된 값을 확인하는 식으로 활용이 가능할 것이라 생각되었습니다.

다음은 참고 자료입니다.

선분이력 테이블 활용

엔진 자체의 기능을 이용하여 변경 이력을 알기 위해서는 위의 트리거나 리턴과 같이 어떠한 이벤트가 발생하거나 종료 후에 값을 확인하여 별도의 테이블에 저장하는 식의 운용이 많았습니다. 변경 전후의 값의 비교가 필요하다면 변경 후의 값 뿐만 아니라 변경 전의 값도 같이 저장해야합니다.
이와 같이 어떠한 데이터가 발생한 후의 값만 저장하는 것을 점 이력이라 하며 변경 전후와 같이 이어지는 데이터의 변경은 선분 이력이라고 합니다.

이번 사항의 경우에도 변경 전후가 필요하니 엔진 자체의 기능으로 구현한다면 선분 테이블의 준비도 하는 것이 좋다고 생각되었습니다.

테이블의 변경 사항을 이메일로 통지하기

기본적으로 RDS를 바로 SNS 토픽과 연결하여 통지 할 수 있는 이벤트 알림 기능이 있습니다.

이 기능의 대응 범위는 RDS 자체의 이벤트이며 DB 내부의 DML 등의 이벤트에 대해 사용하는 기능이 아닙니다.
따라서 DB 내부의 특정 이벤트를 SNS로 통지하기 위해서는 별도의 방법이 필요해지는데 이때 사용하는 것이 aws_lambda 확장입니다.
SNS 토픽으로 내용을 보내는 Lambda를 작성하고 DB에서 어떠한 이벤트가 발생하면 해당 Lambda를 호출하는 방법으로 내부의 이벤트에 대해 알람을 보낼 수 있습니다.

활용 방법은 다음 글이 참고해주세요.

RDS Database Activity Stream 이용

RDS는 데이터베이스 전반의 활동을 감시하기위한 기능으로 Database Activity Stream(이하 DAS)라는 기능을 제공하고 있습니다.

Aurora도 해당 기능을 제공하고 있습니다.

감시 범위는 클러스터 전체이며 활동을 Amazon Kinesis 데이터 스트림에 거의 실시간으로 푸시합니다.
Kinesis 스트림은 자동으로 생성되며 Kinesis에서 Amazon Kinesis Data Firehose 및 AWS Lambda와 같은 AWS 서비스를 구성하여 스트림을 사용하고 데이터를 저장할 수 있습니다.

DAS는 동기식 모드와 비동기식 모드가 있으며 동기식 모드는 Aurora PostgreSQL만 사용할 수 있습니다.
동기식 모드는 데이터베이스 세션이 활동 스트림 이벤트를 생성할 때, 이 세션은 이벤트가 지속될 때까지 다른 활동을 차단합니다. 데이터베이스 성능보다 활동 스트림의 정확성을 우선시하는 모드입니다.
비동기식 모드는 데이터베이스 세션이 활동 스트림 이벤트를 생성하면 세션은 즉시 정상 활동으로 되돌아갑니다. 활동 스트림의 정확성보다 데이터베이스 성능을 우선시하는 모드입니다.

주의 사항

공식 문서에 따르면 DAS의 사용에는 다음과 같은 제한 사항이 있습니다.

  • 데이터베이스 활동 스트림에는 Amazon Kinesis를 사용해야 합니다.
  • 데이터베이스 활동 스트림은 항상 암호화되므로 AWS Key Management Service(AWS KMS)를 사용해야 합니다.
  • Amazon Kinesis 데이터 스트림에 추가 암호화를 적용하는 것은 이미 AWS KMS 키를 사용하여 암호화된 데이터베이스 활동 스트림과 호환되지 않습니다.
  • DB 클러스터 수준에서 데이터베이스 활동 스트림을 시작합니다. 클러스터에 DB 인스턴스를 추가하는 경우 인스턴스에서 활동 스트림을 시작할 필요가 없이 자동으로 감사됩니다.
  • Aurora 글로벌 데이터베이스에서는 활동 스트림을 각 DB 클러스터에서 별도로 시작해야 합니다. 각 클러스터는 자체 AWS 리전 내의 자체 Kinesis 스트림에 감사 데이터를 제공합니다.
  • Aurora PostgreSQL에서는 업그레이드 전에 데이터베이스 활동 스트림을 중지해야 합니다. 업그레이드가 완료된 후 데이터베이스 활동 스트림을 시작할 수 있습니다.

또한 인스턴스 타입에 따라 지원여부가 나뉩니다.
Aurora MySQL의 경우 데이터베이스 활동 스트림을 다음 DB 인스턴스 클래스와 함께 사용할 수 있습니다.

  • db.r7g.*large
  • db.r6g.*large
  • db.r6i.*large
  • db.r5.*large
  • db.x2g.*

Aurora PostgreSQL의 경우 데이터베이스 활동 스트림을 다음 DB 인스턴스 클래스와 함께 사용할 수 있습니다.

  • db.r7g.*large
  • db.r6g.*large
  • db.r6i.*large
  • db.r6id.*large
  • db.r5.*large
  • db.r4.*large
  • db.x2g.*

DAS 자체는 무료 기능이지만 Kinesis의 비용은 발생하기 때문에 이번 사항과 같이 특정 테이블의 변경만을 확인하는 경우 생각보다 많은 비용이 발생할 수 있습니다.
기능 자체가 특정 테이블만을 감시하기 위한 것이 아니라 클러스터 전체의 기능을 감시하는 것이 목적이기 때문입니다.
따라서 한 테이블의 감시 뿐만 아니라 다른 인스턴스의 감시도 설정한다면 DAS를 활용하는 것이 더 적합하다고 생각됩니다.

Kinesis와 SNS를 연결하기

DAS는 스트림 데이터를 Kinesis Data Streams로 보내며 이 데이터를 SNS 토픽으로 보내기 위해서는 Kinesis Data Firehose를 이용하는 것이 일반적입니다.
해당 내용에 참고가 될 글도 공유합니다.

마무리

해당 내용은 앞으로 다른 사안에도 많이 이용될 것 같아 정리하길 잘했다고 생각합니다.
DB에 대해서 아직 모르는게 많기 때문에 다양한 피드백을 주시면 감사합니다.

긴 글 읽어주셔서 감사합니다.
내용 및 오탈자 피드백은 must01940 지메일로 보내주시면 감사합니다.