postgresql postgres checkpoint checkpointer bgwriter

Checkpointer e Background Writer

Hierarquia de memória

Na ciência da computação, a hierarquia de memória é uma representação dos vários meios de armazenamento em função da velocidade de acesso, custo, volume disponível e volatilidade. É desenhada como uma pirâmide, com memórias mais rápidas no topo, memória principal no centro e memórias secundárias e terciárias na base.

  1. As camadas superiores são registradores e cache de processador (L1I, L1D, L2…), que são relevantes para o desenvolvimento do PostgreSQL mas não necessariamente para a administração dele.
  2. A seguir vem a camada de memória principal (RAM), onde os processos do PostgreSQL residem enquanto estão em execução. Ela também é usada para buffers e cache de disco, cuja gestão é o assunto central deste tópico.
  3. Abaixo dela está a camada de memória secundária (ou de disco ou de storage), normalmente apoiada sobre SSDs e HDDs, possivelmente em tiering. Nela, os diretórios de dados e de tablespaces armazenam os objetos (tabelas, índices…), representados como séries de blocos (de 8kB por padrão no PostgreSQL).
  4. Por fim, o armazenamento terciário contém dados de grande volume e baixo acesso, como backups, arquivamento de WAL e possivelmente dumps. Portanto, costuma ser feito sobre fitas e outras tecnologias de baixo custo e longa duração.
                                        ┌───┐
                                      ┌─┴─┬─┴─┐
                                (1)   │L1I│L1D│
                                    ┌─┴───┴───┴─┐
                                    │    L2     │
                                  ┌─┴───────────┴─┐
                                  │      L3       │
                              ┌═─═┴═─═─═─═─═─═─═─═┴═─═┐
                              ║         RAM           ║
                              │                       │
                              ║    ╔════════════╗     ║
                         (2)  │    ║ PostgreSQL ║     │
                              ║    ╚════════════╝     ║
                              │                       │
                              ║                       ║
                    ┌━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━┐
                    ┃                   Disco                   ┃
                    │                                           │
                    ┃     Tabelas e Índices            WAL      ┃
                    │  ┏━┓┏━┓┏━┓┏━┓┏━┓┏━┓┏━┓┏━┓    ┌─────────┐  │
                    ┃  ┣━┫┣━┫┗━┛┣━┫┣━┫┣━┫┣━┫┣━┫    │┏━┓┏━┓┏━┓│  ┃
               (3)  │  ┣━┫┗━┛┏━┓┣━┫┣━┫┣━┫┣━┫┗━┛    │┗━┛┗━┛┗━┛│  │
                    ┃  ┣━┫┏━┓┗━┛┣━┫┗━┛┣━┫┗━┛┏━┓    └┤/…00012├┘  ┃
                    │  ┣━┫┣━┫┏━┓┣━┫┏━┓┗━┛┏━┓┗━┛    ┌─────────┐  │
                    ┃  ┣━┫┣━┫┣━┫┗━┛┣━┫┏━┓┗━┛┏━┓    │┏━┓┏━┓┏━┓│  ┃
                    │  ┣━┫┣━┫┣━┫┏━┓┣━┫┣━┫┏━┓┣━┫    │┗━┛┗━┛┗━┛│  │
                    ┃  ┗━┛┗━┛┗━┛┗━┛┗━┛┗━┛┗━┛┗━┛    └┤/…00013├┘  ┃
    ┏━━━━━━━━━━━━━━━┴━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┴━━━━━━━━━━━━━━━┓
    ┃                           Arquivamento contínuo                           ┃
    ┃  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐  ┃
    ┃  │┏━┓┏━┓┏━┓│ │┏━┓┏━┓┏━┓│ │┏━┓┏━┓┏━┓│ │┏━┓┏━┓┏━┓│ │┏━┓┏━┓┏━┓│ │┏━┓┏━┓┏━┓│  ┃
    ┃ →│┗━┛┗━┛┗━┛│→│┗━┛┗━┛┗━┛│→│┗━┛┗━┛┗━┛│→│┗━┛┗━┛┗━┛│→│┗━┛┗━┛┗━┛│→│┗━┛┗━┛┗━┛│→ ┃
    ┃  └┤/…00007├┘ └┤/…00008├┘ └┤/…00009├┘ └┤/…00010├┘ └┤/…00011├┘ └┤/…00012├┘  ┃
    ┠──────↑────────↑──────↑────────↑───────────↑────────↑─────────↑────────↑───┨
