모든 글 · 2쪽

전체 글 124편 중 13–24번째 글이에요. 최신 글이 앞에 있어요.

2쪽 글 목록

124편 중 13–24

  1. LIMIT 이 붙으면 계획이 통째로 바뀐다

    LIMIT 10 을 붙였더니 오히려 느려졌어요. LIMIT 10 은 0.1초인데 LIMIT 100 은 12초가 걸리기도 하고요. LIMIT 값 하나에 옵티마이저가 계획을 통째로 바꾸는 이유와 대처법을 정리했어요.

    5분#DB
  2. EXPLAIN ANALYZE 읽는 법 — 추정 행 수와 실제 행 수 비교하기

    느린 쿼리를 잡으려고 EXPLAIN 을 열어도 숫자가 무슨 뜻인지 모르겠어요. 인덱스 스캔인데도 느리면 더 막막하고요. 실행 계획에서 먼저 봐야 할 두 숫자와 읽는 순서를 정리했어요.

    4분#DB
  3. @Transactional(readOnly = true) 를 안 붙이면 복제본으로 안 간다

    읽기 복제본을 붙였는데 주 서버 부하가 그대로예요. 라우팅 설정도 맞는데요. 조회만 하는 코드도 읽기 전용이라고 선언하지 않으면 쓰기로 취급되는 이유와 그 한 줄이 바꾸는 것을 정리했어요.

    5분#DB
  4. 배치를 트랜잭션 하나로 돌리지 마라

    백만 건 야간 배치를 트랜잭션 하나로 감쌌더니, 도는 두 시간 동안 서비스가 느려지고 실패하면 처음부터 다시 해야 했어요. 배치를 잘게 나눠 중간부터 이어 하게 만드는 법을 정리했어요.

    5분#DB
  5. 낙관적 락 vs 비관적 락 — 충돌 확률로 고르는 기준

    낙관적 잠금은 빠르고 비관적 잠금은 안전하다는 말, 둘 다 맞게 들려서 더 헷갈려요. 실제로는 충돌이 얼마나 자주 나느냐에 따라 유불리가 뒤집혀요. 상황별로 고르는 기준을 정리했어요.

    5분#DB
  6. 트랜잭션은 짧게 — 경계가 곧 비용이다

    커넥션 부족, 테이블 팽창, 락 경합이 한꺼번에 나서 하나씩 따로 조사했는데, 알고 보니 원인은 트랜잭션이 길다는 것 하나였어요. 경계를 어디에 두고 어떻게 줄이는지 정리했어요.

    5분#DB
  7. 아웃박스 패턴 — 커밋되기 전에 이벤트를 보내지 마라

    주문을 저장하고 바로 알림 이벤트를 보냈더니, 가끔 알림 서비스가 「그런 주문 없는데요」라고 해요. 취소된 주문 알림이 나가기도 하고요. 저장과 발행을 안전하게 묶는 방법을 정리했어요.

    5분#DB
  8. SKIP LOCKED 로 만드는 작업 큐

    DB 테이블로 만든 작업 큐에 워커를 다섯으로 늘렸는데, 처리량은 한 대일 때와 똑같아요. 모두 맨 앞 작업 하나에 줄을 서기 때문이에요. 잠긴 행은 건너뛰는 방식으로 푸는 법을 정리했어요.

    5분#DB
  9. REQUIRES_NEW 가 커넥션 풀을 말린다 — 요청 하나가 커넥션 둘을 쥘 때

    로그만은 남기려고 저장 메서드를 별도 트랜잭션으로 뺐어요. 그런데 트래픽이 오르자 CPU 도 DB 도 한가한데 앱이 멈춰요. 요청 하나가 커넥션 둘을 쥐면서 생기는 교착과 피하는 법을 다뤄요.

    5분#DB
  10. @Transactional 롤백이 안 될 때 — 자기 호출과 프록시

    트랜잭션 애너테이션을 붙였는데 예외가 나도 롤백이 안 돼요. 오타도 없고 임포트도 맞는데요. 트랜잭션이 아예 시작되지 않는 이유와, 같은 클래스 안에서 부를 때 생기는 일을 정리했어요.

    5분#DB
  11. 쓰기 스큐 — 각자는 옳은데 합치면 틀리다

    당직은 최소 한 명이 남아야 하는데, 두 사람이 동시에 해제를 눌렀더니 0명이 됐어요. 검사도 트랜잭션도 있었는데요. 각자는 옳은데 합치면 틀리는 문제와 이를 막는 방법을 다뤄요.

    5분#DB
  12. 갱신 손실(lost update) — 동시에 들어온 포인트 적립이 한 번만 반영될 때

    포인트 적립 요청이 두 번 다 성공했는데 잔액에는 한 번만 들어가 있어요. 에러가 없어서 정산 때가 돼서야 알게 되죠. 동시 요청이 한쪽 쓰기를 덮어쓰는 이유와 막는 방법을 정리했어요.

    5분#DB