CodeGym /Cursos /SQL SELF /Restrições e possíveis problemas ao trabalhar com transaç...

Restrições e possíveis problemas ao trabalhar com transações: LOCK, DEADLOCK

SQL SELF
Nível 54 , Lição 1
Disponível

Transações no PostgreSQL garantem isolamento — uma das paradas chave do ACID. Pra isso, o sistema usa locks. Lock é tipo um mecanismo que garante que várias transações não vão "brigar" pelo mesmo registro ou tabela. Imagina uma fila no mercado: só um de cada vez passa no caixa. Os locks funcionam mais ou menos assim, só que eles controlam o acesso aos dados nas tabelas.

Principais tipos de locks

No PostgreSQL tem vários tipos de locks, alguns deles você talvez já tenha visto no EXPLAIN ANALYZE:

  1. ROW EXCLUSIVE (lock exclusivo de linha) — rola quando você altera dados numa linha. É o tipo de lock mais comum, tipo quando faz INSERT, UPDATE ou DELETE.
  2. SHARE (lock compartilhado) — usado pra operações que garantem que os dados não vão mudar enquanto a query roda, tipo quando faz SELECT ... FOR SHARE.
  3. EXCLUSIVE (lock exclusivo) — bloqueia qualquer outra operação nos dados, menos leitura.

Dá pra dizer que locks são tipo cachorros de guarda protegendo nossos dados.

Problema dos locks: o que pode dar ruim?

Agora que já sacou o que são locks, bora ver os problemas que eles podem causar. O maior deles é o tal do deadlock. Deadlock é quando duas (ou mais) transações ficam esperando uma pela outra, e aí tudo trava num loop infinito. Normalmente rola assim:

  1. Transação 1 bloqueia a linha A e quer acessar a linha B.
  2. Transação 2 bloqueia a linha B e quer acessar a linha A.
  3. Como as duas linhas estão bloqueadas, nenhuma transação consegue terminar.

Exemplo de deadlock

Pra sentir a dor de quem já tomou um deadlock, imagina esse cenário:

-- Transação 1
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- Ao mesmo tempo
-- Transação 2
BEGIN;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;

-- Transação 1 tenta bloquear id = 2
UPDATE accounts SET balance = balance - 100 WHERE id = 2;

-- Transação 2 tenta bloquear id = 1
UPDATE accounts SET balance = balance + 200 WHERE id = 1;

Pronto! Cada transação ficou presa pela outra. O PostgreSQL uma hora percebe isso e manda um erro de deadlock.

Como evitar deadlocks?

  1. Ordem sequencial de acesso aos dados. Tenta sempre acessar os dados na mesma ordem. Se a transação 1 primeiro bloqueia a linha A e depois a B, a transação 2 tem que seguir a mesma lógica: primeiro linha A, depois linha B.
-- Ordem certa de acesso
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;
COMMIT;
  1. Minimiza o tempo das transações. Transações demoradas aumentam a chance de deadlock. Fecha a transação o mais rápido possível: BEGIN, faz tudo que precisa e já manda um COMMIT.

  2. Usa níveis de isolamento de transação. Se não precisa de isolamento super rígido, pensa em usar o nível READ COMMITTED. Ele ajuda a evitar alguns locks.

Timeouts e diagnóstico de locks

Tem umas ferramentas pra diagnosticar e evitar locks no PostgreSQL. Por exemplo, dá pra definir um tempo máximo de espera do lock:

SET lock_timeout = '5s';  -- Define o timeout do lock pra 5 segundos

Se o lock durar mais que esse tempo, a transação é cancelada, evitando que tudo trave geral.

Monitorando locks no PostgreSQL

Um comando útil pra monitorar locks é o pg_locks. Ele mostra todos os locks ativos no sistema:

SELECT * FROM pg_locks;

Dá pra ver quais transações estão segurando locks e quais estão esperando. Isso é top pra debugar deadlocks.

Detalhes do LOCK e lock manual de objetos

Se precisar controlar locks na mão, usa o comando LOCK:

LOCK TABLE orders IN ACCESS EXCLUSIVE MODE;

Atenção: ACCESS EXCLUSIVE é o lock mais forte, bloqueia qualquer operação na tabela, até SELECT. Só usa isso em casos especiais (tipo mudar a estrutura da tabela).

Pra bloquear linhas específicas durante alteração, usa SELECT ... FOR UPDATE:

SELECT * FROM accounts WHERE id = 1 FOR UPDATE;

Isso garante que outras transações não vão conseguir mexer nessas linhas até sua transação acabar.

O que lembrar sobre locks?

Lock não é vilão, é ferramenta. Eles ajudam a manter a integridade dos dados, mas tem que usar com cuidado. Aqui vão umas dicas chave:

  1. Não começa uma transação se não souber exatamente pra quê.
  2. Fecha a transação o mais rápido possível.
  3. Evita acessar dados em ordem diferente.
  4. Usa o nível de isolamento certo pra sua necessidade.

Agora você tá pronto pra lidar com locks e deadlocks! Que o pg_locks e a sabedoria do ACID estejam com você.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION