

# Trabalhar com o autovacuum do PostgreSQL no Amazon RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum"></a>

É altamente recomendável que você use o recurso de autovacuum para bancos de dados PostgreSQL a fim de manter a integridade de sua instância de banco de dados PostgreSQL. O autovacuum automatiza a execução dos comandos VACUUM e ANALYZE. Ele verifica as tabelas com um grande número de tuplas inseridas, atualizadas ou excluídas. Após essa verificação, ele recupera o armazenamento removendo dados obsoletos ou tuplas do banco de dados PostgreSQL.

Por padrão, o autovacuum é ativado nas instâncias de banco de dados do RDS para PostgreSQL que você cria usando qualquer um dos grupos de parâmetros de banco de dados padrão do PostgreSQL. Outros parâmetros de configuração associados ao recurso autovacuum também são definidos por padrão. Como esses padrões são genéricos, você pode se beneficiar do ajuste de alguns dos parâmetros associados ao recurso autovacuum para seu workload específico. 

A seguir, você pode encontrar mais informações sobre o autovacuum e como ajustar alguns dos respectivos parâmetros em sua instância de banco de dados do RDS para PostgreSQL. Para ter informações gerais, consulte [Práticas recomendadas para trabalhar com PostgreSQL](CHAP_BestPractices.md#CHAP_BestPractices.PostgreSQL).

**Topics**
+ [Alocar memória para autovacuum](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory)
+ [Reduzir a probabilidade de conclusão de IDs de transação](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)
+ [Determinar se as tabelas no seu banco de dados precisam de vacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming.md)
+ [Determinar quais tabelas são atualmente elegíveis para autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables.md)
+ [Determinar se o autovacuum está em execução e por quanto tempo](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning.md)
+ [Realização de um congelamento manual de vacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)
+ [Reindexação de uma tabela quando o autovacuum está em execução](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing.md)
+ [Gerenciar o autovacuum com grandes índices](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)
+ [Outros parâmetros que afetam o autovacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms.md)
+ [Definir parâmetros de autovacuum em nível de tabela](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters.md)
+ [Registrar atividades do autovacuum e do vacuum em log](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging.md)
+ [Noções básicas sobre o comportamento do autovacuum com bancos de dados inválidos](appendix.postgresql.commondbatasks.autovacuumbehavior.md)
+ [Identificar e resolver bloqueadores de limpeza agressivos no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.md)

## Alocar memória para autovacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory"></a>

Um dos parâmetros mais importantes que influenciam a performance do autovacuum é o [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM). No RDS para PostgreSQL versões 14 e anteriores, o parâmetro `autovacuum_work_mem` é definido como -1, indicando que a configuração de `maintenance_work_mem` é usada em vez disso. Para todas as outras versões, `autovacuum_work_mem` é determinado por GREATEST(\$1DBInstanceClassMemory/32768\$1, 65536).

As operações vacuum manuais sempre usam a configuração `maintenance_work_mem`, com uma configuração padrão de GREATEST(\$1DBInstanceClassMemory/63963136\$11024\$1, 65536), e também é possível fazer o ajuste no nível da sessão usando o comando `SET` para operações `VACUUM` manuais mais específicas.

O `autovacuum_work_mem` determina a memória do autovacuum para armazenar identificadores de tuplas mortas (`pg_stat_all_tables.n_dead_tup`) para índices de vacuum.

Ao executar cálculos para determinar o valor do parâmetro `autovacuum_work_mem`, esteja ciente do seguinte:
+ Se você definir o parâmetro com um valor muito baixo, o processo de vacuum talvez precise verificar a tabela várias vezes para concluir o trabalho. Essas várias verificações podem ter um impacto negativo sobre a performance. Para instâncias maiores, a configuração de `maintenance_work_mem` ou `autovacuum_work_mem` para pelo menos 1 GB pode melhorar o desempenho de vaccum nas tabelas com um grande número de tuplas mortas. No entanto, no PostgreSQL versões 16 e anteriores, o uso de memória do vacuum é limitado a 1 GB, o que é suficiente para processar aproximadamente 179 milhões de tuplas mortas em uma única passagem. Se uma tabela tiver mais tuplas mortas do que isso, o vacuum precisará fazer várias passagens pelos índices da tabela, aumentando significativamente o tempo necessário. A partir da versão 17 do PostgreSQL, não há um limite de 1 GB, e o autovacuum pode processar mais de 179 milhões de tuplas usando árvores radix.

  Um identificador de tupla tem 6 bytes de tamanho. Para estimar a memória necessária para limpar um índice de uma tabela, consulte `pg_stat_all_tables.n_dead_tup` para encontrar o número de tuplas mortas e multiplique esse número por seis para determinar a memória necessária para realizar vacuum do índice em uma única passagem. Você pode usar a seguinte consulta:

  ```
  SELECT
      relname AS table_name,
      n_dead_tup,
      pg_size_pretty(n_dead_tup * 6) AS estimated_memory
  FROM
      pg_stat_all_tables
  WHERE
      relname = 'name_of_the_table';
  ```
+ O parâmetro `autovacuum_work_mem` funciona em conjunto com o parâmetro `autovacuum_max_workers`. Cada operador entre `autovacuum_max_workers` pode usar a memória que você alocar. Se você tiver muitas tabelas pequenas, aloque mais `autovacuum_max_workers` e menos `autovacuum_work_mem`. Se você tiver tabelas grandes (com mais de 100 GB), aloque mais memória e menos processos de operadores. Você precisa ter memória suficiente alocada para ter sucesso na sua maior tabela. Portanto, garanta que a combinação de processos de operadores e memória seja igual à memória total que deseja alocar.

## Reduzir a probabilidade de conclusão de IDs de transação
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming"></a>

Em alguns casos, as configurações de grupos de parâmetros relacionadas ao autovacuum podem não ser agressivas o suficiente para evitar a conclusão de IDs de transação. Para resolver isso, o RDS para PostgreSQL oferece um mecanismo que adapta automaticamente os valores dos parâmetros de autovacuum. O *autovacuum adaptável* é um recurso do RDS para PostgreSQL. Uma explicação detalhada da [conclusão de TransactionID](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND) encontra-se na documentação do PostgreSQL. 

O autovacuum adaptável está ativado por padrão para instâncias do RDS para PostgreSQL com o parâmetro dinâmico `rds.adaptive_autovacuum` definido como ATIVADO. É altamente recomendável manter esse recurso ativado. No entanto, para desabilitar esse recurso, defina o parâmetro `rds.adaptive_autovacuum` como 0 ou OFF (desativado). 

O wraparound de ID de transação ainda é possível mesmo quando o Amazon RDS ajusta os parâmetros de autovacuum. Nós encorajamos que você implemente um alarme do Amazon CloudWatch para a conclusão de IDs de transação. Para ter mais informações, consulte a postagem [Implement an early warning system for transaction ID wraparound in RDS for PostgreSQL](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/) (Implementar um sistema de alertas antecipados para conclusão de IDs de transação no RDS for PostgreSQL) no Blog de banco de dados da AWS.

Com o ajuste de parâmetros de autovacuum adaptável ativado, o Amazon RDS começa a ajustar parâmetros de autovacuum quando a métrica do CloudWatch `MaximumUsedTransactionIDs` atingir o valor do parâmetro `autovacuum_freeze_max_age` ou 500.000.000, o que for maior. 

O Amazon RDS continuará a ajustar os parâmetros para o autovacuum se uma tabela continuar a tendência para a conclusão de IDs de transação. Cada um desses ajustes dedica mais recursos ao autovacuum para evitar o envolvimento. O Amazon RDS atualiza os seguintes parâmetros relacionados ao autovacuum: 
+ [autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)
+  [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM) 
+  [autovacuum\$1naptime](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-NAPTIME) 

O RDS modificará esses parâmetros somente se o novo valor tornar o autovacuum mais agressivo. Os parâmetros são modificados na memória na instância de banco de dados. Os valores no grupo de parâmetros não são alterados. Para visualizar as configurações atuais na memória, use o comando SQL [SHOW](https://www.postgresql.org/docs/current/sql-show.html) PostgreSQL. 

Quando o Amazon RDS modifica qualquer um desses parâmetros de autovacuum, ele gera um evento para a instância de banco de dados afetada. Esse evento é visível no Console de gerenciamento da AWS e por meio da API do Amazon RDS. Depois que a métrica `MaximumUsedTransactionIDs` do CloudWatch volta a ficar abaixo do limite, o Amazon RDS redefine os parâmetros relacionados a autovacuum na memória de volta aos valores especificados no grupo de parâmetros. Em seguida, ele gera outro evento correspondente a essa alteração.

# Determinar se as tabelas no seu banco de dados precisam de vacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming"></a>

Você pode usar a consulta a seguir para mostrar o número de transações sem restrições em um banco de dados. A coluna `datfrozenxid` de uma linha `pg_database` do banco de dados é um limite inferior nos IDs de transação normais que aparecem nesse banco de dados. Essa coluna é o mínimo dos valores de `relfrozenxid` por tabela no banco de dados. 

```
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) desc limit 20;
```

Por exemplo, os resultados da execução da consulta anterior podem ser os seguintes.

```
datname    | age
mydb       | 1771757888
template0  | 1721757888
template1  | 1721757888
rdsadmin   | 1694008527
postgres   | 1693881061
(5 rows)
```

Quando a idade de um banco de dados atingir 2 bilhões de IDs de transação, ocorrerá a conclusão de IDs de transação (XID), e o banco de dados se tornará somente leitura. Use essa consulta para produzir uma métrica e execute-a algumas vezes por dia. Por padrão, o autovacuum é definido para manter a idade das transações como um máximo de 200,000,000 ([https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)).

Uma estratégia de monitoramento de exemplo pode ser assim:
+ Defina o valor `autovacuum_freeze_max_age` como 200 milhões de transações.
+ Se uma tabela atingir 500 milhões de transações sem restrições, um alarme de baixa gravidade será disparado. Este não é um valor não razoável, mas pode indicar que o autovacuum não está dando conta.
+ Se uma tabela chegar a 1 bilhão, ela deverá ser tratada como um alarme que requer medidas. Em geral, convém manter as idades mais próximas de `autovacuum_freeze_max_age` por motivos de performance. Recomendamos que você investigue usando as recomendações a seguir.
+ Se uma tabela atingir 1,5 bilhões de transações sem vacuum, um alarme de alta gravidade será disparado. Dependendo da rapidez com que seu banco de dados usa IDs de transação, esse alarme pode indicar que o sistema está ficando sem tempo para executar o autovacuum. Nesse caso, recomendamos que você resolva isso imediatamente.

Se uma tabela estiver ultrapassando constantemente esses limiares, modifique ainda mais seus parâmetros de autovacuum. Por padrão, usar VACUUM manualmente (que tem atrasos baseados em custos desabilitados) é mais agressivo do que usar o autovacuum padrão, mas também é mais intrusivo para o sistema como um todo.

Recomendamos o seguinte:
+ Esteja ciente e ative um mecanismo de monitoramento para que você tenha conhecimento da idade das transações mais antigas.

  Para obter informações sobre como criar um processo que avisa sobre a conclusão de IDs de transação, consulte a publicação do blog de banco de dados da AWS [Implement an early warning system for transaction ID wraparound no Amazon RDS for PostgreSQL](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/) (Implementar um sistema de alerta antecipado para conclusão de IDs de transação no Amazon RDS for PostgreSQL).
+ Para tabelas mais ocupadas, execute um congelamento de vacuum manual regularmente durante uma janela de manutenção além de depender do autovacuum. Para obter informações sobre a realização de um congelamento manual de vacuum, consulte [Realização de um congelamento manual de vacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md).

# Determinar quais tabelas são atualmente elegíveis para autovacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables"></a>

Muitas vezes, uma ou duas tabelas precisam de vacuum. Tabelas cujo valor de `relfrozenxid` é maior que o número de transações em `autovacuum_freeze_max_age` são sempre visadas pelo autovacuum. Caso contrário, se o número de tuplas obsoletas desde o último VACUUM exceder o limite de vacuum, um vacuum será realizado na tabela.

O [limite de autovacuum](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#AUTOVACUUM) é definido como:

```
Vacuum-threshold = vacuum-base-threshold + vacuum-scale-factor * number-of-tuples
```

em que o `vacuum base threshold` é `autovacuum_vacuum_threshold`, o `vacuum scale factor` é `autovacuum_vacuum_scale_factor` e o `number of tuples` é `pg_class.reltuples`.

Enquanto você estiver conectado ao seu banco de dados, execute a consulta a seguir para ver uma lista de tabelas que o autovacuum considera elegíveis para o vacuum.

```
WITH vbt AS (SELECT setting AS autovacuum_vacuum_threshold FROM 
pg_settings WHERE name = 'autovacuum_vacuum_threshold'),
vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor FROM 
pg_settings WHERE name = 'autovacuum_vacuum_scale_factor'), 
fma AS (SELECT setting AS autovacuum_freeze_max_age FROM pg_settings WHERE name = 'autovacuum_freeze_max_age'),
sto AS (select opt_oid, split_part(setting, '=', 1) as param,
split_part(setting, '=', 2) as value from (select oid opt_oid, unnest(reloptions) setting from pg_class) opt)
SELECT '"'||ns.nspname||'"."'||c.relname||'"' as relation,
pg_size_pretty(pg_table_size(c.oid)) as table_size,
age(relfrozenxid) as xid_age,
coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age,
(coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) +
coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples)
AS autovacuum_vacuum_tuples, n_dead_tup as dead_tuples FROM
pg_class c join pg_namespace ns on ns.oid = c.relnamespace 
join pg_stat_all_tables stat on stat.relid = c.oid join vbt on (1=1) join vsf on (1=1) join fma on (1=1)
left join sto cvbt on cvbt.param = 'autovacuum_vacuum_threshold' and c.oid = cvbt.opt_oid 
left join sto cvsf on cvsf.param = 'autovacuum_vacuum_scale_factor' and c.oid = cvsf.opt_oid
left join sto cfma on cfma.param = 'autovacuum_freeze_max_age' and c.oid = cfma.opt_oid
WHERE c.relkind = 'r' and nspname <> 'pg_catalog'
AND (age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)
OR coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * 
c.reltuples <= n_dead_tup)
ORDER BY age(relfrozenxid) DESC LIMIT 50;
```

# Determinar se o autovacuum está em execução e por quanto tempo
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning"></a>

Se você precisa realizar vacuum em uma tabela manualmente, determine se o autovacuum está sendo executado. Se estiver, talvez seja necessário ajustar parâmetros para fazê-lo funcionar mais eficientemente ou desativar o autovacuum temporariamente para poder executar VACUUM manualmente.

Use a seguinte consulta para determinar se o autovacuum está sendo executado e por quanto tempo, e se ele está esperando por outra sessão. 

```
SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query
FROM pg_stat_activity 
WHERE upper(query) LIKE '%VACUUM%' 
ORDER BY xact_start;
```

Depois de executar a consulta, você deverá ver uma saída semelhante à seguinte:

```
 datname | usename  |  pid  | state  | wait_event |      xact_runtime       | query  
 --------+----------+-------+--------+------------+-------------------------+--------------------------------------------------------------------------------------------------------
 mydb    | rdsadmin | 16473 | active |            | 33 days 16:32:11.600656 | autovacuum: VACUUM ANALYZE public.mytable1 (to prevent wraparound)
 mydb    | rdsadmin | 22553 | active |            | 14 days 09:15:34.073141 | autovacuum: VACUUM ANALYZE public.mytable2 (to prevent wraparound)
 mydb    | rdsadmin | 41909 | active |            | 3 days 02:43:54.203349  | autovacuum: VACUUM ANALYZE public.mytable3
 mydb    | rdsadmin |   618 | active |            | 00:00:00                | SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query+
         |          |       |        |            |                         | FROM pg_stat_activity                                                                                 +
         |          |       |        |            |                         | WHERE query like '%VACUUM%'                                                                           +
         |          |       |        |            |                         | ORDER BY xact_start;                                                                                  +
```

Vários problemas podem causar uma sessão de autovacuum de longa execução (ou seja, vários dias de duração). O problema mais comum é que o valor do seu parâmetro [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) está muito baixo para o tamanho da tabela ou a taxa de atualizações. 

Recomendamos o uso da fórmula a seguir para definir o valor do parâmetro `maintenance_work_mem`.

```
GREATEST({DBInstanceClassMemory/63963136*1024},65536)
```

Sessões de autovacuum em execução por pouco tempo também podem indicar problemas:
+ Isso pode indicar que não há `autovacuum_max_workers` suficientes para sua workload. Neste caso, você precisa indicar o número de operadores.
+ Pode indicar que existe uma corrupção de índice (o autovacuum trava e reinicia na mesma relação, mas não faz nenhum progresso). Nesse caso, execute um `vacuum freeze verbose table` manual para ver a causa exata. 

# Realização de um congelamento manual de vacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze"></a>

Você pode querer realizar um vacuum manual em uma tabela que tenha um processo de vacuum já em execução. Isso é útil se você identificou uma tabela com uma idade XID próxima de 2 bilhões de transações (ou acima de qualquer limite que você esteja monitorando).

As etapas a seguir são uma orientação com diversas variações no processo. Por exemplo, durante testes, suponha que você perceba que o valor do parâmetro [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) está muito baixo e que precisa tomar medidas imediatas em uma tabela. No entanto, talvez você não queira devolver a instância no momento. Usando as consultas nas seções anteriores, você determina qual tabela é o problema e observa uma sessão de autovacuum de longa execução. Você sabe que precisa alterar a configuração do parâmetro `maintenance_work_mem`, mas também precisa tomar medidas imediatas e evacuar a tabela em questão. O procedimento a seguir mostra o que fazer nessa situação.

**Para executar manualmente um congelamento de vacuum**

1. Abra duas sessões no banco de dados que contém a tabela em que você deseja realizar vacuum. Para a segunda sessão, use "screen" ou outro utilitário que mantenha a sessão se a conexão for encerrada.

1. Na sessão um, obtenha o “Process ID” (PID – ID de processo) da sessão de autovacuum em execução na tabela. 

   Execute a seguinte consulta para obter o PID da sessão de autovacuum.

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. Na sessão dois, calcule a quantidade de memória necessária para essa operação. Neste exemplo, determinamos que podemos usar até 2 GB de memória para essa operação e, portanto, definimos [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) da sessão atual como 2 GB.

   ```
   SET maintenance_work_mem='2 GB';
   SET
   ```

1. Na sessão dois, emita um comando `vacuum freeze verbose` para a tabela. A configuração detalhada é útil porque, embora não haja um relatório de andamento para isso no PostgreSQL, você pode ver as atividades.

   ```
   \timing on
   Timing is on.
   vacuum freeze verbose pgbench_branches;
   ```

   ```
   INFO:  vacuuming "public.pgbench_branches"
   INFO:  index "pgbench_branches_pkey" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  index "pgbench_branches_test_index" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  "pgbench_branches": found 0 removable, 50 nonremovable row versions 
        in 43 out of 43 pages
   DETAIL:  0 dead row versions cannot be removed yet.
   There were 9347 unused item pointers.
   0 pages are entirely empty.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   VACUUM
   Time: 2.765 ms
   ```

1. Na sessão um, se o autovacuum estava bloqueando a sessão de vacuum, `pg_stat_activity` mostrará que a espera é `T` para a sessão de vacuum. Nesse caso, encerre o processo de autovacuum da maneira a seguir.

   ```
   SELECT pg_terminate_backend('the_pid'); 
   ```
**nota**  
Algumas versões anteriores do Amazon RDS não podem encerrar um processo de autovacuum usando o comando anterior e falham com o seguinte erro: `ERROR: 42501: must be a superuser to terminate superuser process LOCATION: pg_terminate_backend, signalfuncs.c:227`. 

   Nesse ponto, sua sessão começa. O autovacuum é reiniciado imediatamente, pois essa tabela é provavelmente a mais alta em sua lista de trabalho. 

1. Inicie seu comando `vacuum freeze verbose` na sessão dois e depois termine o processo de autovacuum na sessão um.

# Reindexação de uma tabela quando o autovacuum está em execução
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing"></a>

Se um índice se tornar corrompido, o autovacuum continuará processando a tabela e falhará. Se você tentar um vacuum manual nessa situação, receberá uma mensagem de erro semelhante à mostrada a seguir.

```
postgres=>  vacuum freeze pgbench_branches;
ERROR: index "pgbench_branches_test_index" contains unexpected 
   zero page at block 30521
HINT: Please REINDEX it.
```

Quando o índice está corrompido e o autovacuum está tentando ser executado na tabela, você lutará com uma sessão de autovacuum já em execução. Ao emitir um comando [REINDEX](https://www.postgresql.org/docs/current/static/sql-reindex.html), você remove um bloqueio exclusivo na tabela. As operações de gravação são bloqueadas, bem como as operações de leitura que usam esse índice específico.

**Para reindexar uma tabela quando o autovacuum está em execução nela**

1. Abra duas sessões no banco de dados que contém a tabela em que você deseja realizar vacuum. Para a segunda sessão, use "screen" ou outro utilitário que mantenha a sessão se a conexão for encerrada.

1. Na sessão um, obtenha o PID da sessão de autovacuum em execução na tabela.

   Execute a seguinte consulta para obter o PID da sessão de autovacuum.

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) like '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. Na segunda sessão, emita o comando reindex.

   ```
   \timing on
   Timing is on.
   reindex index pgbench_branches_test_index;
   REINDEX
     Time: 9.966 ms
   ```

1. Na sessão um, se o autovacuum estava bloqueando o processo, você verá em `pg_stat_activity` que a espera é "T" para a sua sessão de vacuum. Nesse caso, você encerra o processo de autovacuum. 

   ```
   SELECT pg_terminate_backend('the_pid');
   ```

   Nesse ponto, sua sessão começa. É importante observar que o autovacuum é reiniciado imediatamente, pois essa tabela é provavelmente a mais alta em sua lista de trabalho. 

1. Inicie seu comando na sessão dois e depois termine o processo de autovacuum na sessão um.

# Gerenciar o autovacuum com grandes índices
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes"></a>

Como parte de sua operação, o *autovacuum* executa várias [fases de aspiração](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PHASES) ao trabalhar em uma tabela. Antes de a tabela ser limpa, todos os seus índices são aspirados primeiro. Ao remover vários índices grandes, essa fase consome uma quantidade significativa de tempo e recursos. Portanto, como prática recomendada, controle o número de índices em uma tabela e elimine os índices não usados.

Para esse processo, primeiro confira o tamanho geral do índice. Depois, determine se há índices possivelmente não usados que podem ser removidos conforme mostrado nos exemplos a seguir.

**Como conferir o tamanho da tabela e os respectivos índices**

```
postgres=> select pg_size_pretty(pg_relation_size('pgbench_accounts'));
pg_size_pretty
6404 MB
(1 row)
```

```
postgres=> select pg_size_pretty(pg_indexes_size('pgbench_accounts'));
pg_size_pretty
11 GB
(1 row)
```

Neste exemplo, o tamanho dos índices é maior do que a tabela. Essa diferença pode causar problemas de performance, pois os índices estão sobrecarregados ou não são usados, o que afeta as operações de autovacuum e de inserção.

**Como conferir índices não usados**

Usando a visualização [https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW), você pode conferir com que frequência um índice é usado com a coluna `idx_scan`. No exemplo a seguir, os índices não usados têm o valor `idx_scan` de `0`.

```
postgres=> select * from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
relid  | indexrelid | schemaname | relname          | indexrelname          | idx_scan | idx_tup_read | idx_tup_fetch
-------+------------+------------+------------------+-----------------------+----------+--------------+---------------
16433  | 16454      | public     | pgbench_accounts | index_f               | 6        | 6            | 0
16433  | 16450      | public     | pgbench_accounts | index_b               | 3        | 199999       | 0
16433  | 16447      | public     | pgbench_accounts | pgbench_accounts_pkey | 0        | 0            | 0
16433  | 16452      | public     | pgbench_accounts | index_d               | 0        | 0            | 0
16433  | 16453      | public     | pgbench_accounts | index_e               | 0        | 0            | 0
16433  | 16451      | public     | pgbench_accounts | index_c               | 0        | 0            | 0
16433  | 16449      | public     | pgbench_accounts | index_a               | 0        | 0            | 0
(7 rows)
```

```
postgres=> select schemaname, relname, indexrelname, idx_scan from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
schemaname  | relname          | indexrelname          | idx_scan
------------+------------------+-----------------------+----------
public      | pgbench_accounts | index_f               | 6
public      | pgbench_accounts | index_b               | 3
public      | pgbench_accounts | pgbench_accounts_pkey | 0
public      | pgbench_accounts | index_d               | 0
public      | pgbench_accounts | index_e               | 0
public      | pgbench_accounts | index_c               | 0
public      | pgbench_accounts | index_a               | 0
(7 rows)
```

**nota**  
Essas estatísticas são incrementais a partir do momento em que as estatísticas são redefinidas. Suponha que você tenha um índice usado apenas no final de um trimestre comercial ou apenas para um relatório específico. É possível que esse índice não tenha sido usado desde que as estatísticas foram redefinidas. Para ter mais informações, consulte [Funções de estatística](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-STATS-FUNCTIONS). Os índices usados para impor a exclusividade não terão verificações realizadas e não devem ser identificados como índices não usados. Para identificar os índices não usados, você deve ter um conhecimento profundo da aplicação e das respectivas consultas.

Para conferir quando as estatísticas foram redefinidas pela última vez em um banco de dados, use [ https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW]( https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW)

```
postgres=> select datname, stats_reset from pg_stat_database where datname = 'postgres';
    
datname   | stats_reset
----------+-------------------------------
postgres  | 2022-11-17 08:58:11.427224+00
(1 row)
```

## Aspirar uma tabela o mais rápido possível
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.Executing"></a>

**RDS para PostgreSQL 12 e posterior**

Se você tiver muitos índices em uma tabela grande, a instância de banco de dados poderá estar se aproximando do encapsulamento de ID (XID), que é quando o contador XID chega a zero. Se não for conferida, essa situação poderá ocasionar perda de dados. No entanto, você pode aspirar rapidamente a tabela sem limpar os índices. No RDS para PostgreSQL 12 e posterior, você pode usar VACUUM com a cláusula [https://www.postgresql.org/docs/current/sql-vacuum.html](https://www.postgresql.org/docs/current/sql-vacuum.html).

```
postgres=> VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) pgbench_accounts;
        
INFO: vacuuming "public.pgbench_accounts"
INFO: table "pgbench_accounts": found 0 removable, 8 nonremovable row versions in 1 out of 819673 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 7517
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s.
```

Se uma sessão de autovacuum já estiver em execução, você deverá encerrá-la para iniciar a aspiração manual. Para ter informações sobre a realização de um congelamento manual de aspiração, consulte [Realização de um congelamento manual de vacuum](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md).

**nota**  
Ignorar a limpeza do índice regularmente causa sobrecarga no índice, o que diminui a performance geral da verificação. O índice retém as linhas inativas e a tabela retém os ponteiros das linhas inativas. Consequentemente, `pg_stat_all_tables.n_dead_tup` aumenta até que o autovacuum ou um VACUUM manual com limpeza de índice seja executado. Como prática recomendada, use esse procedimento somente para evitar o encapsulamento de ID.

**RDS para PostgreSQL 11 e versões mais antigas**

No entanto, no RDS para PostgreSQL 11 e versões anteriores, a única maneira de permitir que a aspiração seja concluída mais rapidamente é reduzir o número de índices em uma tabela. A eliminação de um índice pode afetar os planos de consulta. Recomendamos que você elimine primeiro os índices não usados e, depois, descarte os índices quando o encapsulamento XID estiver muito próximo. Depois que o processo de aspiração for concluído, você poderá recriar esses índices.

# Outros parâmetros que afetam o autovacuum
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms"></a>

A consulta a seguir mostra os valores de alguns dos parâmetros que afetam diretamente o autovacuum e seu comportamento. Os [parâmetros de autovacuum](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html) são descritos inteiramente na documentação do PostgreSQL.

```
SELECT name, setting, unit, short_desc
FROM pg_settings
WHERE name IN (
'autovacuum_max_workers',
'autovacuum_analyze_scale_factor',
'autovacuum_naptime',
'autovacuum_analyze_threshold',
'autovacuum_analyze_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_cost_delay',
'autovacuum_vacuum_cost_limit',
'vacuum_cost_limit',
'autovacuum_freeze_max_age',
'maintenance_work_mem',
'vacuum_freeze_min_age');
```

Enquanto todos estes afetem o autovacuum, alguns dos mais importantes são:
+ [maintenance\$1work\$1mem](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE_WORK_MEM)
+ [autovacuum\$1freeze\$1max\$1age](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)
+ [autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS)
+ [autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)

# Definir parâmetros de autovacuum em nível de tabela
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters"></a>

Você pode definir [parâmetros de armazenamento](https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS) relacionados ao autovacuum em nível de tabela, o que pode ser melhor do que alterar o comportamento do banco de dados inteiro. Para tabelas grandes, talvez você precise definir configurações agressivas e talvez você não queira que o autovacuum se comporte dessa maneira para todas as tabelas.

A consulta a seguir mostra quais tabelas atualmente têm opções em nível de tabela.

```
SELECT relname, reloptions
FROM pg_class
WHERE reloptions IS NOT null;
```

Um exemplo em que isso pode ser útil é em tabelas que são muito maiores do que o resto das suas tabelas. Suponha que você tenha uma tabela de 300 GB e outras 30 tabelas com menos de 1 GB. Nesse caso, você pode definir alguns parâmetros específicos para a sua tabela grande, para não alterar o comportamento de todo o sistema.

```
ALTER TABLE mytable set (autovacuum_vacuum_cost_delay=0);
```

Fazer isso desativará o atraso de autovacuum baseado em custos para essa tabela, mas aumentará o uso de recursos no seu sistema. Normalmente, o autovacuum faz uma pausa durante `autovacuum_vacuum_cost_delay` sempre que `autovacuum_cost_limit` é alcançado. Para obtert mais detalhes, consulte a documentação do PostgreSQL sobre [vacuum baseado no custo](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST).

# Registrar atividades do autovacuum e do vacuum em log
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging"></a>

Informações sobre atividades de autovacuum são enviadas para `postgresql.log` com base no nível especificado no parâmetro `rds.force_autovacuum_logging_level`. A seguir estão os valores permitidos para esse parâmetro e as versões do PostgreSQL para as quais esse valor é a configuração padrão:
+ `disabled` (PostgreSQL 10, PostgreSQL 9.6)
+ `debug5`, `debug4`, `debug3`, `debug2`, `debug1`
+ `info` (PostgreSQL 12, PostgreSQL 11)
+ `notice`
+ `warning` (PostgreSQL 13 e superior)
+ `error`, log, `fatal`, `panic`

A configuração `rds.force_autovacuum_logging_level` funciona com o parâmetro `log_autovacuum_min_duration`. O valor do parâmetro `log_autovacuum_min_duration` é o limite (em milissegundos) acima do qual as ações autovacuum são registradas em log. Uma configuração `-1` não registra nada em log, enquanto uma configuração 0 registra todas as ações em log. Como ocorre com `rds.force_autovacuum_logging_level`, os valores padrão de `log_autovacuum_min_duration` são dependentes da versão, da seguinte maneira: 
+ `10000 ms`: PostgreSQL 14, PostgreSQL 13, PostgreSQL 12 e PostgreSQL 11 
+ `(empty)`: nenhum valor padrão para PostgreSQL 10 e PostgreSQL 9.6

Recomendamos que você defina `rds.force_autovacuum_logging_level` como `WARNING`. Também recomendamos definir `log_autovacuum_min_duration` para um valor entre 1000 e 5000. Uma configuração 5000 registra em log a atividade que leva mais de 5.000 milissegundos. Qualquer configuração diferente de -1 também registrará mensagens se a ação autovacuum for ignorada devido a um bloqueio conflitante ou relações descartadas simultaneamente. Para ter mais informações, consulte [Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html) (Aplicação automática do vacuum) na documentação do PostgreSQL. 

Para solucionar problemas, você pode alterar o parâmetro `rds.force_autovacuum_logging_level` para um dos níveis de depuração, de `debug1` a `debug5`, para obter informações mais detalhadas. Recomendamos que você use as configurações de depuração por curtos períodos e apenas para fins de solução de problemas. Para saber mais, consulte [When to log](https://www.postgresql.org/docs/current/static/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN) (Quando registrar em log) na documentação do PostgreSQL. 

**nota**  
O PostgreSQL permite que a conta `rds_superuser` visualize sessões de autovacuum em `pg_stat_activity`. Por exemplo, você pode identificar e encerrar uma sessão de autovacuum que esteja bloqueando a execução de um comando, ou executando de forma mais lenta do que um comando de vacuum emitido manualmente.

# Noções básicas sobre o comportamento do autovacuum com bancos de dados inválidos
<a name="appendix.postgresql.commondbatasks.autovacuumbehavior"></a>

 Um novo valor `-2` é introduzido na coluna `datconnlimit` do catálogo `pg_database` para indicar bancos de dados que foram interrompidos no meio da operação DROP DATABASE como inválidos. 

 Esse novo valor está disponível nas seguintes versões do RDS para PostgreSQL: 
+ 15.4 e todas as versões posteriores
+ 14.9 e versões posteriores
+ 13.12 e versões posteriores
+ 12.16 e versões posteriores
+ 11.21 e versões posteriores

Bancos de dados inválidos não afetam a capacidade do autovacuum de congelar a funcionalidade de bancos de dados válidos. O Autovacuum ignora bancos de dados inválidos. Consequentemente, as operações regulares de limpeza continuarão funcionando de forma adequada e eficiente em todos os bancos de dados válidos no ambiente do PostgreSQL.

**Topics**
+ [ID da transação de monitoramento](#appendix.postgresql.commondbatasks.autovacuum.monitorxid)
+ [Ajustar a consulta de monitoramento](#appendix.postgresql.commondbatasks.autovacuum.monitoradjust)
+ [Resolver o problema de banco de dados inválido](#appendix.postgresql.commondbatasks.autovacuum.connissue)

## ID da transação de monitoramento
<a name="appendix.postgresql.commondbatasks.autovacuum.monitorxid"></a>

 A função `age(datfrozenxid)` geralmente é usada para monitorar a idade do ID de transação (XID) dos bancos de dados para evitar o encapsulamento de IDs de transação. 

 Como bancos de dados inválidos são excluídos do autovacuum, seu contador de ID de transação (XID) pode atingir o valor máximo de `2 billion`, ser encapsulado em `- 2 billion` e continuar esse ciclo indefinidamente. Uma consulta típica para monitorar o encapsulamento de IDs de transação pode ser: 

```
SELECT max(age(datfrozenxid)) FROM pg_database;
```

No entanto, com a introdução do valor -2 para `datconnlimit`, bancos de dados inválidos podem distorcer os resultados dessa consulta. Como esses bancos de dados não são válidos e não devem fazer parte das verificações de manutenção regulares, eles podem causar falsos positivos, levando você a acreditar que o `age(datfrozenxid)` é maior do que realmente é.

## Ajustar a consulta de monitoramento
<a name="appendix.postgresql.commondbatasks.autovacuum.monitoradjust"></a>

 Para garantir um monitoramento preciso, você deve ajustar sua consulta de monitoramento para excluir bancos de dados inválidos. Siga esta consulta recomendada: 

```
SELECT
    max(age(datfrozenxid))
FROM
    pg_database
WHERE
    datconnlimit <> -2;
```

Essa consulta garante que somente bancos de dados válidos sejam considerados no cálculo `age(datfrozenxid)`, fornecendo um reflexo real da idade do ID da transação no ambiente do PostgreSQL.

## Resolver o problema de banco de dados inválido
<a name="appendix.postgresql.commondbatasks.autovacuum.connissue"></a>

 Ao tentar se conectar a um banco de dados inválido, talvez seja exibida uma mensagem de erro semelhante à seguinte: 

```
postgres=> \c db1
connection to server at "mydb.xxxxxxxxxx.us-west-2.rds.amazonaws.com" (xx.xx.xx.xxx), port xxxx failed: FATAL:  cannot connect to invalid database "db1"
HINT:  Use DROP DATABASE to drop invalid databases.
Previous connection kept
```

 Além disso, se o parâmetro `log_min_messages` estiver definido como `DEBUG2` ou posterior, você poderá observar as seguintes entradas de log indicando que o processo de autovacuum está ignorando o banco de dados inválido: 

```
       
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db6"
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db1"
```

Para resolver o problema, siga a `HINT` fornecida durante a tentativa de conexão. Conecte-se a qualquer banco de dados válido usando sua conta principal do RDS ou uma conta de banco de dados com o perfil `rds_superuser` e elimine bancos de dados inválidos.

```
SELECT
    'DROP DATABASE ' || quote_ident(datname) || ';'
FROM
    pg_database
WHERE
    datconnlimit = -2 \gexec
```

# Identificar e resolver bloqueadores de limpeza agressivos no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring"></a>

No PostgreSQL, a limpeza é vital para garantir a integridade do banco de dados, pois recupera o armazenamento e evita problemas de [conclusão do ID da transação.](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND) No entanto, há momentos em que a limpeza pode ser impedida de operar conforme desejado, o que pode resultar em degradação do desempenho e sobrecarga do armazenamento e até mesmo afetar a disponibilidade da instância de banco de dados pelo wraparound de ID de transação. Portanto, identificar e resolver esses problemas é essencial para o desempenho e a disponibilidade ideais do banco de dados. Leia [Understanding autovacuum in Amazon RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/) para saber mais sobre o autovacuum.

A função `postgres_get_av_diag()` ajuda a identificar problemas que impedem ou atrasam o progresso da limpeza agressiva. São fornecidas sugestões, que podem incluir comandos para resolver o problema onde ele é identificável ou orientações para diagnósticos adicionais quando o problema não é identificável. Bloqueadores de limpeza agressiva são relatados quando a idade excede o limite de [autovacuum adaptativo](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming) do RDS de 500 milhões de IDs de transação.

**Qual é a idade do ID da transação?**

A função `age()` para IDs de transação calcula o número de transações que ocorreram desde o ID de transação não congelado mais antigo de um banco de dados (`pg_database.datfrozenxid`) ou tabela (`pg_class.relfrozenxid`). Esse valor indica a atividade do banco de dados desde a última operação de limpeza agressiva e destaca a provável workload para os próximos processos de VACUUM. 

**O que é uma limpeza agressiva?**

Uma operação VACUUM agressiva conduz uma varredura abrangente de todas as páginas em uma tabela, incluindo aquelas normalmente ignoradas durante operações VACUUM regulares. Essa verificação completa visa "congelar" os IDs de transação que se aproximam de sua idade máxima, evitando efetivamente uma situação conhecida como [conclusão de ID de transação](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND).

Para que `postgres_get_av_diag()` reporte bloqueadores, o bloqueador deve ter pelo menos 500 milhões de transações de idade.

**Topics**
+ [Instalar ferramentas de monitoramento e diagnóstico de autovacuum no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)
+ [Funções de postgres\$1get\$1av\$1diag() no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.md)
+ [Solucionar bloqueadores de limpeza identificáveis no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md)
+ [Solucionar bloqueadores de limpeza não identificáveis no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers.md)
+ [Resolver problemas de desempenho de limpeza no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md)
+ [Explicação das mensagens de AVISO no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

# Instalar ferramentas de monitoramento e diagnóstico de autovacuum no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation"></a>

No momento, a função `postgres_get_av_diag()` está disponível nas seguintes versões do RDS para PostgreSQL:
+ 17.2 e versões 17 posteriores
+ 16.7 e versões 16 posteriores
+ 15.11 e versões 15 posteriores
+ 14.16 e versões 14 posteriores
+ 13.19 e versões 13 posteriores

 Para usar `postgres_get_av_diag()`, crie a extensão `rds_tools`.

```
postgres=> CREATE EXTENSION rds_tools ;
CREATE EXTENSION
```

Para verificar se a extensão está instalada.

```
postgres=> \dx rds_tools
             List of installed extensions
   Name    | Version |  Schema   |                    Description
 ----------+---------+-----------+----------------------------------------------------------
 rds_tools |   1.8   | rds_tools | miscellaneous administrative functions for RDS PostgreSQL
 1 row
```

Verifique se a função foi criada.

```
postgres=> SELECT
    proname function_name,
    pronamespace::regnamespace function_schema,
    proowner::regrole function_owner
FROM
    pg_proc
WHERE
    proname = 'postgres_get_av_diag';
    function_name     | function_schema | function_owner
----------------------+-----------------+----------------
 postgres_get_av_diag | rds_tools       | rds_superuser
(1 row)
```

# Funções de postgres\$1get\$1av\$1diag() no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions"></a>

A função `postgres_get_av_diag()` recupera informações de diagnóstico sobre processos de autovacuum que estão bloqueando ou atrasando em um banco de dados do RDS para PostgreSQL. A consulta precisa ser executada no banco de dados com o ID de transação mais antigo para obter resultados precisos. Para obter mais informações sobre como usar o banco de dados com o ID de transação mais antigo, consulte [Não conectado ao banco de dados com o ID de transação mais antigo](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

```
SELECT
    blocker,
    DATABASE,
    blocker_identifier,
    wait_event,
    TO_CHAR(autovacuum_lagging_by, 'FM9,999,999,999') AS autovacuum_lagging_by,
    suggestion,
    suggested_action
FROM (
    SELECT
        *
    FROM
        rds_tools.postgres_get_av_diag ()
    ORDER BY
        autovacuum_lagging_by DESC) q;
```

A função `postgres_get_av_diag()` retorna uma tabela com as informações a seguir:

**blocker**  
Especifica a categoria da atividade do banco de dados que está bloqueando o vacuum.  
+ [Instrução ativa](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [Ocioso na transação](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [Transação preparada](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [Slot de replicação lógica](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [Réplica de leitura com slot de replicação física](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [Réplica de leitura com replicação de streaming](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [Tabelas temporárias](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

**banco de dados**  
Especifica o nome do banco de dados, quando aplicável e suportado. Este é o banco de dados no qual a atividade está em andamento e bloqueia ou bloqueará o autovacuum. Este é o banco de dados ao qual você precisa se conectar e tomar ação.

**blocker\$1identifier**  
Especifica o identificador da atividade que está bloqueando ou bloqueará o autovacuum. O identificador pode ser um ID de processo junto com uma instrução SQL, uma transação preparada, um endereço IP de uma réplica de leitura e o nome do slot de replicação, seja lógico ou físico.

**wait\$1event**  
Especifica o [evento de espera](PostgreSQL.Tuning.md) da sessão de bloqueio e é aplicável para os seguintes bloqueadores:  
+ Instrução ativa
+ Ocioso na transação

**autovacuum\$1lagging\$1by**  
Especifica o número de transações que o autovacuum está atrasado no trabalho pendente por categoria.

**suggestion**  
Especifica sugestões para resolver o bloqueador. Essas instruções incluem o nome do banco de dados no qual a atividade existe, quando aplicável, o ID do processo (PID) da sessão, quando aplicável, e a ação a ser tomada.

**suggested\$1action**  
Sugere a ação que precisa ser tomada para resolver o bloqueador.

# Solucionar bloqueadores de limpeza identificáveis no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

O Autovacuum realiza limpezas agressivas e reduz a idade dos IDs de transação para abaixo do limite especificado pelo parâmetro `autovacuum_freeze_max_age` de sua instância do RDS. É possível rastrear essa idade usando a métrica `MaximumUsedTransactionIDs` do Amazon CloudWatch.

Para encontrar a configuração de `autovacuum_freeze_max_age` (que tem um padrão de 200 milhões de IDs de transação) da sua instância do Amazon RDS, use a seguinte consulta:

```
SELECT
    TO_CHAR(setting::bigint, 'FM9,999,999,999') autovacuum_freeze_max_age
FROM
    pg_settings
WHERE
    name = 'autovacuum_freeze_max_age';
```

Observe que `postgres_get_av_diag()` só verifica se há bloqueadores de limpeza agressiva quando a idade excede o limite de 500 milhões de IDs de transação do [autovacuum adaptativo](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming) do Amazon RDS. Para que `postgres_get_av_diag()` detecte bloqueadores, o bloqueador deve ter pelo menos 500 milhões de transações de idade.

A função `postgres_get_av_diag()` identifica os seguintes tipos de bloqueadores:

**Topics**
+ [Instrução ativa](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [Ocioso na transação](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [Transação preparada](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [Slot de replicação lógica](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [Réplicas de leitura](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [Tabelas temporárias](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

## Instrução ativa
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement"></a>

No PostgreSQL, uma instrução ativa é uma instrução SQL que está sendo executada atualmente pelo banco de dados. Isso inclui consultas, transações ou quaisquer operações em andamento. Ao monitorar por meio do `pg_stat_activity`, a coluna de estado indica que o processo com o PID correspondente está ativo.

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando identifica uma instrução que é uma instrução ativa.

```
blocker               | Active statement
database              | my_database
blocker_identifier    | SELECT pg_sleep(20000);
wait_event            | Timeout:PgSleep
autovacuum_lagging_by | 568,600,871
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (29621);"}
```

**Ação sugerida**

Seguindo as orientações na coluna `suggestion`, o usuário pode se conectar ao banco de dados em que a instrução ativa está presente e, conforme especificado na coluna `suggested_action`, é recomendável analisar cuidadosamente a opção de encerrar a sessão. Se o encerramento for seguro, use a função `pg_terminate_backend()` para encerrar a sessão. Essa ação pode ser executada por um administrador (como a conta mestra do RDS) ou por um usuário com o privilégio `pg_terminate_backend()` necessário.

**Atenção**  
Uma sessão encerrada reverterá (`ROLLBACK`) as alterações feitas. Dependendo de seus requisitos, pode ser necessário executar a instrução novamente. No entanto, é recomendável fazer isso somente após o processo do autovacuum terminar a operação de limpeza agressiva.

## Ocioso na transação
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction"></a>

Uma instrução ociosa na transação se refere a qualquer sessão que abriu uma transação explícita (como emitir uma instrução `BEGIN`), realizou algum trabalho e agora está esperando que o cliente passe mais trabalho ou sinalize o final da transação emitindo um `COMMIT`, `ROLLBACK` ou `END` (o que resultaria em um `COMMIT` implícito).

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando identifica uma instrução `idle in transaction` como um bloqueador.

```
blocker               | idle in transaction
database              | my_database
blocker_identifier    | INSERT INTO tt SELECT * FROM tt;
wait_event            | Client:ClientRead
autovacuum_lagging_by | 1,237,201,759
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (28438);"}
```

**Ação sugerida**

Conforme indicado na coluna `suggestion`, conecte-se ao banco de dados em que a sessão ociosa na transação está presente e encerre a sessão usando a função `pg_terminate_backend()`. O usuário pode ser seu usuário administrador (conta mestra do RDS) ou um usuário com o privilégio `pg_terminate_backend()`.

**Atenção**  
Uma sessão encerrada reverterá (`ROLLBACK`) as alterações feitas. Dependendo de seus requisitos, pode ser necessário executar a instrução novamente. No entanto, é recomendável fazer isso somente após o processo do autovacuum terminar a operação de limpeza agressiva.

## Transação preparada
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

O PostgreSQL permite transações que fazem parte de uma estratégia de confirmação bifásica chamada [transações preparadas](https://www.postgresql.org/docs/current/sql-prepare-transaction.html). Elas são habilitadas ao definir o parâmetro `max_prepared_transactions` como um valor diferente de zero. As transações preparadas são projetadas para garantir que uma transação seja durável e permaneça disponível mesmo após falhas no banco de dados, reinicializações ou desconexões do cliente. Como as transações regulares, elas recebem um ID de transação e podem afetar o autovacuum. Se deixado em um estado preparado, o autovacuum não realiza o congelamento e isso pode levar à conclusão do ID da transação.

Quando as transações são deixadas no estado de preparação indefinidamente, sem serem resolvidas por um gerenciador de transações, elas se tornam transações preparadas órfãs. A única maneira de corrigir isso é confirmar ou reverter a transação usando os comandos `COMMIT PREPARED` ou `ROLLBACK PREPARED`, respectivamente.

**nota**  
Esteja ciente de que um backup feito durante uma transação preparada ainda conterá essa transação após a restauração. Consulte as informações a seguir sobre como localizar e fechar essas transações.

A função `postgres_get_av_diag()` exibe a saída a seguir quando identifica um bloqueador que é uma transação preparada.

```
blocker               | Prepared transaction
database              | my_database
blocker_identifier    | myptx
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database" and consider either COMMIT or ROLLBACK the prepared transaction using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"COMMIT PREPARED 'myptx';",[OR],"ROLLBACK PREPARED 'myptx';"}
```

**Ação sugerida**

Conforme mencionado na coluna de sugestões, conecte-se ao banco de dados em que a transação preparada está localizada. Com base na coluna `suggested_action`, analise cuidadosamente se deseja executar `COMMIT` ou `ROLLBACK`, e então execute a ação apropriada.

Para monitorar transações preparadas em geral, o PostgreSQL oferece uma visualização de catálogo chamada `pg_prepared_xacts`. Use a consulta a seguir para encontrar transações preparadas.

```
SELECT
    gid,
    prepared,
    owner,
    database,
    transaction AS oldest_xmin
FROM
    pg_prepared_xacts
ORDER BY
    age(transaction) DESC;
```

## Slot de replicação lógica
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot"></a>

O objetivo de um slot de replicação é manter as alterações não consumidas até que elas sejam replicadas em um servidor de destino. Consulte a página sobre [replicação lógica](https://www.postgresql.org/docs/current/logical-replication.html) do PostgreSQL para obter mais informações.

Existem dois tipos de slots de replicação lógica.

**Slots de replicação lógica inativa**

Quando a replicação é encerrada, os logs de transações não consumidos não podem ser removidos e o slot de replicação fica inativo. Embora um slot de replicação lógica inativo não seja usado atualmente por um assinante, ele permanece no servidor, levando à retenção de arquivos WAL e impedindo a remoção de logs de transações antigos. Isso pode aumentar o uso do disco e, especificamente, impedir que o autovacuum limpe as tabelas internas do catálogo, pois o sistema deve evitar que as informações do LSN sejam sobrescritas. Se não for resolvido, esse problema pode resultar em inchaço do catálogo, degradação do desempenho e aumento do risco de conclusão da limpeza, potencialmente causando tempo de inatividade das transações.

**Slots de replicação lógica ativos, mas lentos**

Às vezes, a remoção de tuplas inativas do catálogo é adiada devido à degradação do desempenho da replicação lógica. Esse atraso na replicação retarda a atualização do `catalog_xmin` e pode causar inchaço do catálogo e conclusão da limpeza.

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando encontra um slot de replicação lógica como um bloqueador.

```
blocker               | Logical replication slot
database              | my_database
blocker_identifier    | slot1
wait_event            | Not applicable
autovacuum_lagging_by | 1,940,103,068
suggestion            | Ensure replication is active and resolve any lag for the slot if active. If inactive, consider dropping it using the command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_drop_replication_slot('slot1') FROM pg_replication_slots WHERE active = 'f';"}
```

**Ação sugerida**

Para resolver esse problema, verifique se há problemas com o esquema ou os dados de destino na configuração de replicação que possam estar encerrando o processo de aplicação. Os motivos mais comuns são: 
+ Colunas ausentes
+ Tipos de dados incompatíveis
+ Incompatibilidade de dados
+ Tabela ausente

Se o problema estiver relacionado a questões de infraestrutura:
+ Problemas de rede: [Como resolver problemas com um banco de dados do Amazon RDS que está em um estado de rede incompatível?](https://repost.aws/knowledge-center/rds-incompatible-network).
+ O banco de dados ou a instância de banco de dados não está disponível devido aos seguintes motivos:
  + A instância da réplica está sem armazenamento: consulte [Como resolver problemas que ocorrem quando as instâncias de banco de dados do Amazon RDS ficam sem armazenamento?](https://repost.aws/knowledge-center/rds-out-of-storage) para obter informações sobre como adicionar armazenamento.
  + Parâmetros incompatíveis: consulte [Como corrijo uma instância de banco de dados do Amazon RDS que está presa no status de parâmetros incompatíveis?](https://repost.aws/knowledge-center/rds-incompatible-parameters) para obter mais informações sobre como resolver o problema.

Se sua instância estiver fora da rede da AWS ou no AWS EC2, consulte seu administrador sobre como resolver os problemas de disponibilidade ou problemas relacionados à infraestrutura.

**Descartar o slot inativo**

**Atenção**  
Cuidado: antes de descartar um slot de replicação, verifique cuidadosamente se ele não tem nenhuma replicação em andamento, está inativo e está em um estado irrecuperável. Descartar um slot prematuramente pode interromper a replicação ou causar perda de dados.

Depois de confirmar que o slot de replicação não é mais necessário, descarte-o para permitir que o autovacuum continue. A condição `active = 'f'` garante que somente um slot inativo seja descartado.

```
SELECT pg_drop_replication_slot('slot1') WHERE active ='f'
```

## Réplicas de leitura
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas"></a>

Quando a configuração `hot_standby_feedback` está habilitada para [réplicas de leitura do Amazon RDS](USER_PostgreSQL.Replication.ReadReplicas.md), ela impede que o autovacuum no banco de dados primário remova linhas inativas que ainda podem ser necessárias para consultas executadas na réplica de leitura. Isso afeta todos os tipos de réplicas de leitura físicas, incluindo as que são gerenciadas com ou sem slots de replicação. Esse comportamento é necessário porque as consultas executadas na réplica em espera exigem que essas linhas permaneçam disponíveis no primário, evitando [conflitos de consultas](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT) e cancelamentos.

**Réplica de leitura com slot de replicação física**  
As réplicas de leitura com slots de replicação física aumentam significativamente a confiabilidade e a estabilidade da replicação no RDS para PostgreSQL. Esses slots garantem que o banco de dados primário retenha os arquivos essenciais do log de gravação antecipada até que a réplica os processe, mantendo a consistência de dados mesmo durante interrupções na rede.

A partir do RDS para PostgreSQL versão 14, todas as réplicas utilizam slots de replicação. Nas versões anteriores, somente réplicas entre regiões usavam slots de replicação.

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando encontra uma réplica de leitura com slot de replicação física como um bloqueador.

```
blocker               | Read replica with physical replication slot
database              |
blocker_identifier    | rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxxx
wait_event            | Not applicable
autovacuum_lagging_by | 554,080,689
suggestion            | Run the following query on the replica "rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxx" to find the long running query:                           
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;                                                       
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                 +                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;","                                                                                 +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                   +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Delete the read replica if not needed"}
```

**Réplica de leitura com replicação de streaming**  
O Amazon RDS permite configurar réplicas de leitura sem um slot de replicação física em versões mais antigas, até a versão 13. Essa abordagem reduz a sobrecarga ao permitir que o primário recicle arquivos WAL de forma mais agressiva, o que é vantajoso em ambientes com espaço em disco limitado e que podem tolerar ReplicaLag ocasional. No entanto, sem um slot, o standby deve permanecer sincronizado para evitar a perda de arquivos WAL. O Amazon RDS usa arquivos WAL arquivados para ajudar a réplica a se recuperar caso ela fique atrasada, mas esse processo exige monitoramento cuidadoso e pode ser lento.

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando encontra uma réplica de leitura de streaming como um bloqueador.

```
blocker               | Read replica with streaming replication slot
database              | Not applicable
blocker_identifier    | xx.x.x.xxx/xx
wait_event            | Not applicable
autovacuum_lagging_by | 610,146,760
suggestion            | Run the following query on the replica "xx.x.x.xxx" to find the long running query:                                                                                                                                                         +
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;                                                                                                                                                     +
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                       +
                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;","                                                                                                                        +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                                                          +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Delete the read replica if not needed"}
```

**Ação sugerida**

Conforme recomendado na coluna `suggested_action`, analise cuidadosamente essas opções para desbloquear o autovacuum.
+ **Encerrar a consulta**: seguindo as orientações na coluna de sugestões, é possível se conectar à réplica de leitura, conforme especificado na coluna suggested\$1action. É recomendável analisar cuidadosamente a opção de encerrar a sessão. Se o encerramento for considerado seguro, use a função `pg_terminate_backend()` para encerrar a sessão. Essa ação pode ser executada por um administrador (como a conta mestra do RDS) ou por um usuário com o privilégio pg\$1terminate\$1backend() necessário.

  Execute o comando SQL a seguir na réplica de leitura para encerrar a consulta que está impedindo a limpeza das linhas antigas no primário. O valor de `backend_xmin` é reportado na saída da função:

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **Desabilitar o feedback de standby a quente**: considere desabilitar o parâmetro `hot_standby_feedback` se ele estiver causando atrasos significativos na limpeza.

  O parâmetro `hot_standby_feedback` permite que uma réplica de leitura informe o primário sobre sua atividade de consulta, impedindo que o primário faça a limpeza de tabelas ou linhas que estão em uso no standby. Embora isso garanta a estabilidade da consulta no standby, pode atrasar significativamente a limpeza no primário. Desabilitar esse recurso permite que o primário prossiga com a limpeza sem esperar que o standby se atualize. No entanto, isso pode levar a cancelamentos de consultas ou falhas no standby se ele tentar acessar linhas que foram removidas pela limpeza no primário.
+ **Excluir a réplica de leitura se não for necessária**: se a réplica de leitura não for mais necessária, você poderá exclui-la. Isso removerá a sobrecarga de replicação associada e permitirá que o primário recicle os logs de transações sem ser retido pela réplica.

## Tabelas temporárias
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

[Tabelas temporárias](https://www.postgresql.org/docs/current/sql-createtable.html), criadas usando a palavra-chave `TEMPORARY`, residem no esquema temporário, por exemplo pg\$1temp\$1xxx, e só podem ser acessadas pela sessão que as criou. As tabelas temporárias são removidas quando a sessão termina. No entanto, essas tabelas são invisíveis para o processo de autovacuum do PostgreSQL e devem ser limpas manualmente pela sessão que as criou. Tentar limpar a tabela temporária de outra sessão não tem efeito.

Em circunstâncias incomuns, uma tabela temporária pode existir sem uma sessão ativa que a possua. Se a sessão proprietária terminar inesperadamente devido a uma falha fatal, problemas de rede ou eventos do tipo, a tabela temporária pode não ser limpa, deixando-a como uma tabela "órfã". Quando o processo de autovacuum do PostgreSQL detecta uma tabela temporária órfã, ele registra em log a seguinte mensagem:

```
LOG: autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"
```

A função `postgres_get_av_diag()` exibe uma saída semelhante à saída a seguir quando identifica uma tabela temporária como um bloqueador. Para que a função exiba corretamente a saída relacionada às tabelas temporárias, ela precisa ser executada no mesmo banco de dados em que essas tabelas existem.

```
blocker               | Temporary table
database              | my_database
blocker_identifier    | pg_temp_14.ttemp
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database". Review carefully, you may consider dropping temporary table using command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"DROP TABLE ttemp;"}
```

**Ação sugerida**

Siga as instruções fornecidas na coluna `suggestion` da saída para identificar e remover a tabela temporária que está impedindo a execução do autovacuum. Use o comando a seguir para eliminar a tabela temporária reportada por `postgres_get_av_diag()`. Substitua o nome da tabela com base na saída fornecida pela função `postgres_get_av_diag()`.

```
DROP TABLE my_temp_schema.my_temp_table;
```

A seguinte consulta pode ser usada para identificar tabelas temporárias:

```
SELECT
    oid,
    relname,
    relnamespace::regnamespace,
    age(relfrozenxid)
FROM
    pg_class
WHERE
relpersistence = 't'
ORDER BY
    age(relfrozenxid) DESC;
```

# Solucionar bloqueadores de limpeza não identificáveis no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

Esta seção explora razões adicionais que podem impedir o progresso da limpeza. Esses problemas atualmente não são diretamente identificáveis pela função `postgres_get_av_diag()`. 

**Topics**
+ [Páginas inválidas](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)
+ [Inconsistência do índice](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency)
+ [Taxa de transação excepcionalmente alta](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate)

## Páginas inválidas
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages"></a>

Um erro de página inválida ocorre quando o PostgreSQL detecta uma incompatibilidade na soma de verificação de uma página ao acessá-la. O conteúdo é ilegível, impedindo que o autovacuum congele as tuplas. Isso efetivamente interrompe o processo de limpeza. O seguinte erro é registrado no log do PostgreSQL:

```
WARNING:  page verification failed, calculated checksum YYYYY but expected XXXX
ERROR:  invalid page in block ZZZZZ of relation base/XXXXX/XXXXX
CONTEXT:  automatic vacuum of table myschema.mytable
```

**Determinar o tipo de objeto**

```
ERROR: invalid page in block 4305910 of relation base/16403/186752608 
WARNING: page verification failed, calculated checksum 50065 but expected 60033
```

A partir da mensagem de erro, o caminho `base/16403/186752608` fornece as seguintes informações:
+ "base" é o nome do diretório sob o diretório de dados do PostgreSQL.
+ "16403" é o OID do banco de dados, que você pode consultar no catálogo do sistema `pg_database`.
+ "186752608" é o `relfilenode`, que você pode usar para pesquisar o esquema e o nome do objeto no catálogo do sistema `pg_class`.

Ao verificar a saída da consulta a seguir no banco de dados afetado, será possível determinar o tipo de objeto. A consulta a seguir recupera informações do objeto para oid: 186752608. Substitua o OID pelo relevante para o erro que você encontrou.

```
SELECT
    relname AS object_name,
    relkind AS object_type,
    nspname AS schema_name
FROM
    pg_class c
    JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
    c.oid = 186752608;
```

Para obter mais informações, consulte a documentação do PostgreSQL [https://www.postgresql.org/docs/current/catalog-pg-class.html](https://www.postgresql.org/docs/current/catalog-pg-class.html) para ver todos os tipos de objetos compatíveis, indicados pela coluna `relkind` em `pg_class`.

**Orientação**

A solução mais eficaz para esse problema depende da configuração da instância específica do Amazon RDS e do tipo de dados afetados pela página inconsistente.

**Se o tipo de objeto for um índice:**

É recomendável reconstruir o índice.
+ **Usar a opção `CONCURRENTLY`**: antes da versão 12 do PostgreSQL, a reconstrução de um índice exigia um bloqueio de tabela exclusivo, restringindo o acesso à tabela. Com a versão 12 e posteriores do PostgreSQL, a opção `CONCURRENTLY` permite o bloqueio em nível de linha, melhorando significativamente a disponibilidade da tabela. Este é o comando:

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  Embora `CONCURRENTLY` seja menos disruptivo, pode ser mais lento em tabelas acessadas com frequência. Considere construir o índice durante períodos de baixo tráfego, se possível.

  Para obter mais informações, consulte a documentação [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html) do PostgreSQL.
+ **Usar a opção `INDEX_CLEANUP FALSE`**: se os índices forem grandes e, segundo sua avaliação, exigirem muito tempo para serem concluídos, é possível desbloquear o autovacuum executando um `VACUUM FREEZE` manual ao excluir os índices. Essa funcionalidade está disponível na versão 12 e versões posteriores do PostgreSQL. 

  Ignorar os índices permitirá que você pule o processo de limpeza do índice inconsistente e mitigue o problema de conclusão. No entanto, isso não resolverá o problema subjacente da página inválida. Para abordar e resolver totalmente o problema da página inválida, ainda será necessário reconstruir o índice.

**Se o tipo de objeto for uma visão materializada:**

Se ocorrer um erro de página inválida em uma visão materializada, faça login no banco de dados afetado e atualize-a para resolver a página inválida:

Atualize a visão materializada.

```
REFRESH MATERIALIZED VIEW schema_name.materialized_view_name;
```

Se a atualização falhar, tente recriar:

```
DROP MATERIALIZED VIEW schema_name.materialized_view_name;
CREATE MATERIALIZED VIEW schema_name.materialized_view_name AS query;
```

Atualizar ou recriar a visão materializada a restaura sem afetar os dados da tabela subjacente.

**Para todos os outros tipos de objetos:**

Para todos os outros tipos de objetos, entre em contato com o AWS Support.

## Inconsistência do índice
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

Um índice logicamente inconsistente pode impedir que o autovacuum progrida. Os seguintes erros ou erros semelhantes são registrados em log durante a fase de limpeza do índice ou quando o índice é acessado por instruções SQL.

```
ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
```

```
ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX
CONTEXT:  while vacuuming index index_name of relation schema.table
```

**Orientação**

Reconstrua o índice ou pule índices usando `INDEX_CLEANUP` no manual `VACUUM FREEZE`. Para obter informações sobre como reconstruir o índice, consulte [Se o tipo de objeto for um índice](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages).
+ **Usar a opção CONCURRENTLY**: antes da versão 12 do PostgreSQL, a reconstrução de um índice exigia um bloqueio de tabela exclusivo, restringindo o acesso à tabela. Com a versão 12 e posteriores do PostgreSQL, a opção CONCURRENTLY permite o bloqueio em nível de linha, melhorando significativamente a disponibilidade da tabela. Este é o comando:

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  Embora CONCURRENTLY seja menos disruptivo, pode ser mais lento em tabelas acessadas com frequência. Considere construir o índice durante períodos de baixo tráfego, se possível. Para ter mais informações, consulte a documentação [REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html) do *PostgreSQL*.
+ **Usar a opção INDEX\$1CLEANUP FALSE**: se os índices forem grandes e, segundo sua avaliação, exigirem muito tempo para serem concluídos, é possível desbloquear o autovacuum executando um VACUUM FREEZE manual ao excluir os índices. Essa funcionalidade está disponível na versão 12 e versões posteriores do PostgreSQL.

  Ignorar os índices permitirá que você pule o processo de limpeza do índice inconsistente e mitigue o problema de conclusão. No entanto, isso não resolverá o problema subjacente da página inválida. Para abordar e resolver totalmente o problema da página inválida, ainda será necessário reconstruir o índice.

## Taxa de transação excepcionalmente alta
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

No PostgreSQL, altas taxas de transação podem afetar significativamente o desempenho do autovacuum, levando a uma limpeza mais lenta das tuplas inativas e ao aumento do risco de conclusão do ID da transação. É possível monitorar a taxa de transação medindo a diferença em `max(age(datfrozenxid))` entre dois períodos, normalmente por segundo. Além disso, é possível usar as métricas de contador do Insights de Performance do RDS a seguir para medir a taxa de transação (a soma de xact\$1commit e xact\$1rollback), que é o número total de transações.


|  Contador  |  Type  |  Unidade  |  Métrica  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  Transações  |  Confirmações por segundo  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  Transações  |  Reversões por segundo  |  db.Transactions.xact\$1rollback  | 

Um aumento rápido indica uma alta carga de transações, que pode sobrecarregar o autovacuum, causando sobrecarga, contenção de bloqueios e possíveis problemas de desempenho. Isso pode impactar negativamente o processo de autovacuum de duas maneiras:
+ **Atividade da tabela:** a tabela específica que está sendo limpa pode estar passando por um alto volume de transações, causando atrasos.
+ **Recursos do sistema:** o sistema geral pode estar sobrecarregado, dificultando que o autovacuum acesse os recursos necessários para funcionar com eficiência.

Considere as seguintes estratégias para permitir que o autovacuum opere com mais eficiência e acompanhe suas tarefas:

1. Reduza a taxa de transação, se possível. Considere agrupar transações semelhantes sempre que possível.

1. Defina tabelas atualizadas com frequência com a operação `VACUUM FREEZE` manual noturna, semanal ou quinzenal durante horários de baixo movimento. 

1. Considere aumentar a escala verticalmente da classe de instância para alocar mais recursos do sistema para lidar com o alto volume de transações e o autovacuum.

# Resolver problemas de desempenho de limpeza no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance"></a>

Esta seção discute os fatores que geralmente contribuem para um desempenho mais lento de limpeza e como resolvê-los.

**Topics**
+ [Limpeza em índices grandes](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes)
+ [Muitas tabelas ou bancos de dados para limpar](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables)
+ [A limpeza agressiva (para evitar conclusão) está em execução](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

## Limpeza em índices grandes
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes"></a>

O VACUUM opera em fases sequenciais: inicialização, verificação do heap, índice e limpeza do heap, limpeza de índices, truncamento de heap e limpeza final. Durante a verificação do heap, o processo remove, desfragmenta e congela páginas. Depois que o heap é verificado, o VACUUM limpa os índices, devolve páginas vazias ao sistema operacional e realiza tarefas finais de limpeza, como limpar o mapa de espaço livre e atualizar as estatísticas.

A limpeza de índice pode exigir várias passagens quando `maintenance_work_mem` (ou `autovacuum_work_mem`) é insuficiente para processar o índice. No PostgreSQL 16 e anterior, um limite de memória de 1 GB para armazenar IDs de tuplas mortas geralmente forçava várias passagens em índices grandes. O PostgreSQL 17 introduz o `TidStore`, que aloca memória dinamicamente em vez de usar uma matriz de alocação única. Isso remove a restrição de 1 GB, usa a memória com maior eficiência e reduz a necessidade de várias verificações para cada índice.

Índices grandes ainda podem exigir várias passagens no PostgreSQL 17 se a memória disponível não for suficiente para o processamento completo do índice de uma só vez. Normalmente, os índices maiores contêm mais tuplas mortas que exigem várias passagens.

**Detectar operações de limpeza lentas**

A função `postgres_get_av_diag()` pode detectar quando a execução de operações de limpeza está lenta devido a memória insuficiente. Para ter mais informações sobre essa função, consulte [Instalar ferramentas de monitoramento e diagnóstico de autovacuum no RDS para PostgreSQL](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md).

A função `postgres_get_av_diag()` emite os avisos a seguir quando a memória disponível não é suficiente para concluir a limpeza do índice em uma única passagem.

**`rds_tools` 1.8**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).
```

**`rds_tools` 1.9**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see 
        [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)
        .
```

**nota**  
A função `postgres_get_av_diag()` depende do `pg_stat_all_tables.n_dead_tup` para estimar a quantidade de memória necessária para a limpeza do índice.

Quando a função `postgres_get_av_diag()` identificar uma operação de limpeza lenta que requer várias verificações do índice devido a `autovacuum_work_mem` insuficiente, ela gerará a seguinte mensagem:

```
NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html).
```

**Orientação**

Você pode aplicar as soluções alternativas a seguir usando o `VACUUM FREEZE` manual para acelerar o congelamento da tabela.

**Aumentar a memória para limpeza**

Conforme sugerido pela função `postgres_get_av_diag()`, é recomendável aumentar o parâmetro `autovacuum_work_mem` para lidar com possíveis restrições de memória no nível da instância. Embora `autovacuum_work_mem` seja um parâmetro dinâmico, é importante observar que, para que a nova configuração de memória entre em vigor, o daemon autovacuum precisa reiniciar seus processos. Para fazer isso:

1. Confirme se a nova configuração está em vigor.

1. Encerre os processos que estão executando o autovacuum.

Essa abordagem garante que a alocação de memória ajustada seja aplicada às novas operações do autovacuum.

Para obter resultados mais imediatos, considere realizar manualmente uma operação `VACUUM FREEZE` com uma configuração `maintenance_work_mem` maior em sua sessão:

```
SET maintenance_work_mem TO '1GB';
VACUUM FREEZE VERBOSE table_name;
```

Se você estiver usando o Amazon RDS e notar que precisa de memória adicional para oferecer suporte a valores mais altos para `maintenance_work_mem` ou `autovacuum_work_mem`, considere fazer upgrade para uma classe de instância com mais memória. Isso pode fornecer os recursos necessários para aprimorar as operações de limpeza manuais e automáticas, levando a um melhor desempenho geral da limpeza e do banco de dados.

**Desativar INDEX\$1CLEANUP**

O `VACUUM` manual no PostgreSQL versão 12 e posteriores permite pular a fase de limpeza do índice, enquanto o autovacuum de emergência no PostgreSQL versão 14 e posteriores faz isso automaticamente com base no parâmetro [https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE).

**Atenção**  
Pular a etapa de limpeza do índice pode causar inchaço no índice e afetar negativamente o desempenho da consulta. Para mitigar isso, considere reindexar ou fazer limpeza nos índices afetados durante uma janela de manutenção.

Para obter orientação adicional sobre como lidar com índices grandes, consulte a documentação em [Gerenciar o autovacuum com grandes índices](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md).

**Limpeza paralelo de índices**

Desde o PostgreSQL 13, os índices podem ser limpos em paralelo por padrão usando o `VACUUM` manual, com um processo de operação de limpeza atribuído a cada índice. No entanto, para que o PostgreSQL determine se uma operação de limpeza se qualifica para execução paralela, critérios específicos devem ser atendidos:
+ Deve haver pelo menos dois índices.
+ O parâmetro `max_parallel_maintenance_workers` deve ser definido como no mínimo 2.
+ O tamanho do índice deve exceder o limite `min_parallel_index_scan_size`, que por padrão é 512 KB.

É possível ajustar a configuração `max_parallel_maintenance_workers` com base no número de vCPUs disponíveis na sua instância do Amazon RDS e no número de índices na tabela para otimizar o tempo de resposta da limpeza.

Para obter mais informações, consulte [Parallel vacuuming in Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL](https://aws.amazon.com/blogs/database/parallel-vacuuming-in-amazon-rds-for-postgresql-and-amazon-aurora-postgresql/).

## Muitas tabelas ou bancos de dados para limpar
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables"></a>

Conforme mencionado na documentação [The Autovacuum Daemon](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM') do PostgreSQL, o daemon autovacuum é executado por meio de vários processos. Isso inclui um inicializador persistente de autovacuum, responsável por iniciar os processos de trabalho de autovacuum para cada banco de dados do sistema. O inicializador programa esses trabalhadores para iniciarem aproximadamente a cada `autovacuum_naptime` segundos por banco de dados.

Com 'N' bancos de dados, um novo trabalhador começa aproximadamente a cada [`autovacuum_naptime`/N segundos]. No entanto, o número total de trabalhadores simultâneos é limitado pela configuração `autovacuum_max_workers`. Se o número de bancos de dados ou tabelas que precisam ser limpos exceder esse limite, o próximo banco de dados ou tabela será processado assim que um trabalhador estiver disponível.

Quando muitas tabelas ou bancos de dados grandes precisam ser limpos simultaneamente, todos os trabalhadores de autovacuum disponíveis podem ficar ocupados por um longo período, atrasando a manutenção em outras tabelas e bancos de dados. Em ambientes com altas taxas de transação, esse gargalo pode aumentar rapidamente e potencialmente levar a problemas de conclusão de limpeza em sua instância do Amazon RDS.

Quando o `postgres_get_av_diag()` detecta um grande número de tabelas ou bancos de dados, ele fornece a seguinte recomendação:

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.
```

**Orientação**

**Aumentar autovacuum\$1max\$1workers**

Para agilizar a limpeza, recomendamos ajustar o parâmetro `autovacuum_max_workers` para permitir mais trabalhadores simultâneos de autovacuum. Se os gargalos de desempenho persistirem, considere aumentar a escala verticalmente de sua instância do Amazon RDS para uma classe com mais vCPUs, o que pode melhorar ainda mais as capacidades de processamento paralelo.

## A limpeza agressiva (para evitar conclusão) está em execução
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum"></a>

A idade do banco de dados (MaximumUsedTransactionIDs) no PostgreSQL só diminui quando uma limpeza agressiva (para evitar conclusão) é concluída com sucesso. Até que essa limpeza termine, a idade continuará aumentando dependendo da taxa de transação.

A função `postgres_get_av_diag()` gera o seguinte `NOTICE` quando detecta uma limpeza agressiva. No entanto, ela só aciona essa saída depois que a limpeza estiver ativa por pelo menos dois minutos.

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```

Consulte [When an aggressive vacuum is already running](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md) para obter mais informações sobre a limpeza agressiva.

Use a seguinte consulta para verificar se uma limpeza agressiva está em andamento:

```
SELECT
    a.xact_start AS start_time,
    v.datname "database",
    a.query,
    a.wait_event,
    v.pid,
    v.phase,
    v.relid::regclass,
    pg_size_pretty(pg_relation_size(v.relid)) AS heap_size,
    (
        SELECT
            string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ')
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS index_sizes,
    trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct,
    v.index_vacuum_count || '/' || (
        SELECT
            count(*)
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS step2_vacuum_indexes,
    trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct,
    age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar
FROM
    pg_stat_activity a
    INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;
```

É possível determinar se é uma limpeza agressiva (para evitar conclusão) verificando a coluna de consulta na saída. A frase "para evitar conclusão" indica que se trata de uma limpeza agressiva.

```
query                  | autovacuum: VACUUM public.t3 (to prevent wraparound)
```

Por exemplo, suponha que você tenha um bloqueador com idade de transação de 1 bilhão e uma tabela exigindo uma limpeza agressiva para evitar conclusão na mesma idade da transação. Além disso, há outro bloqueador com idade de transação de 750 milhões. Depois de eliminar o bloqueador com idade de transação de 1 bilhão, a idade de transação não cairá imediatamente para 750 milhões. Ela permanecerá alta até que a tabela que precise da limpeza agressiva ou qualquer transação com idade superior a 750 milhões seja concluída. Durante esse período, a idade das transações do cluster do PostgreSQL continuará aumentando. Quando o processo de limpeza for concluído, a idade da transação cairá para 750 milhões, mas começará a aumentar novamente até que a limpeza adicional seja concluída. Esse ciclo continuará enquanto essas condições persistirem, até que a idade da transação caia para o nível configurado na instância do Amazon RDS, especificado por `autovacuum_freeze_max_age`.

# Explicação das mensagens de AVISO no RDS para PostgreSQL
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE"></a>

 A função `postgres_get_av_diag()` fornece as seguintes mensagens de AVISO:

**Quando a idade ainda não atingiu o limite de monitoramento**  
O limite de monitoramento de `postgres_get_av_diag()` para identificar bloqueadores é de 500 milhões de transações por padrão. Se `postgres_get_av_diag()` gerar o seguinte AVISO, isso indica que a idade da transação ainda não atingiu esse limite.  

```
NOTICE: postgres_get_av_diag() checks for blockers that prevent aggressive vacuums only, it does so only after exceeding dvb_threshold which is 500,000,000 and age of this PostgreSQL cluster is currently at 2.
```

**Não conectado ao banco de dados com o ID de transação mais antigo**  
A função `postgres_get_av_diag()` fornece a saída mais precisa quando conectada ao banco de dados com a idade de ID de transação mais antiga. O banco de dados com a idade de ID de transação mais antiga informada por `postgres_get_av_diag()` será diferente de “my\$1database” no seu caso. Se você não estiver conectado ao banco de dados correto, o seguinte AVISO será gerado:  

```
NOTICE: You are not connected to the database with the age of oldest transaction ID. Connect to my_database database and run postgres_get_av_diag() for accurate reporting.
```
Conectar-se ao banco de dados com a idade de transação mais antiga é importante pelos seguintes motivos:  
+ **Identificação de bloqueadores de tabelas temporárias:** como os metadados das tabelas temporárias são específicos de cada banco de dados, eles geralmente são encontrados no banco de dados em que foram criados. No entanto, se uma tabela temporária for o principal bloqueador e residir no banco de dados com a transação mais antiga, isso pode ser enganoso. A conexão com o banco de dados correto garante a identificação precisa do bloqueador de tabelas temporárias.
+ **Diagnóstico de vacuums lentos:** os metadados do índice e as informações de contagem de tabelas são específicos do banco de dados e necessários para diagnosticar problemas de vacuum lento.

**O banco de dados com a transação mais antiga por idade está em um banco de dados rdsadmin ou template0**  
Em alguns casos, os bancos de dados `rdsadmin` ou `template0` podem ser identificados como o banco de dados com a idade de ID de transação mais antiga. Se isso acontecer, `postgres_get_av_diag()` emitirá o seguinte AVISO:  

```
NOTICE: The database with the age of oldest transaction ID is rdsadmin or template0, reach out to support if the reported blocker is in rdsadmin or template0.
```
Verifique se o bloqueador listado não é originário de nenhum desses dois bancos de dados. Se for relatado que o bloqueador está presente em `rdsadmin` ou `template0`, entre em contato com o suporte, pois esses bancos de dados não são acessíveis ao usuário e exigem intervenção.  
É altamente improvável que o banco de dados `rdsadmin` ou `template0` contenha um bloqueador principal.

**Quando um vacuum agressivo já está em execução**  
A função `postgres_get_av_diag()` foi projetada para relatar quando um processo de vacuum agressivo está em execução, mas ela só vai acionar essa saída depois que o vacuum estiver ativo por pelo menos 1 minuto. Esse atraso intencional ajuda a reduzir as chances de falsos positivos. Ao esperar, a função garante que somente vacuums efetivos e significativos sejam relatados, levando a um monitoramento mais preciso e confiável da atividade do vacuum.  
A função `postgres_get_av_diag()` gera o seguinte AVISO quando detecta um ou mais vacuums agressivos em andamento.   

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```
Conforme indicado no AVISO, continue monitorando o desempenho do vacuum. Para obter mais informações sobre o vacuum agressivo, consulte [A limpeza agressiva (para evitar conclusão) está em execução](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

**Quando o autovacuum está desativado**  
A função `postgres_get_av_diag()` vai gerar o seguinte AVISO se o autovacuum estiver desativado na instância de banco de dados:  

```
NOTICE: Autovacuum is OFF, we strongly recommend to enable it, no restart is necessary.
```
O autovacuum é um recurso essencial da instância de banco de dados do RDS para PostgreSQL que garante uma operação tranquila do banco de dados. Ele remove automaticamente as versões antigas das linhas, recupera espaço de armazenamento e evita o inchaço das tabelas, ajudando a manter as tabelas e os índices eficientes para um desempenho ideal. Além disso, ele protege contra o wraparound de ID de transação, que pode interromper transações na instância do Amazon RDS. A desativação do autovacuum pode levar a quedas de longo prazo no desempenho e na estabilidade do banco de dados. Sugerimos que você o mantenha ativado sempre. Para ter mais informações, consulte [Understanding autovacuum in RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/).  
O desligamento do autovacuum não impede os vacuums agressivos. Estes ainda ocorrerão quando as tabelas atingirem o limite de `autovacuum_freeze_max_age`. 

**O número de transações restantes é criticamente baixo**  
A função `postgres_get_av_diag()` gera o seguinte AVISO quando um vacuum wraparound é iminente. Este AVISO é emitido quando a instância do Amazon RDS está a 100 milhões de transações de possivelmente rejeitar novas transações.  

```
WARNING: Number of transactions remaining is critically low, resolve issues with autovacuum or perform manual VACUUM FREEZE before your instance stops accepting transactions.
```
Sua ação imediata é necessária para evitar tempo de inatividade do banco de dados. Você deve monitorar de perto suas operações de vacuum e considerar iniciar manualmente um `VACUUM FREEZE` no banco de dados afetado para evitar falhas nas transações.