본문 바로가기
C.W.K.
Stream
Lesson 05 of 10 · published

행 잠금과 테이블 잠금

~12 min · transactions, locks

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

PostgreSQL이 자동으로 잡는 잠금

행을 UPDATE하면 트랜잭션이 끝날 때까지 FOR UPDATE와 비슷한 행 잠금을 잡아. 다른 트랜잭션이 같은 행을 바꾸려 하면 기다리지만, 보통 SELECT는 MVCC로 읽을 뿐 잠그지 않아.

바꿀 의도로 읽는다면 명시해

SELECT ... FOR UPDATE는 읽은 행을 잠가 확인 뒤 갱신하는 사이에 다른 쓰기가 끼어들지 못하게 해. 다시 말해 SELECT ... FOR UPDATE를 써야 할 자리는 단순 읽기가 아니라 이어질 변경의 경계야.

테이블 수준 잠금과 온라인 DDL

ALTER TABLE이나 DROP TABLE 같은 DDL은 넓은 잠금을 요구할 수 있어. 운영 환경에서 30초 동안 읽기와 쓰기를 막는 변경은 장애가 돼. 가능한 작업이라면 CONCURRENTLY를 지원하는 방식을 쓰고, 단순한 FOR UPDATE만으로 해결할 수 없는 잠금 범위를 배포 전에 확인해.

Code

SELECT FOR UPDATE로 행을 명시적으로 잠그기·sql
BEGIN;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- 이제 row 1 UPDATE 시도하는 다른 트랜잭션 기다림.
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
FOR UPDATE SKIP LOCKED로 작업 큐 만들기·sql
-- 다른 worker 가 lock 한 거 스킵, 다음 pending job 가져오기
BEGIN;
SELECT id, payload FROM jobs
WHERE  status = 'pending'
ORDER  BY created_at
LIMIT  1
FOR UPDATE SKIP LOCKED;
-- ... 처리 ...
UPDATE jobs SET status = 'done' WHERE id = ?;
COMMIT;
쓰기를 막지 않고 색인 만들기·sql
-- 테이블 잠깐 lock, 그 다음 exclusive lock 없이 read
CREATE INDEX CONCURRENTLY orders_customer_idx ON orders (customer_id);

External links

Exercise

status 열이 있는 jobs 테이블과 SELECT ... FOR UPDATE SKIP LOCKED LIMIT 1로 작업을 가져오는 작은 워커를 만들어. 처리 뒤 status를 갱신하고 COMMIT해. 워커 2개를 동시에 실행해 같은 작업을 가져가지 않는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.