몽고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) — 쓰고 싶은 유혹은 있지만 퍼포먼스 함정이라 피하는 중
결론: 트랜잭션 가능해졌어도 스키마를 트랜잭션 없이 돌아가게 설계하는 원칙은 유지. 쓰기 싫게 생겼을 때만 쓴다.
댓글 없음:
댓글 쓰기