주제 허브
DB를 쓰는 사람인가, DB가 어떻게 도는지 아는 사람인가
데이터베이스 내부와 트랜잭션
락 보유 시간을 재고, 시퀀스 병목을 뜯고, InnoDB 리두 로그와 DDL 알고리즘을 읽는다. 트랜잭션 경계와 격리 수준이 실제로 어디서 깨지는지를 실측과 원문 분석으로 좁힌다.
먼저 읽을 글
직접 만들고 재 본 것 ParityPay로 검증하는 결제 정합성 2 - 잠금을 필요 이상으로 오래 쥐고 있었다: 추론을 측정으로 바꾼 기록 직접 만들고 재 본 것 대량 배치 안정성을 높이기 위한 구조 개선: Part 1 - 시스템을 압박하기 시작한 배치 직접 만들고 재 본 것 키 생성 병목을 추적해 구조를 바꾼 기록: Part 1 - INSERT가 느린 줄 알았다 직접 만들고 재 본 것 정산이 진행되는 동안 기준 데이터 수정을 막는 방법: 상태 플래그와 AOP로 만든 경량 락 기술 블로그 리뷰 카카오 「MySQL InnoDB Log에 대한 이해 - (1)」 리뷰 — 트랜잭션 하나가 어떻게 MTR 여러 개로 쪼개져 Redo Log Buffer에 들어가는가 컨퍼런스 발표 리뷰 SLASH 21 리뷰 - MySQL HA & DR Topology: MMM, 대칭 DR 구성, 바이너리 로그 필터, super_read_only 안전장치
직접 만들고 재 본 것
55편- ParityPay로 검증하는 결제 정합성 2 - 잠금을 필요 이상으로 오래 쥐고 있었다: 추론을 측정으로 바꾼 기록
- 대량 배치 안정성을 높이기 위한 구조 개선: Part 1 - 시스템을 압박하기 시작한 배치
- 키 생성 병목을 추적해 구조를 바꾼 기록: Part 1 - INSERT가 느린 줄 알았다
- 정산이 진행되는 동안 기준 데이터 수정을 막는 방법: 상태 플래그와 AOP로 만든 경량 락
- CDC의 원리와 한계 - 로그 기반 변경 포착, 초기 스냅샷, 스키마 변경
- 커넥션과 세션 - 커넥션 풀이 실제로 아끼는 것
- spring-internals-lab로 다시 읽는 Spring 7 - @Transactional의 실체
- 파티셔닝과 샤딩 - 기준 선택, 로컬과 글로벌 인덱스, 재분배 비용
- 분산 트랜잭션 - 2PC와 Saga, 보상 트랜잭션이 실패하는 방식
- WAL과 체크포인트 - 커밋은 언제 디스크에 닿는가
- spring-lite로 이해하는 Spring 구현 3 - ProxyFactory, @Transactional, JdbcTemplate 연결
- TimescaleDB를 시계열 DB로 고른 이유 — Hypertable과 연속 집계
- 락의 종류와 대기 - row, gap, next-key, intention과 데드락 탐지
- ParityPay로 검증하는 결제 정합성 10 - 락 lease가 트랜잭션보다 먼저 끝나면 정말 정합성이 깨지는가: SETNX 락, Watchdog, fencing token, 그리고 락 없는 구조의 실측
- 실행 계획을 읽는 법 - 연산자, 비용 모델, 카디널리티 추정이 틀어지는 지점
- ParityPay로 검증하는 결제 정합성 7 - 애플리케이션 코드를 믿지 않는 원장: 이중부기를 계정 체계, DB 제약, 속성 테스트로 강제하기
- MULTI, Pub/Sub, Lua로 보는 Redis 확장 기능과 구현 과정
- ParityPay로 검증하는 결제 정합성 6 - 대사: "기관에 물어보지 못했다"와 "기관에 기록이 없다"는 다른 상태다
- 키 생성 병목을 추적해 구조를 바꾼 기록: Part 2 - SELECT 안에서 UPDATE가 일어나고 있었다
- ParityPay로 검증하는 결제 정합성 5 - DB 커밋과 Kafka 발행 사이: Transactional Outbox와 at-least-once 소비자
- 프록시의 한계 - self-invocation, final, JDK와 CGLIB의 선택
- 동시성 도구의 비용 - synchronized, ReentrantLock, CAS가 경쟁에서 갈리는 지점
- Postgres 커넥션 하나의 비용 - 풀을 키우면 대기가 사라지는 게 아니라 볼 수 없는 곳으로 옮겨간다
- 합의 알고리즘 - Raft를 상태 기계로 읽기
- B+Tree 인덱스의 내부 - 노드 분할, 클러스터드와 논클러스터드, 커버링이 아끼는 것
- 인덱스가 선택되지 않는 순간 - 컬럼에 캐스팅 하나가 3,000배, 그리고 추정이 31.7배 틀려도 계획이 안 바뀌는 경우
- 트랜잭션 전파 7종 - 각 옵션이 커넥션과 롤백에 남기는 결과
- 키 생성 병목을 추적해 구조를 바꾼 기록: Part 3 - 채번을 INSERT 시점으로 옮기고 범위 단위로 받기
- 격리 수준의 이상 현상을 직접 만들기 - 같은 REPEATABLE READ에서 PostgreSQL은 중단시키고 MySQL은 조용히 덮어썼다
- 일관성 모델 - 선형화, 순차, 최종 일관성, 그리고 CAP를 설정값의 언어로
- 격리 수준과 이상 현상 - 표준이 정의한 것과 MySQL·PostgreSQL이 실제로 하는 것
- 대량 배치 안정성을 높이기 위한 구조 개선: Part 2 - 전체 삭제 후 전체 등록 구조의 위험성
- 대량 배치 안정성을 높이기 위한 구조 개선: Part 3 - 청크 분할과 병렬 처리로 재설계하기
- 대량 배치 안정성을 높이기 위한 구조 개선: Part 4 - 분산 락이 있어도 레이스가 발생한 이유
- 대량 배치 안정성을 높이기 위한 구조 개선: Part 5 - 배타적 락과 조건부 해제로 순서를 보장하기
- 모든 도메인이 100% 정합성을 요구하지는 않는다: Post-Commit 이벤트와 재시도 3회 정책을 정한 기준
- Redis Sentinel Replication
- Redo Log와 Undo Log를 어떻게 구분해야 하는가
- 데이터베이스 리플리케이션 기본 정리
- ACID를 실무적으로 이해하기
- 데이터베이스 트랜잭션을 어떻게 봐야 하는가
- Gap Lock
- MVCC를 어떻게 이해해야 하는가
- JSP 기반 시스템의 구조적 문제를 해결한 아키텍처 전환기: 시퀀스 테이블 기반 코드 생성의 병목을 해결한 이야기
- [3주차] 속도를 지배하는 DB 인덱스
- @TransactionalEventListener 빠른 체크 노트
- 데이터베이스 페이징 성능을 어떻게 봐야 하는가
- 왜 이벤트가 안 먹히지? @TransactionalEventListener가 무시되는 이유와 해결법
- 데이터베이스 인덱스를 어떻게 이해해야 하는가
- 점 이력과 선분 이력 모델링
- Statement와 PreparedStatement는 무엇이 다른가
- Spring과 JPA에서 Race Condition을 다루는 방법
- Connection Pool
- Transaction
- 배열을 데이터베이스에 저장할 때 무엇을 먼저 판단해야 하는가
기술 블로그 리뷰
14편- 카카오 「MySQL InnoDB Log에 대한 이해 - (1)」 리뷰 — 트랜잭션 하나가 어떻게 MTR 여러 개로 쪼개져 Redo Log Buffer에 들어가는가
- 카카오 「MySQL 인증 플러그인 caching_sha2_password에 대한 이해」 리뷰 — 비밀번호 해시가 바뀌는 것보다 '평문이 서버까지 가야 한다'는 점이 전환의 진짜 비용
- 쿠팡 「대용량 트래픽 처리를 위한 쿠팡의 백엔드 전략」 리뷰 — 캐시 두 겹과 '분 단위 99.99% 동일'이라는 문장, 그리고 그 0.01%를 누가 어떻게 세는가
- 카카오 「잃어버린 리포트를 찾아서: 카카오 메시징 시스템의 경쟁 조건 문제와 안티 패턴 제거 과정」 리뷰 — 벤더가 8ms 만에 리포트를 보냈고, 우리는 101ms짜리 트랜잭션 안에 있었다
- 카카오 「MySQL Json 데이터 타입의 저장 구조와 성능 비교」 리뷰 — 통째로 넣고 통째로 꺼내면 TEXT, 키로 파고들면 JSON
- 네이버 D2 「스마트스토어센터 Oracle에서 MySQL로의 무중단 전환기」 리뷰 — 두 DB에 동시에 쓰되 한쪽 실패는 무시하고, 읽기 트래픽을 복제해 성능을 재고, 6개월간 불일치를 0으로 만든 과정
- 뱅크샐러드 「게임을 만들 때 데이터 정합성을 유지하는 법 (feat. 낙관적 락)」 리뷰 — 같은 WHERE version 조건인데, 충돌한 요청을 어떻게 하는가에서 갈리는 두 설계
- 카카오 「PostgreSQL to ES: Kafka Connect CDC 파이프라인」 1·2편 리뷰 — 변경이 없어서 디스크가 차고, LSN이 사라져서 스냅샷을 다시 짜야 했던 CDC의 실제 운영 비용
- 네이버 D2 「CDC 복제 이후 오라클이 느려졌다? child cursor 폭증이 만든 예상치 못한 문제」 리뷰 — 같은 SQL인데 바인딩 타입이 다르면 Oracle은 다른 쿼리로 본다
- 카카오 「MySQL Ver. 8.0 New Feature: Instant DDL Algorithm에 대한 이해」 리뷰 — 컬럼을 0.01초에 추가하는 대가는 '읽을 때마다 버전을 대조하는 것'이다
- 카카오 「MySQL Orchestrator 기반의 새로운 HA 표준 개발기」 리뷰 — 10년 멈춘 Perl 도구를 떠나 Raft 클러스터로, 그리고 slave_net_timeout 한 줄
- 카카오 「MySQL ALTER DDL 수행 방식에 대한 이해」 리뷰 — Copy·In-Place·Instant는 '무엇을 복사하느냐'보다 '언제 Exclusive 메타 락을 잡느냐'로 구분된다
- 네이버 D2 「6개월 만에 연간 수십조를 처리하는 DB CDC 복제 도구 무중단/무장애 교체하기」 리뷰 — 복제·검증·복구를 셋으로 나누고, 옛 도구와 새 도구를 서로 모르게 같이 돌린 전환
- 카카오 「MySQL DATETIME, TIMESTAMP 데이터 타입에 대한 분석」 리뷰 — 바이트 단위 저장 구조부터 아직 안 고쳐진 Y2K38까지