(4) ┃                                  Backups                                  ┃
    ┃  ╔═══════════════╗ ╔═══════════════╗ ╔═══════════════╗ ╔═══════════════╗  ┃
    ┃  ╠═════╗   ╔═════╣ ╠═════╗   ╔═════╣ ╠═════╗   ╔═════╣ ╠═════╗   ╔═════╣  ┃
    ┃  ║     ║   ║     ║ ║     ║   ║     ║ ║     ║   ║     ║ ║     ║   ║     ║  ┃
    ┃……╠═════╝   ╚═════╣…╠═════╝   ╚═════╣…╠═════╝   ╚═════╣…╠═════╝   ╚═════╣……┃
    ┃  ╠══════════╗    ║ ╠══════════╗    ║ ╠══════════╗    ║ ╠══════════╗    ║  ┃
    ┃  ║          ║    ║ ║          ║    ║ ║          ║    ║ ║          ║    ║  ┃
    ┃  ╚══════════╩════╝ ╚══════════╩════╝ ╚══════════╩════╝ ╚══════════╩════╝  ┃
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Memória consumida pelo PostgreSQL

Dentro da memória principal, o PostgreSQL ocupa algumas áreas distintas. Além dele, outros processos em execução na mesma máquina também usam memória, o que pode diminuir a quantidade de memória disponível direta ou indiretamente para o PostgreSQL. Adicionalmente, o próprio kernel toma proveito de toda memória não usada pelos processos para agilizar operações em disco através de estratégias como readahead, cache e buffers.

  1. Se a aplicação reside na mesma máquina do PostgreSQL, ela compete pela memória e pode causar problemas de contenção, portanto é desejável que ela esteja em máquinas distintas.
  2. O postmaster, processo principal do PostgreSQL, é responsável por alocar uma região de memória única e compartilhada entre todos os processos, configurada por shared_buffers.
  3. Essa região é usada para comunicação inter-processos, para páginas de cache de leitura de disco e para páginas de buffers de escrita em disco.
  4. Alguns processos do PostgreSQL não precisam de memória adicional, operando quase que completamente sobre a memória compartilhada.
  5. Outros processos podem precisar de memória extra (configurada por autovacuum_work_mem, maintenance_work_mem, entre outras).
  6. Conexões externas executando comandos utilitários de manutenção, como o VACUUM, podem alocar memória específica para essas operações.
  7. Conexões externas executando comandos simples podem não alocar memória ou alocar poucas vezes o valor de work_mem.
  8. Conexões externas executando comandos complexos podem alocar várias vezes o valor de work_mem.
  9. Como o PostgreSQL opera sobre os blocos de disco através das primitivas de I/O com buffers do sistema operacional, os blocos de disco (A), (B), (C) são mantidos tanto em disco, quanto em page cache do kernel e em shared_buffers para uso dos processos do PostgreSQL. O WAL também recebe cópias deles à medida que as mudanças são geradas pelas transações.
 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                 (2)╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║        (3)         ║                (4)╔╡checkpointer╞╗  │
  (1)│││   VACUUM ║  ║ ╔══════════════════════╗║(6)    ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃(C)┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││           ║  ╔╡postgres╞═══╗                   ║    ┃(A)┃  ┃   ┃    ╠══════════════════════╩═══════════╝  ║
     ││    SELECT │  ║ ╔══════════╗║(7)                ║    ┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │            │  ║ ╚══════════╝║                   ║    ┃   ┃  ┃(B)┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║    (5)║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║(8)          ║    ┃   ┃  ┃   ┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║              ┃   ┃ ┃(A)┃ ┃   ┃ ┃(C)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║           (9)┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃(B)┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃(C)┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(A)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃(A)┃┃   ┃┃(B)┃┃   ┃││┃(C)┃┃(B)┃┃   ┃┃(A)┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃(B)┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓             ↑                                                           ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃             └─────────────────┤pg_control│                              │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

