Tema: databases
-
Manter visíveis os limites das transações
Documente quais alterações de estado são confirmadas juntas e o que pode acontecer entre transações de banco de dados e chamadas externas.
-
Busca de texto completo no PostgreSQL com tsvector
O PostgreSQL converte texto em um tsvector de lexemas normalizados usando uma configuração de idioma, compara-o com tsquery, classifica com ts_rank e indexa com GIN; trata stemming e stop words, mas não erros de digitação nem sinônimos por padrão.
-
Event sourcing e CQRS: o que oferecem e quanto custam
O event sourcing guarda cada mudança de estado como um evento imutável e obtém o estado atual por reprodução (replay); o CQRS separa o modelo de escrita dos modelos de leitura. Ambos trazem auditabilidade e flexibilidade, ao preço de mais complexidade e de consistência eventual.
-
Gerenciamento de extensões do PostgreSQL: instalar, versionar, atualizar e exportar
Uma extensão agrupa objetos SQL e, muitas vezes, uma biblioteca compartilhada sob um único nome, com um arquivo de controle e scripts versionados. CREATE EXTENSION a instala por banco de dados, ALTER EXTENSION UPDATE aplica os scripts de atualização do autor e o pg_dump emite apenas a linha CREATE EXTENSION. Mantenha alinhados os arquivos instalados, a versão no catálogo e a biblioteca carregada, sobretudo em atualizações de pacote e no pg_upgrade.
-
Dados de seed e fixtures para bancos de dados locais: pequenos, idempotentes e versionados junto com o esquema
Separe dados de referência (necessários em todo lugar), dados de exemplo (desenvolvimento e demos) e dados de teste (criados pelos próprios testes). Escreva o seed como código idempotente com upserts em chaves naturais, mantenha o conjunto de exemplo pequeno e nomeado, execute-o após as migrations no script de setup e no CI, e nunca popule máquinas de desenvolvimento com dados brutos de produção.
-
Como projetar uma tabela de séries temporais somente de inserção no PostgreSQL
Armazene medições em uma tabela particionada por intervalo de tempo, com timestamptz, chave composta de série e tempo, índices adequados ao padrão de consulta (B-tree por série, BRIN para varreduras de tempo na tabela inteira) e retenção feita por detach e drop de partições, em vez de DELETE; as escolhas decorrem de as linhas chegarem em ordem de tempo e saírem em fatias inteiras de tempo.
-
Armazenar dados derivados no PostgreSQL: colunas geradas ou views materializadas
Uma coluna gerada deriva um valor por linha apenas a partir dessa mesma linha, podendo ser virtual (calculada na leitura) ou armazenada (calculada na escrita), e aceita só expressões imutáveis; uma view materializada guarda o resultado de qualquer consulta e só está tão atualizada quanto o último REFRESH. Use colunas geradas armazenadas para normalização por linha que deva ser indexada, views materializadas para agregações caras que podem ficar defasadas e uma tabela de resumo mantida quando nenhuma das duas serve.
-
VACUUM, autovacuum e bloat de tabelas
O MVCC do PostgreSQL deixa versões mortas de linhas após updates e deletes; o VACUUM as recupera, mantém as estatísticas e protege contra o wraparound de IDs de transação. O autovacuum deve permanecer ativo e ser ajustado para tabelas com muito movimento.
-
Bancos de dados efêmeros em contêineres para testes de integração
Suba o motor de banco de dados real em um contêiner descartável a cada execução de testes, mantenha os dados em memória, aplique as migrações uma só vez em um banco-modelo e copie-o para cada arquivo de teste. Assim, os testes exercitam o planejador, as constraints e o comportamento de isolamento reais, em vez de um substituto em memória.
-
Níveis de isolamento de transação na prática
Read committed, repeatable read e serializable trocam concorrência por consistência; saber quais anomalias cada nível permite define quando adicionar locks explícitos ou tentativas repetidas (retries).
-
Alterações de banco de dados sem indisponibilidade: Expand e Contract
Como alterar um esquema em três etapas que podem ser entregues separadamente: expandir (criar a nova coluna ou tabela e manter a antiga), migrar (gravar nos dois lugares e preencher os dados antigos em lotes pequenos) e contrair (remover o antigo quando todo o código já usa o novo). Para evitar bloqueios longos, nenhuma tabela é reescrita em um único comando e o lock_timeout limita qualquer espera.
-
Dados de teste sem dados pessoais de produção
Forneça dados realistas a desenvolvimento, CI e staging gerando-os: classifique colunas, escreva geradores com seed que passem nos validadores da aplicação, crie volume com generate_series, copie da produção apenas distribuições, marque os registros gerados de forma reconhecível e elimine o atalho de fazer dump da produção.
-
NULL em SQL: lógica de três valores e suas armadilhas
NULL significa desconhecido, então comparações com NULL resultam em desconhecido, e não em verdadeiro ou falso: filtros WHERE descartam as linhas cuja condição é desconhecida, NOT IN com um NULL não retorna nada e agregações ignoram NULLs. Use IS NULL, IS DISTINCT FROM e COALESCE de forma deliberada.
-
Modo de manutenção somente leitura: continuar a atender leituras com as escritas em pausa
Em migrações de armazenamento, failovers e migrações longas, um serviço pode continuar a atender leituras e recusar escritas com uma mensagem clara, em vez de ficar fora do ar. O `default_transaction_read_only` do PostgreSQL torna as novas transações somente leitura no banco como rede de segurança, e o HTTP 503 com `Retry-After` indica aos clientes quando tentar de novo. O modo exige um único interruptor, uma mensagem para o usuário e um ensaio.
-
Common table expressions e consultas recursivas com WITH
WITH dá um nome a uma subconsulta para o resto da instrução; WITH RECURSIVE avalia um termo não recursivo e repete o termo recursivo até que não surjam novas linhas, percorrendo árvores e grafos de qualquer profundidade numa só consulta. CTEs de uso único e sem efeitos colaterais são incorporadas na consulta externa, a menos que se escreva MATERIALIZED; as cláusulas SEARCH e CYCLE tratam da ordenação e dos ciclos.
-
Colunas JSONB: para que servem e quando é melhor usar uma coluna comum
O jsonb guarda JSON já interpretado em formato binário, indexável com GIN e consultável com operadores de contenção e de caminho; serve para atributos esparsos, definidos externamente ou realmente variáveis. Dados com estrutura fixa, que exigem restrições, chaves estrangeiras ou atualizações por campo, e documentos grandes alterados com frequência pertencem a colunas comuns.
-
Prevenção de SQL injection com consultas parametrizadas
Nunca monte SQL concatenando strings não confiáveis: passe os valores como parâmetros, para que o driver os envie separados da instrução, e use listas de permissão para qualquer identificador que precise ser dinâmico.
-
Pool de conexões com o banco de dados e seus limites
Cada conexão PostgreSQL é um processo com custo de memória; a aplicação deve manter um pool pequeno, dimensionado pela concorrência real, definir timeouts de aquisição e nunca deixar os handlers de requisição abrirem conexões avulsas.
-
Medição de reservas com SKIP LOCKED no PostgreSQL usando quatro consumidores de fila concorrentes
Quatro transações concorrentes reservaram, cada uma, 25 jobs sintéticos no PostgreSQL 16.15. Os 100 IDs retornados eram únicos e nenhum job ficou sem reserva; isso verifica uma única fase de reserva limitada, não o processamento exactly-once nem a substituição de um broker.
-
Sagas: fluxos de trabalho em várias etapas entre serviços, com compensação em vez de rollback
Uma saga é uma sequência de transações locais em serviços diferentes, em que cada uma dispara a seguinte; se uma etapa falha, as anteriores são desfeitas por transações compensatórias escritas pelo desenvolvedor. As sagas restauram a consistência sem transações distribuídas, mas abrem mão do isolamento: os estados intermediários ficam visíveis e as compensações precisam ser projetadas, não presumidas.
Legível por máquina: JSON