452. 타임스탬프 순서 (Timestamp Ordering)
⚠️ 이 문서는 트랜잭션들이 서로 데이터를 차지하려고 싸울 때 락(Lock)을 걸면 데드락(Deadlock)이 발생하는 문제를 원천 차단하기 위해, 아예 자물쇠를 없애버리고 "누가 먼저 도착했는가?"라는 시간표(Timestamp) 하나만으로 질서를 유지하는 병행 제어 기법을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 락(Lock)을 쓰지 않는 비관적(Pessimistic) 또는 낙관적(Optimistic) 병행 제어 기법이다. 트랜잭션이 시작될 때 시스템 시계(Timestamp)를 부여받고, 이 나이순으로 데이터 접근 권한을 결정한다.
- 가치: 자물쇠를 걸고 대기하는 시간(Wait)이 아예 없으므로 교착 상태(Deadlock)가 절대 발생하지 않는다.
- 규칙: 무조건 "나이가 많은(먼저 온) 트랜잭션이 먼저 처리되어야 한다"는 대원칙을 지킨다. 젊은이(나중에 온 놈)가 이미 데이터를 건드려놨다면, 뒤늦게 온 늙은이(먼저 시작했지만 느린 놈)는 무자비하게 쫓겨난다(Rollback).
Ⅰ. 개요: 줄서기 표와 자물쇠 (Context & Necessity)
은행 시스템에 두 명의 사용자가 접속했다. 2단계 잠금 규약(2PL - 450번 문서)은 "먼저 데이터에 도착한 놈이 자물쇠를 건다!"라는 선착순 게임이다. 그래서 데드락이 발생한다.
타임스탬프 순서 기법은 자물쇠를 치워버리고, 은행 창구에 번호표 기계를 둔다.
- T1 (먼저 옴): 번호표 1번 (나이가 많음)
- T2 (나중에 옴): 번호표 2번 (젊음)
규칙은 단순하다. "무조건 1번 손님이 먼저 만진 물건이어야 한다." 만약 1번 손님이 화장실에 다녀오느라 늦었는데, 2번 손님이 이미 물건을 사고 결제까지 끝내버렸다면? 은행은 1번 손님에게 이렇게 말한다. "손님, 늦으셨네요. 이미 2번 손님이 건드려서 과거로 되돌릴 수 없습니다. 손님 작업은 전부 취소(Rollback)할 테니 번호표 다시 뽑고 처음부터 다시 하세요!"
📢 섹션 요약 비유: 타임스탬프 순서는 **'선배 우선 원칙이 있는 식당'**과 같습니다. 후배(T2)가 먼저 식당에 와서 밥을 먹고 나가버렸는데, 뒤늦게 온 선배(T1)가 "내가 선배인데 감히 나보다 먼저 밥을 먹어?"라며 화를 냅니다. 식당 주인(DB)은 질서를 지키기 위해 뒤늦게 온 선배를 식당에서 내쫓아버립니다. (Rollback)
Ⅱ. 타임스탬프의 2가지 기본 규칙 ★
데이터베이스의 모든 데이터(행)에는 두 가지 도장이 찍혀있다.
Read_TS(X): X 데이터를 마지막으로 읽고 간 사람의 번호표Write_TS(X): X 데이터를 마지막으로 고치고 간 사람의 번호표
1. 읽기 (READ) 규칙
T1(번호표 1번)이 데이터를 읽으려 한다.
- 거절당하는 경우:
Write_TS가 2번이다. (즉, 나보다 어린 놈이 이미 미래의 값으로 고쳐버림). T1은 쫓겨난다(Rollback). - 성공하는 경우:
Write_TS가 1번보다 작다. (정상). T1이 데이터를 읽고Read_TS에 내 번호(1)를 남긴다.
2. 쓰기 (WRITE) 규칙
T1(번호표 1번)이 데이터를 고치려 한다.
- 거절당하는 경우 1:
Read_TS가 2번이다. (나보다 어린 놈이 옛날 값을 이미 읽고 자기 로직을 돌려버렸는데, 내가 지금 옛날 값을 고쳐버리면 그 어린 놈의 계산이 다 엉망이 되므로 안 됨). T1은 쫓겨난다. - 거절당하는 경우 2:
Write_TS가 2번이다. (나보다 어린 놈이 이미 미래의 값을 썼음). T1은 쫓겨난다. - 성공하는 경우: 위 두 가지가 아닐 때만 쓸 수 있다.
Ⅲ. 토마스 쓰기 규칙 (Thomas Write Rule)
위의 쓰기 규칙 중 "거절당하는 경우 2"를 살짝 융통성 있게 봐주는 천재적인 예외 규칙이다.
- 상황: T1(1번)이 데이터를 쓰려고 갔는데, 이미 T2(2번)가 데이터를 써버렸다. (
Write_TS= 2) - 기존 원칙: "아이고, 1번 손님. 2번이 이미 썼네요. 1번 손님은 롤백입니다!"
- 토마스 규칙: "가만 생각해 보니... 어차피 1번이 쓰고 난 뒤에 2번이 덮어쓸 운명이었잖아? 그럼 그냥 1번이 쓰려는 값은 휴지통에 몰래 버리고(무시하고), 1번 손님한테는 '성공했습니다~'라고 뻥치고 넘어가자!"
- 효과: 불필요한 Rollback을 줄여서 시스템 성능을 엄청나게 높여준다.
┌──────────────────────────────────────────────────────────────┐
│ 타임스탬프 순서 기법의 Rollback 시나리오 시각화 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [ ⏱️ 타임스탬프 부여 ] T1(먼저 옴: 10시) / T2(나중에 옴: 11시) │
│ │
│ [ 📦 데이터 X 상태: Read_TS=9시, Write_TS=9시 ] │
│ │
│ 1. T2가 X를 읽음 ──▶ 승인! (Read_TS = 11시로 변경) │
│ │
│ 2. T1이 X를 쓰려함 ──▶ 거절! 💥 (Rollback) │
│ (이유: 내가 10시로 시간을 돌려서 값을 고치면, 아까 11시에 이 값을 읽어간 │
│ T2의 계산이 완전히 엉터리가 되어버리기 때문!) │
│ │
│ ★ 특징: 락(Lock)을 기다리는 '대기 시간'은 0초. 무조건 승인이거나 사살이다. │
└──────────────────────────────────────────────────────────────┘
Ⅳ. 결론
"데드락은 피했지만, 연쇄 폭발을 조심하라." 타임스탬프 순서 기법은 분산 데이터베이스 환경에서 매우 중요한 개념이다. 전 세계에 흩어진 서버들이 자물쇠를 걸고 서로 통신하는 것은 네트워크 비용이 너무 비싸기 때문이다 (구글 스패너의 TrueTime이 이 철학의 끝판왕이다 - 388번 문서). 하지만 타임스탬프 기법은 조금만 타이밍이 엇갈려도 트랜잭션을 무자비하게 롤백(Rollback)시켜 버리므로, 트래픽이 폭주할 때는 살아남는 트랜잭션이 거의 없는 끔찍한 기아 상태(Starvation)를 유발할 수 있다는 치명적인 맹점을 아키텍트는 반드시 기억해야 한다.
📌 관련 개념 맵
- 관련 특성: 고립성 (Isolation - 443번 문서)
- 대척점 기술: 2PL (2단계 잠금 규약 - 450번 문서)
- 해결하려는 문제: Deadlock (데드락 방지)
- 진화된 기술: MVCC (다중 버전 동시성 제어 - 453번 문서)
👶 어린이를 위한 3줄 비유 설명
- 타임스탬프는 은행 창구에서 뽑는 '번호표'와 같아요.
- 1번 손님이 화장실에 다녀온 사이에 2번 손님이 돈을 먼저 뽑아가 버렸어요.
- 화장실에서 돌아온 1번 손님이 돈을 뽑으려 하자, 은행원은 "번호표 순서가 꼬였으니 아저씨는 쫓겨납니다! 다시 뒤로 가서 새 번호표 뽑아오세요!"라고 쫓아내는 무서운 규칙이랍니다!