Буферный кэш и журнал в Postgresql

Буферный кэш и журнал в Postgresql

    Буферный кэш

    Буферный кэш используется для сглаживания скорости работы оперативной памяти и дисков
    Буферный кэш состоит из массива буферов, которые содержат страницы данных и дополнительную информацию ( имя файла, положение страницы в этом файле и др. )
    Размер страницы по умолчанию 8 Кбайт, изменить можно только при сборке
    Любая работа со страницами данных проходит через буферный кэш. Сначала процесс обращается к кэшу. Если в буфере страницы нет, процесс обращается к операционной системе с просьбой прочитать страницу из собственного кэша или диска и добавить ее в буферный кэш
    К странице в буферном кэше можно обращаться повторно без накладных расходов на вызовы ОС
    Если процесс изменил данные на странице, соответствующий буфер становится грязным. Измененная страница подлежит записи на диск, по соображениям производительности запись происходит асинхронно и может откладываться
    Буферный кеш, как и другие структуры общей памяти, защищен блокировками для управления одновременным доступом. Хотя блокировки и реализованы эффективно, доступ к буферному кешу далеко не так быстр, как простое обращение к оперативной памяти. Поэтому в общем случае чем меньше данных читает и изменяет запрос, тем быстрее он будет работать
    Размер буферного кэша при первичной настройке следует устанавливать примерно 1/4 от общего размера оперативной памяти

    Вытеснение редко используемых страниц

    Естественно вся база в кэше не поместится. Его ограничивают доступная оперативная память и возрастающие при увеличении кэша накладные расходы.
    Когда место в буферном кэше заканчивается применяется вытеснение страниц
    Алгоритм вытеснения выбирает в буферном кэше страницу, которая использовалась реже других. Если страница окажется грязной, тогда страница записывается на диск
    В кэше сохраняются только активные страницы, горячие данные
    При достаточном объеме буферного кэша получается существенно сократить количество обращений к ОС
    shared_buffers Значение по умолчанию слишком мало; в любой реальной системе его требуется увеличить сразу после установки сервера (изменение требует перезапуска)
    После перезапуска сервера содержимое буферного кэша сбросится

    postgres=# create database test_wal; CREATE DATABASE postgres=# postgres=# \c test_wal You are now connected to database "test_wal" as user "postgres". test_wal=# test_wal=# CREATE TABLE t(n integer); CREATE TABLE test_wal=# test_wal=# INSERT INTO t SELECT id FROM generate_series(1, 10000) AS id; INSERT 0 10000 test_wal=# test_wal=# --Размер буферного кэша показывает параметр shared_buffers: test_wal=# test_wal=# SHOW shared_buffers; shared_buffers ---------------- 128MB (1 row) test_wal=# test_wal=# --Команда EXPLAIN ANALYZE выполняет запрос, выводит план выполнения и дополнительную информацию:
    test_wal=# test_wal=# EXPLAIN (analyze, buffers, costs off, timing off) test_wal-# SELECT * FROM t; QUERY PLAN ------------------------------------------- Seq Scan on t (actual rows=10000 loops=1) Buffers: shared hit=45 Planning: Buffers: shared hit=4 dirtied=1 Planning Time: 0.176 ms Execution Time: 1.939 ms (6 rows) test_wal=# -- EXPLAIN ANALYZE последовательно читает таблицу test_wal=# -- hit — количество буферов из буфера, в котором нашлись нужные для запроса страницы test_wal=# test_wal=# -- read — количество буферов, в которые пришлось прочитать страницы с диска test_wal=# test_wal=# EXPLAIN (analyze, buffers, costs off, timing off) SELECT * FROM t; QUERY PLAN ------------------------------------------- Seq Scan on t (actual rows=10000 loops=1) Buffers: shared hit=45 Planning Time: 0.071 ms Execution Time: 2.027 ms (4 rows) test_wal=#
    Журнал предзаписи wal

    Журнал предзаписи защищает объекты, работа с которыми ведется в оперативной памяти ( таблицы, индексы, др. )
    При сбое теряются данные из оперативной памяти, не записанные на диск
    Журнал - поток информации о выполняемых действиях, позволяющий повторно выполнить потерянные при сбое операции
    Журнал защищает страницы таблиц, индексов и других объектов
    Журнал не защищает временные и нежурналируемые таблицы
    Наличие буферного кэша увеличивается производительность, но уменьшает надежность
    Запись в журнал должна попасть на диск ( постоянно устройство хранения ) раньше, чем будут записаны изменяемые операцией данные, поэтому журнал называется журнал предзаписи
    Файлы журнала располагаются в каталоге PGDATA/pg_wal
    Восстановление данных из журнала называется восстановлением с воспроизведением или REDO
    Результатом использования WAL является значительное уменьшение количества запросов записи на диск, потому что для гарантии, что транзакция подтверждена, в записи на диск нуждается только файл WAL, а не каждый файл данных, изменённый в результате транзакции
    Логически журнал можно представить в виде непрерывного потока записей. Каждая запись имеет номер, называемый LSN (Log Sequence Number). Это 64-разрядное число — смещение записи в байтах относительно начала журнала.
    Текущую позицию показывает функция pg_current_wal_lsn:

    postgres=# SELECT pg_current_wal_lsn(); pg_current_wal_lsn -------------------- 0/122B5FB8 (1 row) testbase=# UPDATE t SET s = 'test'; UPDATE 1 testbase=# SELECT pg_current_wal_lsn(); pg_current_wal_lsn -------------------- 0/122B61A0 (1 row) -- На файлы можно взглянуть не только средствами файловой системы, но и с помощью функции: testbase=# SELECT * FROM pg_ls_waldir() ORDER BY name LIMIT 10; name | size | modification --------------------------+----------+------------------------ 000000010000000000000012 | 16777216 | 2024-08-25 01:45:56+03 000000010000000000000013 | 16777216 | 2024-08-03 15:39:05+03 000000010000000000000014 | 16777216 | 2024-08-03 15:39:22+03 (3 rows)

    Записи из журнала могут попасть в кэш операционной системы, postgres полагается, что есть вызов операционной системы, который гарантирует, что операционная система не будет держать данные журнала у себя в кэше и будут сразу записаны на диск
    Каждый commit записывает журнальные данные на диск. Соответственно большое количество транзакций будет влиять на производительность
    Поэтому существует асинхронная запись, когда доступ к таблице возвращается сразу после фиксации, а данные из журнала записываются на диск чуть погодя
    Фоновый процесс walwriter через определенное время проверяет наличие журнальных записей и при необходимости синхронизирует их на диск

    h5>Контрольная точка

    Переодический сброс всех грязных буферов на диск гарантирует попадание на диск всех изменений до контрольной точки
    Восстановление при сбое начинается с последней контрольной точки
    Когда сервер запускается после сбоя, он входит в режим восстановления
    Чтобы восстановить согласованность, PostgreSQL читает WAL и после-довательно проигрывает каждую его запись, если соответствующее изменение не попало на диск. Таким образом восстанавливается работа всех транзакций. Транзакции, запись о фиксации которых не успела попасть в журнал, считаются оборванными.
    Объем журнала за время работы сервера мог бы достигнуть гигантских размеров. Хранить его целиком и просматривать при сбое совершенно не реально. Поэтому СУБД периодически выполняет контрольную точку (КТ): принудительно сбрасывает на диск все грязные буферы (включая буферы clog, хранящие состояние транзакций)
    Собственно «точка» — это момент начала записи буферов, которые были грязными на этот момент. Но точка считается выполненной только после того, как все такие буферы записаны. Это гарантирует, что все изменения, сделанные до момента КТ, находятся на диске
    Журнальные записи долгой транзакции будут записываться асинхронно (чтобы освободить буферы WAL). А если при сбросе страницы данных окажется, что соответствующая журнальная запись еще не на диске, она тут же будет записана в синхронном режиме.
    Процесс walwriter - занимается асинхронной записью журнала на диск.
    При синхронном режиме записью журнала занимается тот процесс, который выполняет фиксацию транзакции
    Процесс контрольной точки checkpointer периодечески сбрасывает все грязные буферы на диск
    Процесс фоновой записи background writer (или bgwriter) похож на процесс контрольной точки, записывает только часть грязных буферов, которые с большой вероятностью будут вытеснены в ближайшее время
    Обслуживающие процессы, читающие данныев буферный кеш. Если, несмотря на работу процессов контрольной точки и фоновой записи, вытесняемый буфер окажется грязным, обслуживающий процесс самостоятельно запишет его на диск
    Буферный кэш ускоряет работу, уменьшая число дисковых операций. Надежность обеспечивается журналированием. Размер журнала ограничен благодаря контрольным точкам.
    Журнал используется для восстановления после сбоя, резервного копирования, репликации между серверами

    Уровни журнала

    Объем данных, который попадает в журнал, регулируется параметром wal_level
    Minimal - гарантия восстановления после сбоя
    Replica - резервное копирование, репликация, передача и проигрование данных на другом сервере. На данном уровне в журнал добавляется информация, позволяющая использовать его для создания резервных копий и репликации. При репликации журнальные записи передаются на другой сервер и применяются там, таким образом создается точная копия ( реплика ) основго сервера
    Logical - логическая репликация, информация об изменении, удалении, добавлении табличных строк. На данном уровне в журнал добавляется информация, позволяющая декодировать журнальные(физические) записи и сформировать из них логические записи о добавлении, изменении, удалении табличных строк


    Немного практики

    Процесс postmaster можно узнать из файла /var/lib/postgresql/14/main/postmaster.pid

    -- Найдем все процессы, поражденные процессом postmaster ~$ sudo ps -o pid,command --ppid 1065 PID COMMAND 1078 postgres: 14/main: checkpointer 1079 postgres: 14/main: background writer 1080 postgres: 14/main: walwriter 1082 postgres: 14/main: autovacuum launcher 1083 postgres: 14/main: stats collector 1084 postgres: 14/main: logical replication launcher -- Остановка в режиме immediate sudo pg_ctlcluster 16 main stop -m immediate --skip-systemctl-redirect --Перед тем, как начать принимать соединения, СУБД выполнила восстановление (automatic recovery in progress)
    Источники
    Последнее изменение: 06.11.2024 22:43


    Связанные темы
    Здесь пока нет комментариев
    Добавлять комментарии могут только авторизованные пользователи

    Авторизоваться
    Я буду рекламой
    Я тоже буду рекламой
    И я
    ВВЕРХ