Alguns pontos de atenção:

Buffers de leitura e escrita em disco

Fluxo de leitura

  1. Aplicação envia consulta ao backend do PostgreSQL e aguarda resposta.
  2. O backend do PostgreSQL executa consulta que precisa de dados (A). Esses dados são buscados nas páginas (cópias em memória principal dos blocos de disco) presentes em shared_buffers.
  3. Se uma página não está presente em shared_buffers, o PostgreSQL requisita uma cópia de page cache do sistema operacional. Mas se estiver presente, o backend a usa diretamente.
  4. Se a página requisitada não está presente em page cache do sistema operacional, o bloco é lido do disco. Mas se estiver presente, o sistema operacional faz a cópia para uma posição livre em shared_buffers.
  5. Blocos de disco são as unidades básicas de operações de I/O. O tamanho padrão no bloco para o PostgreSQL é 8kB (não configurável, exceto em tempo de compilação). Cada objeto (tabela, índice…) pode ser representado por zero, um ou mais arquivos no sistema de arquivos; e cada arquivo é composto por uma sequência de zero, um ou mais blocos (até um limite de 1GB por arquivo).
 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                    ╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║                    ║                   ╔╡checkpointer╞╗  │
     │││   VACUUM ║  ║ ╔══════════════════════╗║       ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃   ┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││       (1) ║  ╔╡postgres╞═══╗                   ║    ┃(?)┃  ┃   ┃    ╠══════════════════════╩═══════════╝  ║
     ││    SELECT │  ║ ╔══════════╗║(2)                ║ (3)┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │            │  ║ ╚══════════╝║                   ║    ┃   ┃  ┃   ┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║       ║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║             ║    ┃   ┃  ┃   ┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║           (4)┃   ┃ ┃(?)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║              ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛(5)                                                                      ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(A)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃││┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃   ┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓             ↑                                                           ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃             └─────────────────┤pg_control│                              │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

Fluxo de escrita

  1. Aplicação envia um comando de escrita ao backend do PostgreSQL e aguarda resposta. Se a página não esiver em shared_buffers, o fluxo de leitura é executado neste momento antes de continuar.
  2. O backend do PostgreSQL executa a operação sobre a página presente em shared_buffers, alterando o conteúdo original (A) para o novo conteúdo (X). As possíveis alterações estão descritas em MVCC.
  3. Obs.: A página é alterada no mesmo lugar, sem ocupar mais espaço, mas o diagrama está mostrando (A) indo para (X) para facilitar a leitura.
  4. O walwriter registra a página alterada (X) no WAL.
  5. A aplicação eventualmente finaliza a transação com um COMMIT, que é marcado diretamente no WAL (exceto quando synchronous_commit estiver desabilitado).
 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                    ╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║                    ║                   ╔╡checkpointer╞╗  │
     │││   VACUUM ║  ║ ╔══════════════════════╗║       ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃   ┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││       (1) ║  ╔╡postgres╞═══╗                   ║    ┃(A)┃→→┃(X)┃    ╠══════════════════════╩═══════════╝  ║
     ││    UPDATE │  ║ ╔══════════╗║                   ║ (3)┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │     COMMIT │  ║ ╚══════════╝║(2)                ║    ┃   ┃  ┃   ┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║       ║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║             ║    ┃   ┃  ┃   ┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║              ┃   ┃ ┃(A)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║              ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛                 (4)  (5)                                                ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(A)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃(X)┃┃COM┃┃   ┃┃   ┃││┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃   ┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓             ↑                                                           ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃             └─────────────────┤pg_control│                              │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

