테마
이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.
18화 진단에서 신규 이커머스 플랫폼의 FK 39개가 전부 꺼져 있고 고아 데이터도 있다는 것이 드러났다. 그래서 고아를 정리하고, 7월 9일에 첫 단계로 orders → customers FK 하나를 켰다.
다음 날 11:00에 개인정보 파기 배치(가입 5년이 지나도록 주문이 없는 고객을 지운다)가 돌기 시작했는데, 평소 2초면 끝나던 배치가 4분째 끝나지 않는다. 그 사이 고객 등급 갱신 배치도 멈췄다. 주문 화면은 정상이다.
customers(부모): 5,230행 · 51블록 · PK customer_idorders(자식): 34,908행 · 193블록 · FK_ORDERS_CUSTOMER_ID (customer_id → customers) ENABLED VALIDATED · customer_id에 인덱스 없음(PK order_id만 있다)-- 7월 9일 반영 — 고아를 정리하고 FK 하나를 켰다
ALTER TABLE orders ENABLE VALIDATE CONSTRAINT FK_ORDERS_CUSTOMER_ID;
-- 매일 11:00 개인정보 파기 배치 — 가입 5년 · 주문 없는 고객
BEGIN
FOR r IN (SELECT c.customer_id
FROM customers c
WHERE c.join_date < ADD_MONTHS(SYSDATE, -60)
AND NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id)) LOOP
DELETE FROM customers WHERE customer_id = r.customer_id;
END LOOP;
COMMIT;
END;
[시간표 — 7월 10일 · FK 를 켠 다음 날]
시각 주문 화면 A (SID 142) 파기 배치 B (SID 77) 등급 갱신 C (SID 95)
11:00:00 INSERT INTO orders (고객 3,118)
결제창 — COMMIT 전
11:00:01 고객 52 명 DELETE (한 명 2 ~ 3 ms)
11:00:01 53 번째 고객 4,410 DELETE → 기다림 ①
11:00:40 UPDATE customers SET grade … (전 고객)
→ B 가 지운 고객 행에서 기다림 ②
11:02:30 COMMIT (결제 완료) → 다음 고객 · 또 다른 주문 화면 D 를 만나 또 기다림
11:04:10 140 명 끝 · COMMIT → 이제야 진행
[V$SESSION — 11:01:30]
SID EVENT SECS BLOCKING_SESSION 하고 있는 문장
142 SQL*Net message from client 90 (결제창 — 트랜잭션을 연 채)
77 enq: TX - row lock contention 89 142 DELETE FROM CUSTOMERS WHERE CUSTOMER_ID = :B1
95 enq: TX - row lock contention 50 77 UPDATE CUSTOMERS SET GRADE = …
[V$LOCK — 11:01:30 (TM 은 객체 이름으로)]
SID TYPE 대상 LMODE REQUEST BLOCK
142 TM ORDERS 3 0 0
142 TM CUSTOMERS 3 0 0 ← 자식에 넣은 세션은 부모에도 TM 3 을 쥔다
142 TX A 의 트랜잭션 6 0 1
77 TM CUSTOMERS 3 0 0
77 TX A 의 트랜잭션 0 4 0 ← 행 락(6)이 아니라 4 — 'A 가 끝나야 결과를 안다'
77 TX B 의 트랜잭션 6 0 1
95 TM CUSTOMERS 3 0 0
95 TX B 의 트랜잭션 0 6 0
(B 는 ORDERS 에 TM 을 쥐지도 요청하지도 않았다)
[고객 한 명 DELETE — 혼자 돌렸을 때 session logical reads]
FK 꺼짐 약 6 · FK 켬 (인덱스 없음) 약 200 — orders 193 블록을 통째로 훑는다
[같은 장면을 문서(Concepts 「Locks and Unindexed Foreign Keys」)와 이전 버전 사례는 이렇게 적는다 — 이 교재의 컨테이너에서는 재현되지 않았다]
B 가 자식 ORDERS 에 테이블 락 S(4) 를 요청 → A 의 TM 3 과 충돌 → B 는 enq: TM - contention
그 뒤에 오는 주문 INSERT (TM 3 요청) 는 B 의 요청 뒤에 줄을 선다 → 주문 화면 전체가 멈춘다
orders를 통째로 훑는지 설명하시오.