220716_TIL(2) : 트랜잭션 / DB 운영 방식 (Primary, Replica)

백승한·2022년 7월 16일
0

트랜잭션의 이해

트랜잭션이란?

트랜잭션 : 데이터베이스에서 데이터에 대한 하나의 논리적 실행단계
ACID (원자성, 일관성, 고립성, 지속성)는 데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질을 가리키는 약어
출처: 위키백과

  • 트랜잭션의 특징
    • DB에서 더 이상 쪼갤 수 없는 최소단위의 작업
    • 모두 저장되거나, 아무 것도 저장되지 않거나를 보장!!
    • 모! 아니면 도!!

데이터 1개 저장 시

트랜잭션 사용 예시

트랜잭션 시작

  1. A 계좌 잔고 200,000 원 이상 확인
    • A 계좌 잔고: 1,000,000 원
  2. A 계좌 잔고 200,000 원 금액 감소
    • A 계좌 잔고: 800,000 원 (1,000,000 원 - 200,000 원)
  3. B 계좌 잔고 200,000 원 금액 증가
    • B 계좌 잔고: 1,200,000 원 (1,000,000 원 + 200,000 원)

모두 성공 시 ⇒트랜잭션 Commit

중간에 하나라도 실패 시 ⇒ 트랜잭션 Rollback

@Transactional 의 정체

트랜잭션을 사용한 폴더 생성 코드 (객체 버젼)

public List<Folder> addFolders(List<String> folderNames, User user) {

    // 트랜잭션의 시작
    TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
        // 1) 입력으로 들어온 폴더 이름을 기준으로, 회원이 이미 생성한 폴더들을 조회합니다.
        List<Folder> existFolderList = folderRepository.findAllByUserAndNameIn(user, folderNames);

        List<Folder> savedFolderList = new ArrayList<>();
        for (String folderName : folderNames) {
            // 2) 이미 생성한 폴더가 아닌 경우만 폴더 생성
            if (isExistFolderName(folderName, existFolderList)) {
                // Exception 발생!
                throw new IllegalArgumentException("중복된 폴더명을 제거해 주세요! 폴더명: " + folderName);
            } else {
                Folder folder = new Folder(folderName, user);
                // 폴더명 저장
                folder = folderRepository.save(folder);
                savedFolderList.add(folder);
            }
        }

        // 트랜잭션 commit
        transactionManager.commit(status);

        return savedFolderList;
    } catch (Exception ex) {
        // 트랜잭션 rollback
        transactionManager.rollback(status);
        throw ex;
    }
}

트랜잭션을 사용한 폴더 생성 Flowchart

  • 비즈니스 로직에 트랜잭션 코드가 포함됨

Service에서 DB한테 트랜잭션 시작을 알려준다. 그럼 DB에서 트랜잭션 Id를 부여해주고 그 Id를 가지고 커밋하거나 롤백을 하는 흐름이다.

구조를 보니 전에 공부했던 AOP 구조와 거의 흡사하다.
그렇다. @Transactional은 AOP가 동작하는 것이다.

@Transactional 사용 시 폴더 생성 Flowchart

@Transactional
public List<Folder> addFolders(List<String> folderNames, User user) {
  // ...
}

현업 DB 운영 방식 (Primary, Replica)

  • 현업에서는 DB 를 2대 이상 운영
    • 문제점: DB1 과 DB2 를 어떻게 데이터 Sync 를 하지??

Primary / Replica 운영방식

  • 쓰기 전용 DB (Primary)읽기 전용 DB (Replica) 를 구분

    • Primary: 쓰기 전용
      • @Transactional 의 readOnly 속성
        @Transactional(**readOnly = false**)
      • readOnly 를 코드에 적지 않으면, 기본값은 false
        import org.springframework.transaction.annotation.Transactional;
        
        @Transactional
        public List<Folder> createFolders(List<String> folderNameList, User user) {
      • Write 된 Data (Create, Update, Delete) 가 Replica 로 Sync 됨 (Replication)
    • Replica (Secondary): 읽기 전용
      @Transactional(**readOnly = true**)
    • 하지만, 위 개념은 스프링에 Primary DB endpoint, Replica DB endpoint 를 설정해야지만 가능!!

Primary 에 문제가 생겼을 때

  • Replica 중 1개가 Primary 로 승격 됨

  • 다시 Primary - Replica 로 정상 운영

profile
방문해주셔서 감사합니다🙂

0개의 댓글