Ao final, shared_buffers contém apenas a versão nova (X) da página, que é usada para atender novas leituras e escritas em memória. O WAL também contém essa versão, e pode ser usado para replicação e recuperação de falhas. Mas a tabela em disco e page cache podem conter a versão anterior (A) por tempo indeterminado.

Fluxo de checkpoint

O fluxo de escrita normal tenta fazer todas as operações em memória principal, transformando as operações em escritas sequenciais e dependendo de confirmação (fsync) apenas para retornar a garantia de transação em disco (Durabilidade).

Mas isso faz com que o estado nas tabelas (indicado pelo ponteiro de LSN de consistência do pg_control) e o estado mais recente escrito no WAL sejam diferentes. Essa defasagem do pg_control causa um maior tempo de recuperação de desastres e de parada do serviço, além de outros pontos.

O checkpointer é o processo de background responsável por executar o checkpoint, que é a ação que garante que as escritas confirmadas para a aplicação sejam eventualmente propagadas para os objetos e, então, avança o ponteiro do pg_control.

O checkpoint é acionado periodicamente em função de checkpoint_timeout, quando o espaço ocupado pelo WAL em pg_wal está próximo do máximo max_wal_size ou quando o comando CHECKPOINT é executado por um superusuário.

1 write

O primeiro passo do checkpoint é enviar as páginas de buffers sujos (ou seja, que tiveram alterações desde que foram lidos do disco) para que o sistema operacional faça a escrita (write) nos respectivos blocos disco. Essa escrita vai ser feita quando o sistema operacional puder.

Para evitar sobrecarregar o I/O, as escritas são distribuídas ao longo de um tempo proporcional ao checkpoint_timeout, configurável por checkpoint_completion_target. Por exemplo, se temos checkpoint_timeout = 10min e checkpoint_completion_target = 0.8, então as escritas são dispersadas ao longo de 8min (8min = 10min * 0.8).

Por exemplo, as páginas (X), (Y) e (Z) foram enviadas para page cache e o sistema operacional já conseguiu escrever duas (X) e (Y) em disco:

 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                    ╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║                    ║                   ╔╡checkpointer╞╗  │
     │││   VACUUM ║  ║ ╔══════════════════════╗║       ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃(Z)┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││       (1) ║  ╔╡postgres╞═══╗                   ║    ┃(X)┃  ┃   ┃    ╠══════════════════════╩═══════════╝  ║
     ││    UPDATE │  ║ ╔══════════╗║                   ║ (3)┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │            │  ║ ╚══════════╝║(2)                ║    ┃   ┃  ┃   ┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║       ║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║             ║    ┃   ┃  ┃(Y)┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║              ┃   ┃ ┃(X)┃ ┃   ┃ ┃(Z)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║              ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃(Y)┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃(C)┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(X)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃(X)┃┃COM┃┃(Y)┃┃COM┃││┃(Z)┃┃(Y)┃┃COM┃┃(X)┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃(Y)┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓             ↑                                                           ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃             └─────────────────┤pg_control│                              │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

2 sync

