- •Предисловие
- •Об этой книге
- •Глава 1. Обзор статистики
- •Внутреннее устройство PostgreSQL
- •Установка соединений и работа сеансов
- •Запросы как базовая единица рабочей нагрузки
- •Планирование и выполнение запросов
- •Ввод-вывод при выполнении запросов
- •Журнал сообщений СУБД
- •Репликация изменений
- •Архивирование журнала предзаписи
- •Фоновая синхронизация данных
- •Автоочистка
- •Интерфейс статистики
- •Статистика как отправная точка инструментов мониторинга
- •Особенности статистики
- •Тестовое окружение
- •Глава 2. Статистика активности
- •Ключ к пониманию происходящего в СУБД
- •Взаимодействие клиента и сервера
- •Источники информации об активности
- •Представление pg_stat_activity
- •Представление pg_locks
- •Особенности pg_stat_activity и pg_locks
- •Представление pg_stat_database
- •Подключенные клиенты
- •Отслеживание клиентских сеансов
- •Транзакционная активность
- •Статусы завершения сеансов
- •Состояния сеансов
- •Отслеживание состояний
- •Ожидания и блокировки
- •Отслеживание состояний с учетом ожиданий
- •Взаимоблокировки
- •Бездействующие транзакции
- •Время выполнения запросов и транзакций
- •Отслеживание времени ожидания блокировок
- •Использование pg_locks.waitstart
- •Использование pg_stat_activity.state_change
- •Дерево блокировок
- •Глава 3. Выполнение запросов и функций
- •Зачем нужен мониторинг запросов
- •Расширение pg_stat_statements
- •Метаданные запроса
- •Планирование запроса
- •Исполнение запроса
- •Сквозная идентификация с queryid
- •Построение отчетов на основе pg_stat_statements
- •Представление pg_stat_statements_info
- •Выполнение процедур и функций
- •Глава 4. Базы данных
- •Иерархия объектов СУБД
- •Кластер баз данных
- •Табличные пространства
- •Базы данных
- •Схемы
- •Таблицы и индексы
- •TOAST
- •События в кластере баз данных
- •Рабочая нагрузка в отношении таблиц и индексов
- •Ошибки и нежелательные события
- •Функции для работы с объектами СУБД
- •Определение размеров объектов СУБД
- •Размещение объектов в файловой системе
- •Глава 5. Область общей памяти и ввод-вывод
- •Анализ общей памяти
- •Представление pg_buffercache
- •Представление pg_shmem_allocations
- •Анализ памяти клиентских процессов
- •Оценка использования SLRU-кешей
- •Ввод-вывод в контексте объектов СУБД
- •Базы данных
- •Ввод-вывод в контексте выполнения запросов
- •Временные файлы
- •Уровень баз данных
- •Ввод-вывод при выполнении запросов
- •Отслеживание в журнале сообщений
- •Отслеживание активных временных файлов
- •Ввод-вывод фоновых процессов
- •Глава 6. Журнал упреждающей записи
- •Отслеживание активности в журнале
- •Представление pg_stat_wal
- •Представление pg_stat_statements
- •Архивирование журнала
- •Представление pg_stat_archiver
- •Очередь архивирования
- •Глава 7. Репликация
- •Обзор репликации
- •Инструменты отслеживания репликации
- •Представление pg_stat_replication
- •Представление pg_stat_wal_receiver
- •Cлоты репликации и pg_replication_slots
- •Публикации и подписки
- •Конфликты восстановления
- •Глава 8. Очистка
- •Введение в очистку
- •Особенности очистки на практике
- •Когда выполняется автоочистка?
- •Статистика выполнения очистки
- •Счетчик транзакций и предотвращение ошибок, связанных с его зацикливанием
- •Раздувание таблиц и индексов
- •Отслеживание активных процессов очистки
- •Представление pg_stat_activity
- •Представление pg_stat_progress_vacuum
- •Глава 9. Ход выполнения операций
- •Представление pg_stat_progress_analyze
- •Представление pg_stat_progress_basebackup
- •Представление pg_stat_progress_cluster
- •Представление pg_stat_progress_create_index
- •Представление pg_stat_progress_copy
- •Предметный указатель
16 |
Глава 1. Обзор статистики |
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Client Backends |
|
|
|
|
|
Postmaster |
|||||
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Query Planning |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
||||
|
|
Shared Buffers |
|
Background Workers |
|||||||||
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|||||||||
|
|
Query Execution |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Autovacuum Launcher |
|||
|
|
|
|
|
|
|
|
|
|
||||
|
|
Indexes Usage |
|
Tables Usage |
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
Buffers IO |
|
SLRU Caches |
|
Autovacuum Workers |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Write-Ahead Log |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
Logger Process |
|
|
|
|
|
Stats Collector |
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
Logical |
|
WAL Sender |
|
WAL Archiver |
|
Background |
|
|
Checkpointer |
||
|
|
Replication |
|
Process |
|
Process |
|
Writer |
|
|
Process |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
Network |
|
|
|
|
|
Storage |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
WAL Receiver Process |
|
|
|
|
|
|
|
|
|
||
Tables/Indexes Data Files
Recovery Process
Рис. 1.1.Внутреннее устройство СУБД PostgreSQL
•конкурентный транзакционный доступ к данным с гарантиями атомарности, согласованности и изоляции (эти свойства входят в известную аббревиатуру ACID1).
Для реализации этих и многих других услуг СУБД опирается на различные подсистемы и механизмы.
1.2. Внутреннее устройство PostgreSQL
Давайте поверхностно, с минимально необходимым погружением в детали, рассмотрим основные подсистемы СУБД и работу внутренних процессов при выполнениитаких регулярных задач,как:
•установка соединений и обслуживание сеансов;
•планирование и выполнение запросов;
•ввод-вывод при работе с данными;
•журналирование изменений;
1 en.wikipedia.org/wiki/ACID
1.2. Внутреннее устройство PostgreSQL |
17 |
•репликация и архивирование журнала транзакций;
•фоновая синхронизация данных;
•журнал сообщений;
•автоочистка.
Установка соединений и работа сеансов
В своем обычном режиме СУБД работаеткак служба (программа-сервер) и ожидаетподключений со стороны клиентов.Клиентом можетбытькак приложение,так и пользователь,подключающийся через клиентскую программу (psql, pgAdmin, DataGrip и др.). Для каждого клиента сервером СУБДсоздаютсяотдельные процессыоперационной системы,которыев привычной для администраторов терминологии называются бэкендами (backend). В каждом таком процессе между клиентом и сервером СУБД устанавливается сеанс — двухсторонняя связь, позволяющая клиенту взаимодействовать с СУБД. В процессе создания сеанса СУБД выполняет аутентификацию клиента согласно указаниям в pg_hba.conf, инициализирует внутренние рабочие структуры и применяет различные настройки,влияющие на дальнейшую работу.Когда сеанс готов,клиент может отправлять серверу команды,включающие в себя как команды SQL, так и системные управляющие команды1.
При эксплуатации СУБД важно иметь представление о подключенных клиентах, установленных сеансах и том, что происходит в этих сеансах. Поведение клиента и состояние сеанса в некоторых обстоятельствах могут негативно влиять на работу и производительность СУБД.
Запросы как базовая единица рабочей нагрузки
Запросы являются подмножеством команд и представляют собой базовую единицу рабочей нагрузки. Рабочую нагрузку можно представить как весь объем запросов, отправляемый всеми приложениями и выполняемый на стороне СУБД. Чтобы справляться с рабочей нагрузкой, серверутребуются ресурсы,такие как CPU,память,ввод-вывод и пространство надиске.В эксплуатации СУБД важно иметьточное представление о том,какие запросы исполняются СУБД и достаточно ли ресурсов для их эффективного выполнения.Статистика дает ответ на этот вопрос и предоставляет отправную точку для оптимизации запросов и производительности.
Планирование и выполнение запросов
Получив команду от клиента, сервер проверяет ее корректность. Чаще всего командой является SQL-запрос; втаком случае СУБД начинаетего планирование.Планирование заключается в составлении оптимального плана для доступа к данным. Доступ и промежуточная обработка данных могут стоить по-разному (в смысле использования системных ресурсов), и задача
1 www.postgrespro.ru/docs/postgresql/current/sql-commands
18Глава 1. Обзор статистики
планирования сводится к составлению и выбору наиболее дешевого плана. План обычно принято представлять в виде графа, где каждый узел является вполне конкретной операцией над данными.
СУБД способна планировать параллельное выполнение некоторых операций, например чтение изтаблицы или индекса.Если планом предполагается параллельное выполнение,для этого будут автоматически запущены вспомогательные процессы (background workers), которые возьмут на себя часть работы. После выполнения операции вспомогательные процессы также автоматически будут завершены.
Когда план выбран, сервер приступает к выполнению запроса согласно этому плану. Каждый узел плана — это конкретная операция над данными (например, над строками из таблиц). Когда запрос выполнен, результат возвращается клиенту. В качестве результата может выступать набор строк или тег команды (command tag), сообщающий об успешности выполнения. В случае запросов на изменение данных результат запроса должен быть записан в журнале транзакций (Write-Ahead Log, WAL). В зависимости от настроек СУБД это может происходить в синхронном или асинхронном режиме.В любом случае после выполнения запроса СУБД передает управление клиенту,и он может отправлять следующий запрос.
Ввод-вывод при выполнении запросов
При выполнении запросов практически вся работа с данными является буферизованной ипроисходитвпамяти,выделеннойпроцессамсистемой.Всяпамять,выделяемаяСУБД,представляет собой набор сегментов, которые с точки зрения использования самой СУБД можно разделить на два типа областей памяти—локальные и общие.
Локальные области памяти—это сегменты,которые выделяются индивидуально для каждого процесса (в рамках сеанса),при этом процессы не имеютдоступа клокальным сегментамдруг друга.Среди таких сегментов можно выделить следующие характерные области:
•рабочая памятьпроцессов (см. параметр work_mem)—выделяется при необходимостидля оперативногоразмещенияданныхпривыполнениинекоторыхпромежуточныхопераций в запросе (сортировка,исключение дубликатов (DISTINCT),соединение таблиц по алгоритмам merge join и hash join и др.). Если для выполнения операции рабочей памяти становится недостаточно, на диске создаются временные файлы, которые удаляются после завершения операции;
•временные буферы (см. параметр temp_buffers) — используются для работы с данными временных таблиц (temporary tables), которые существуют в рамках сеанса или вообще транзакции. Такие таблицы являются нежурналируемыми и часто применяются для сохранения промежуточных результатов;
•рабочая память для операций обслуживания (см. параметр maintenance_work_mem) — выделяется для таких операций, как VACUUM, CREATE INDEX, REINDEX и др. Фоновые процессы автоочистки используют собственную отдельную рабочую память (см. параметр autovacuum_work_mem).
1.2. Внутреннее устройство PostgreSQL |
19 |
Параметры конфигурации СУБД
В этой и следующих главах часто будутвстречаться параметры конфигурации.Полный список всех параметров доступен в документации по адресу: postgrespro.ru/docs/postgresql/ current/runtime-config.
Общая память (shared memory) — это один и, как правило, достаточно большой сегмент памяти, который выделяется один раз при запуске СУБД. Доступ к общей памяти имеют все процессы СУБД.В области общей памяти размещаются:
•буферный кеш для страниц таблиц и индексов;
•буферы WAL-журнала;
•данные журнала, который хранит состояние всех транзакций (commit log) и используется правилами видимости многоверсионного управления конкурентным доступом;
•служебные структурыдля управлениядоступом (тяжелые илегкие блокировки,семафоры и т. п.);
•служебные структурытранзакций,необходимыедляточек сохранений (savepoint)1 идвухфазного подтверждения (two-phase commit)2,при котором становится возможным успешное подтверждение даже в случае аварийного сбоя,предшествующего подтверждению;
•служебные структуры фоновых служб;
•серверная статистика;
•и многое другое.
Буферный кеш
Здесьидалее подтермином «буферный кеш» мы будем называтьименно общий буферный кеш,известный как shared buffers.В контексте повествования,где упоминаютсялокальные буферные кеши,это отмечено отдельно.
Кроме основной общей памяти, также могут создаваться и небольшие сегменты общей памяти для взаимодействия вспомогательных процессов в случае параллельного выполнения некоторых операций. Существование таких сегментов ограничено временем жизни вспомогательных процессов,а размер зависит от объемов передаваемых данных.
Работа с пользовательскими данными происходит примерно одинаково независимо от типа области данных, локального или общего. СУБД использует страничную организацию данных со страницами (page) фиксированного размера (8 КБ по умолчанию), что определяет минимальный объем ввода-вывода.В случае операций чтения или измененияданных процесс проверяет наличие необходимых данных в буфере, неважно, в локальном или общем. Если они
1 postgrespro.ru/docs/postgrespro/current/sql-savepoint
2 postgrespro.ru/docs/postgrespro/current/sql-prepare-transaction
20Глава 1. Обзор статистики
есть, это считается успешной попыткой доступа (hit). Если данных в кеше не нашлось, то для продолженияработыихтребуетсязагрузитьсдискавкеш;этосчитаетсяпромахомкеша(miss, или read). Если к данным обращались ранее, они могут оказаться в страничном кеше операционной системы (page cache), откуда взять их будет быстрее, чем прочитать из основного хранилища. В случае обновления (INSERT, UPDATE, DELETE) страницы изменяются в кеше; такие страницы считаются грязными (dirtied), что указывает на необходимость их синхронизации с файлом данных в основном хранилище. Обычно синхронизацией страниц занимаются два фоновыхпроцесса—checkpointerиbackgroundwriter,новнекоторыхслучаяхэтоможетделать и клиентский процесс. Так бывает, когда процессу требуются страницы, которых нет в кеше, и, чтобы прочитать их с диска, процессу нужны свободные буферы, которых тоже нет. Чтобы освободить буфер под целевую страницу,процесс начинает поиск и вытеснение страницы, к которой давно не было обращений. Найденная страница может оказаться грязной, и тогда процесс сначала синхронизирует ее (written) и только потом освобождает буфер. В общем, получается не самая дешевая операция,особенно если приходится делать это часто.
Всего получаются четыре возможных случая:
•hit — наиболее быстрая и дешевая, но все-таки не бесплатная операция: страница находится в общей памяти;
•miss,илиread—болеедорогаяоперация:страницунеобходимопрочитатьвлучшемслучае из страничного кеша,а в худшем—с диска;
•dirtied—такжедорогая операция: страницу впоследствии нужно будетсинхронизировать с основным хранилищем;
•written — еще одна дорогая операция: вместо отложенной фоновой синхронизации страница должна быть синхронизирована немедленно клиентским процессом (который выполняет запрос).
Описанная выше модельработыодинаковакакдля общего,так идлялокальногокеша.Приработе с обычными и временнымитаблицами страницы в кеше всегда ассоциированы с файлом таблицы на диске.В случае использования рабочей памятитакого файла нет ровно дотех пор, пока не будет превышено ее ограничение (параметр work_mem). В этом случае создается временный файл, который удаляется после завершения операции. При нехватке рабочей памяти для операций обслуживания (автоочистка,создание индексов) СУБД повторно используетуже выделенную память без создания дополнительных файлов.
С точки зрения производительности очень хорошо, когда бóльшая часть данных находится в памяти и на любое обращение страницу можно найти в кеше, и хуже, когда приходится регулярно читать данные из основного хранилища или же вытеснять грязные страницы для освобождения буферов под новые страницы.
Журнал упреждающей записи —Write-Ahead Log
Перед тем как вернуть результат запроса, направленного на изменение данных, СУБД записывает эти изменения в журнал предзаписи (Write-Ahead Log). Еще можно встретить термин
