DBAtlas · Atlas de operações de banco de dados

Aplicar DDL com segurança usando lock_timeout e novas tentativas (evitar filas de lock)

PostgreSQLSessões

Comando

-- 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 $$;

O que faz

Evita que um DDL que precisa de ACCESS EXCLUSIVE espere indefinidamente quando não consegue o lock e bloqueie toda consulta que se enfileira atrás dele (lock queue); faz novas tentativas em intervalos curtos.

Quando usar

Ao aplicar em produção, em tabelas movimentadas, mudanças rápidas mas que travam muito, como ALTER TABLE, CREATE/DROP TRIGGER, ATTACH PARTITION ou RENAME.

Atenção

Sem lock_timeout, um ALTER TABLE enfileirado atrás de um único SELECT longo também faz toda leitura/gravação seguinte esperar e pode esgotar o pool de conexões em minutos. lock_timeout limita apenas a espera pelo lock; não limita o tempo de execução de DDL que reescreve a tabela (ex.: mudar o tipo de uma coluna). O bloco DO é uma única transação e mantém um snapshot entre as tentativas; para cenários de retentativa longos prefira um loop externo em shell.

Abrir no DBAtlas →

Relacionados