20200920

MongoDB 4.4 transactions 실전

몽고DB 트랜잭션이 4.0에서 replica set, 4.2에서 sharded cluster까지 열린 뒤 사내 일부 서비스에서 조심스럽게 쓰기 시작. 4.4 올리고 정리.

드라이버는 pymongo 3.11. 세션 열고 with_transaction 블록으로 감싸는 게 표준 패턴.

def transfer(session, src, dst, amount):
    accounts.update_one(
        {"_id": src, "balance": {"$gte": amount}},
        {"$inc": {"balance": -amount}},
        session=session,
    )
    accounts.update_one(
        {"_id": dst},
        {"$inc": {"balance": amount}},
        session=session,
    )

with client.start_session() as session:
    session.with_transaction(
        lambda s: transfer(s, "a", "b", 100),
        read_concern=ReadConcern("snapshot"),
        write_concern=WriteConcern("majority"),
    )

운영 체감:

  • 트랜잭션은 "가능"한 거지 "권장"은 아님. 짧게, 적은 컬렉션만 건드리는 게 원칙.
  • 60초 기본 타임아웃. 이 안에 안 끝나면 abort. 안에서 외부 API 호출 금물.
  • sharded tx는 정말 느리다. 벤치 결과 단일 문서 업데이트 대비 3~5배. 정말 필요한 경우에만.
  • 충돌 시 TransientTransactionError 나오면 자동 retry되는 편. 명시적 retry 필요한 경우도 있으니 테스트 필수.

4.4 개선점 중 유용한 것:

  • hedged reads: secondary 두 개에 병렬로 읽어서 빠른 쪽 응답 사용. p99 개선됨
  • refinable shard keys: 샤드 키에 접두어 추가 가능. 기존엔 샤드 키 잘못 정하면 리샤딩 외엔 답 없었음
  • custom aggregation expressions ($function) — 쓰고 싶은 유혹은 있지만 퍼포먼스 함정이라 피하는 중

결론: 트랜잭션 가능해졌어도 스키마를 트랜잭션 없이 돌아가게 설계하는 원칙은 유지. 쓰기 싫게 생겼을 때만 쓴다.

댓글 없음: