DBAtlas · 데이터베이스 운영 아틀라스

lock_timeout과 재시도로 DDL 안전하게 적용(lock queue 방지)

PostgreSQL세션

명령어

-- Single attempt: give up if the lock is not acquired within 3 s instead of queueing and blocking traffic
SET lock_timeout = '3s';
ALTER TABLE customer ADD COLUMN IF NOT EXISTS segment text;
RESET lock_timeout;

-- Automatic retry: up to 5 attempts, 3 s apart
DO $$
DECLARE
  attempt int := 0;
BEGIN
  LOOP
    attempt := attempt + 1;
    BEGIN
      SET LOCAL lock_timeout = '2s';
      ALTER TABLE customer ADD COLUMN IF NOT EXISTS segment text;
      RAISE NOTICE 'OK, attempt %', attempt;
      EXIT;
    EXCEPTION WHEN lock_not_available THEN
      RAISE NOTICE 'lock not acquired, attempt %', attempt;
      IF attempt >= 5 THEN RAISE; END IF;
      PERFORM pg_sleep(3);
    END;
  END LOOP;
END $$;

하는 일

ACCESS EXCLUSIVE가 필요한 DDL이 락을 얻지 못할 때 무한정 대기하거나 뒤에 대기하는 모든 쿼리를 블로킹하는 것(lock queue)을 막고, 짧은 간격으로 재시도한다.

사용 시점

운영 환경의 바쁜 테이블에 ALTER TABLE, CREATE/DROP TRIGGER, ATTACH PARTITION, RENAME처럼 빠르지만 강한 락을 잡는 변경을 적용할 때.

주의

lock_timeout이 없으면 장시간 SELECT 하나 뒤에 대기하는 ALTER TABLE이 이후의 모든 읽기/쓰기도 대기하게 만들어 몇 분 안에 커넥션 풀을 고갈시킬 수 있다. lock_timeout은 락 대기만 제한하며 테이블을 다시 쓰는 DDL(예: 컬럼 타입 변경)의 실행 시간은 제한하지 않는다. DO 블록은 단일 트랜잭션이며 시도 간 스냅샷을 유지하므로 긴 재시도 시나리오에서는 외부 셸 루프를 권장한다.

DBAtlas에서 열기 →

관련 항목