Tenho uma pergunta relacionada a um incidente que aconteceu em um de nossos bancos de dados Postgres.
Temos um serviço backend que monitora a atividade do usuário em algum tipo de evento online. O serviço utiliza o Postgres 12 como banco de dados, e para esse tipo de evento existe uma tabela (chamarei user_event
no restante da pergunta) onde os dados são mantidos. A tabela tinha cerca de 3.500 transações por segundo, principalmente atualizações (das quais quase todas eram atualizações HOT - isso pode ser uma parte importante).
Aqui está um gráfico separado para tuplas inseridas e excluídas (as excluídas são 0), pois não é visível na foto acima:
O número de tuplas ativas aumentou assim:
O uso da tabela começou em aproximadamente 11 e estava indo bem durante o dia, mas por volta das 18h o tamanho da tabela passou de aproximadamente 3 GB para> 80 GB em 2 horas. Isso fez com que o disco quase atingisse sua capacidade total, então tivemos que desabilitar o evento em andamento e fazer um vácuo completo, o que reduziu o tamanho da tabela de >80GB para ~3GB.
Aqui está o tamanho da tabela com estimativas de inchaço:
* calculamos o inchaço exibido no segundo gráfico com esta consulta
Os índices das tabelas não cresceram tanto:
Naquele momento (por volta das 20h30 - 21h), suspeitamos que o problema era o autovacuum e que precisava ser mais agressivo, então configuramos o tempo de soneca de 30s (o padrão é 1 min) e definimos para 0,005 e para 0 (os últimos autovacuum_vacuum_scale_factor
2 autovacuum_vacuum_cost_delay
parâmetros definimos apenas para a tabela crítica). Antes dessas mudanças, o autovacuum era executado uma vez a cada 60s antes das 18h e depois das 18h uma vez a cada 2min (devido ao crescimento da tabela).
Talvez uma informação importante seja que durante todo o evento, a grande maioria dos checkpoints foram solicitados (não cronometrados) com frequência de uma vez a cada 3-4 minutos:
Depois disso, o problema não se repetiu, mas ainda não conseguimos explicar por que e como aconteceu esse grande aumento no tamanho da tabela. Após uma inspeção detalhada, o autovacuum (e a autoanalyse) funcionou o tempo todo na mesa (confirmamos isso em métricas e logs).
Para lhe dar mais contexto, notamos uma mudança na dinâmica dos buffers quando a tabela começou a aumentar rapidamente (por volta das 18h):
Alguém tem uma ideia do que/onde procurar para explicar isso? Se precisar de mais informações, posso fornecê-las.
Dados adicionais: o esquema da tabela user_event é este:
# \d user_event;
Table "public.user_event"
Column | Type | Collation | Nullable | Default
----------------------------------+--------------------------+-----------+----------+---------
id | uuid | | not null |
event_id | text | | not null |
user_id | bigint | | not null |
server_id | integer | | not null |
state | text | | not null |
generator_type | text | | |
timestamp_when_claimable | timestamp with time zone | | not null |
claimeditems | jsonb | | not null |
timestamp_when_energy_full | timestamp with time zone | | not null |
overflow_energy | integer | | not null |
timestamp_when_energy_cost_reset | timestamp with time zone | | not null |
grid | jsonb | | not null |
refill_count | integer | | not null |
Indexes:
"user_event_pkey" PRIMARY KEY, btree (id)
"idx_event_id" btree (event_id)
"idx_event_id_state" btree (event_id, state)
"idx_login_id" btree (login_id)
"idx_login_id_event_id" btree (login_id, event_id)
A versão do Postgres é 12, com os parâmetros mais importantes:
- buffers_compartilhados: '6GB'
- manutenção_work_mem: 1 GB
- max_wal_size: 10 GB
- min_wal_size: 1 GB
- checkpoint_timeout: '10min'
- efetivo_cache_size: "58 GB"
- log_autovacuum_min_duration: 0
- autovacuum_vacuum_scale_factor: 0,02
- autovacuum_analyze_scale_factor: 0,01
Os recursos da VM são:
- 16 CPUs
- 64 GB de RAM
- Disco SSD de 250 GB