O segundo passo é pedir a confirmação (sync) ao sistema operacional das escritas enviadas anteriormente. As escritas que não tiverem sido feitas até este momento serão feitas. E o sistema operacional irá pedir a confirmação de todas as escritas para a camada inferior (controlador de RAID, storage etc).

 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                    ╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║                    ║                   ╔╡checkpointer╞╗  │
     │││   VACUUM ║  ║ ╔══════════════════════╗║       ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃(Z)┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││       (1) ║  ╔╡postgres╞═══╗                   ║    ┃(X)┃  ┃   ┃    ╠══════════════════════╩═══════════╝  ║
     ││    UPDATE │  ║ ╔══════════╗║                   ║ (3)┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │            │  ║ ╚══════════╝║(2)                ║    ┃   ┃  ┃   ┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║       ║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║             ║    ┃   ┃  ┃(Y)┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║              ┃   ┃ ┃(X)┃ ┃   ┃ ┃(Z)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║              ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃(Y)┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃(Z)┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(X)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃(X)┃┃COM┃┃(Y)┃┃COM┃││┃(Z)┃┃(Y)┃┃COM┃┃(X)┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃(Y)┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓             ↑                                                           ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃             └─────────────────┤pg_control│                              │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

3 pg_control

Por fim, o ponteiro de consistência contido em pg_control é avançado para o novo estado consistente alcançado. A partir desse momento, segmentos de WAL do passado podem ser reciclados.

 ╔═══════════╗    ┌═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═─═┐
 ║ Aplicação ║    ║                                    ╔══╡shared_buffers╞══╗                                     ║
 ╚═══════════╝    │  ╔╡postgres╞═══════════════╗       ║                    ║                   ╔╡checkpointer╞╗  │
     │││   VACUUM ║  ║ ╔══════════════════════╗║       ║    ┏━━━┓  ┏━━━┓    ╠═══════════════════╩══════════════╝  ║
     ││└──────────│─→║→║ maintenance_work_mem ║╠═══════╣    ┃   ┃  ┃(Z)┃    ║              ╔╡background writer╞╗  │
     ││           ║  ║ ╚══════════════════════╝║       ║    ┗━━━┛  ┗━━━┛    ╠══════════════╩═══════════════════╝  ║
     ││           │  ╚═════════════════════════╝       ║    ┏━━━┓  ┏━━━┓    ║                      ╔╡walwriter╞╗  │
     ││       (1) ║  ╔╡postgres╞═══╗                   ║    ┃(X)┃  ┃   ┃    ╠══════════════════════╩═══════════╝  ║
     ││    UPDATE │  ║ ╔══════════╗║                   ║ (3)┗━━━┛  ┗━━━┛    ║            ╔╡autovacuum launcher╞╗  │
     │└───────────║─→║→║ work_mem ║╠═══════════════════╣    ┏━━━┓  ┏━━━┓    ╠════════════╩═════════════════════╝  ║
     │            │  ║ ╚══════════╝║(2)                ║    ┃   ┃  ┃   ┃    ║       ╔════════════╡autovacuum╞╗ │  │
     │            ║  ╚═════════════╝                   ║    ┗━━━┛  ┗━━━┛    ║       ║╔═════════════════════╗ ║ │  ║
     │            │  ╔╡postgres╞═════════╗             ║    ┏━━━┓  ┏━━━┓    ╠═══════╣║ autovacuum_work_mem ║←║←┘  │
     │     SELECT ║  ║ ╔══════════╗      ║             ║    ┃   ┃  ┃(Y)┃    ║       ║╚═════════════════════╝ ║    ║
     └────────────│─→║→║ work_mem ║╗     ╠═════════════╣    ┗━━━┛  ┗━━━┛    ║       ╚════════════════════════╝    │
                  ║  ║ ╚══════════╝║╗    ║             ╚════════════════════╝                                     ║
                  │  ║  ╚══════════╝║╗   ║                                                                        │
                  ║  ║   ╚══════════╝║╗  ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     ║
                  │  ║    ╚══════════╝║╗ ║              ┃   ┃ ┃(X)┃ ┃   ┃ ┃(Z)┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃     │
                  ║  ║     ╚══════════╝║ ║              ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     ║
                  │  ║      ╚══════════╝ ║              ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓ ┏━━━┓     │
                  ║  ╚═══════════════════╝              ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃   ┃ ┃(Y)┃ ┃   ┃ ┃   ┃     ║
                  │                                     ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛ ┗━━━┛     │
                  ║                                                                                               ║
