Search

[인슈어런스] Database 개발 및 작업 가이드

유의사항 (배경)

토스 개발팀에서는 데이터베이스 부하를 분산하기 위해서 RW (DML 전용)와 RO (조회 전용)으로 데이터베이스를 분리하여 운영하고 있습니다. 이 때 RW에 INSERT, UPDATE, DELETE 된 데이터가 RO 에 복제됩니다.
이 때 아래와 같은 이유로 복제가 지연되거나 중단될 수 있으며 이는 RW, RO 데이터베이스 간에 데이터 불일치를 초래하여 비지니스 로직 오류 및 서비스 중단을 초래할 수 있습니다.
Slow Query 로 인한 데이터베이스 성능 저하로 인한 복제 지연
장시간 데이터베이스 Lock 을 획득하거나 또는 다량의 데이터에 대해 DML 처리 후 commit 할 경우
짧은 시간에 DML 데이터 증가로 인한 복제 지연 및 중단
RO 데이터베이스에 DML (INSERT, UPDATE, DELETE) 쿼리를 실행하는 경우 (복제 중단 초래)

요청 및 권고사항 (결론)

SELECT 부하를 줄이기 위해 EXPLAIN 으로 인덱스가 적용되는지와 1초 이내로 응답이 되는지 확인해야 합니다. 또한 동적 생성 쿼리에 따라 조건절이 변경되므로 모든 검색 조건에 부합한 인덱스가 적용되는지 확인해야 합니다.
테이블 생성시 PK 를 반드시 설정해야 합니다. (Auto increment 강력 권고)
MySQL 8.0 의 PK 는 기본적으로 클러스터 인덱스로 등록되어 일반 인덱스보다 조회 성능이 우수.
PK는 쿼리 데이터의 물리적인 저장 순서에 영향을 줍니다. 따라서 자동 증가(Auto increment) 속성 컬럼을 PK 로 설정하는 것이 DML 작업에 유리합니다.
INSERT SELECT 와 같이 데이터 처리량을 제어할 수 없는 구문을 사용하지 않습니다.
UPDATE, DELETE 는 반드시 PK 를 조건으로 실행하고, Loop 를 돌며 UPDATE, DELETE 할 때는 2000 건당 1초씩 sleep 을 주어 RO 가 RW 를 안정적으로 반영할 수 있도록 처리해야 합니다.
DML 쿼리를 실행할때 auto_commit = 1 로 처리 혹은 한개 쿼리당 commit을 원칙으로 합니다.
단일 Transaction 에서 10 or 100개 묶음마다 commit 하지 않습니다.
아래 쿼리는 2000개당 한 개 commit 이기 때문에 사용하면 안됩니다.
update dml_table set values_2 = 4 where id in (1,2,…2000) and values_1 = 'aaa';

고려 후 적용해 볼 항목 (다음 스텝)

SELECT 작업은 read-only 데이터베이스에서 수행되도록 Database connection 을 분리해야 합니다. (현재는 DML 과 SELECT 를 모두 RW 데이터베이스에서 수행하고 있음)
대량 데이터로 증가될 데이터 테이블은 페이지네이션 방식을 LIMIT OFFSET 이 아니라 Cursor-based Pagination 으로 구현해야 합니다.
빈번하게 조회되는 데이터는 In memory cache 로 등록하여 사용하거나 Redis 에 등록하여 사용하는 것을 지향해야 합니다.