┌━─━─━─━─━─━─━─━─━┴═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═━═┴━─━─━─━─━─━─━─━─━┐
┃   ┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃   ┃┃(Z)┃┃   ┃┃   ┃┃   ┃┃   ┃                                                                         │
┃   ┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┣━━━┫┗━━━┛┣━━━┫┣━━━┫┗━━━┛                                                                         ┃
│   ┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃   ┃┃   ┃┏━━━┓┃   ┃┃(X)┃┏━━━┓          ┌─────────────────────────┐┌─────────────────────────┐         │
┃   ┣━━━┫┣━━━┫┗━━━┛┃   ┃┗━━━┛┣━━━┫┣━━━┫┃   ┃┣━━━┫┣━━━┫┃   ┃          │┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓││┏━━━┓┏━━━┓┏━━━┓┏━━━┓┏━━━┓│         ┃
│   ┃   ┃┃   ┃┏━━━┓┗━━━┛┏━━━┓┃   ┃┃   ┃┣━━━┫┃   ┃┃   ┃┣━━━┫          │┃   ┃┃(X)┃┃COM┃┃(Y)┃┃COM┃││┃(Z)┃┃(Y)┃┃COM┃┃(X)┃┃   ┃│         │
┃   ┣━━━┫┗━━━┛┃   ┃     ┃(Y)┃┣━━━┫┣━━━┫┃   ┃┣━━━┫┗━━━┛┃   ┃          │┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛││┗━━━┛┗━━━┛┗━━━┛┗━━━┛┗━━━┛│         ┃
│   ┃   ┃     ┣━━━┫     ┗━━━┛┃   ┃┃   ┃┣━━━┫┃   ┃┏━━━┓┗━━━┛          └───────┤/…000012├────────┘└───────┤/…000013├────────┘         │
┃   ┗━━━┛     ┃   ┃          ┣━━━┫┗━━━┛┃   ┃┗━━━┛┃   ┃┏━━━┓                                                  ↑                      ┃
│             ┗━━━┛          ┃   ┃     ┗━━━┛     ┗━━━┛┃   ┃                               │pg_control├───────┘                      │
┃                            ┗━━━┛                    ┗━━━┛                                                                         ┃
└━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━─━┘

Fluxo de background writer

Nos fluxos de leitura e escrita, quando um bloco precisa ser buscado do disco e copiado para memória principal, ao menos uma página deve estar disponível em shared_buffers. Caso contrário, se todas as páginas de shared_buffers estiverem ocupadas e sujas (ou seja, com alterações que não foram escritas em disco), então o backend que está fazendo a leitura ou escrita deve primeiro escolher uma página suja e escrevê-la em disco antes de carregar o novo bloco de interesse. Ou seja, no melhor caso a leitura e escrita são feitas em memória principal pois operam sobre shared_buffers, mas no pior caso a resposta de leituras e escritas pode depender da velocidade de escrita aleatória em disco.

O backgroud writer (ou bgwriter) é um processo interno responsável por encontrar páginas sujas de shared_buffers e escrevê-las em disco, liberando espaço para que outros backends possam trabalhar com maior eficiência. O fato de menos páginas serem mantidas sujas em memória significa que o checkpoint pode ser mais barato já que a escrita e confirmação delas pode ter terminado antes; mas isso não acontece em casos que as mesmas páginas são sujas repetidamente.

Quando o bgwriter executa, ele tenta limpar uma quantidade de páginas proporcionais ao número de páginas que foram sujas recentemente, multiplicadas por bwriter_lru_multiplier, mas não mais que bgwriter_lru_maxpages. As páginas escolhidas são aquelas usadas menos recentemente (LRU). Depois de executar ele aguarda o tempo bgwriter_delay até ser acionado novamente.