1.1 Две услуги одного сервиса
Если свести PostgreSQL к сути, он даёт две вещи, и обе нетривиальны.
Первая - надёжно хранить данные. Записал - значит, не потеряешь: ни при выключении питания посреди транзакции, ни при падении процесса. Данные переживут сбой в том состоянии, в каком ты их зафиксировал.
Вторая - давать согласованный доступ многим сразу. Десятки клиентов читают и пишут одновременно, и каждый видит непротиворечивую картину, как будто работает с базой один. Никто не ловит «половину» чужой транзакции.
Почти всё устройство движка - это машинерия, обслуживающая два этих обещания. Журнал предзаписи и контрольные точки отвечают за надёжность. Многоверсионность и блокировки - за согласованный конкурентный доступ. Остальное (буферный кеш, vacuum, планировщик, индексы) делает эти два обещания быстрыми, а не только выполнимыми.
1.2 Клиент и сервер
PostgreSQL - это сервер, к которому подключаются клиенты. Клиент -
это psql, драйвер приложения, ORM: что угодно, говорящее по
сетевому протоколу PostgreSQL. Сервер - набор процессов, работающих с
одним каталогом данных.
Ключевая деталь, которая отличает PostgreSQL от многих СУБД: на каждое соединение поднимается отдельный процесс операционной системы. Подключился клиент - главный процесс (postmaster) породил для него backend-процесс. Этот процесс обслуживает только это соединение и живёт, пока оно открыто.
Из этой модели «процесс на соединение» вытекает многое: и почему тысячи соединений дороги, и зачем нужны пулы соединений, и как устроена разделяемая память, через которую процессы видят общий буферный кеш. Подробно процессы разберём в следующей главе.
1.3 Карта подсистем
Соберём подсистемы в одну картинку. Запрос проходит сверху вниз: от клиента к данным на диске, а сбоку его обслуживают механизмы согласованности и надёжности.
Каждый блок - это часть книги:
- Хранение - как данные лежат на диске (части про страницы и форки).
- MVCC - как сервер решает, какую версию строки показать.
- Vacuum - как убирается мусор от старых версий.
- Буфер и журнал - как страницы кешируются и как гарантируется надёжность записи.
- Блокировки - как упорядочивается конкурентный доступ.
- Планировщик и индексы - как запрос превращается в быстрый план.
Дальше мы пройдём эту карту слой за слоем, начиная с самого низа - с того, как байты лежат на диске.
1.4 Зачем понимать изнутри
Можно годами пользоваться базой, не зная её устройства. Пока всё работает - и не надо. Понимание окупается в двух ситуациях: когда нужно, чтобы было быстро, и когда что-то сломалось.
Почти любая проблема производительности упирается в механизм: запрос медленный, потому что планировщик выбрал sequential scan вместо индекса; таблица распухла, потому что долгая транзакция держит горизонт и vacuum не может убрать мусор; запись тормозит, потому что чекпойнты идут слишком часто. Не зная механизма, ты крутишь параметры наугад. Зная - ставишь диагноз.
Эта книга даёт именно диагностическую модель. Не «поставь вот этот параметр», а «вот как это работает, поэтому симптом такой, а лечение такое». Рецепты устаревают с версиями. Модель устройства - нет.
1.5 Реляционная модель за минуту
Договоримся о словах, которыми будем пользоваться. PostgreSQL -
реляционная СУБД: данные лежат в таблицах (в терминах движка -
отношениях), таблица состоит из строк, у строки есть колонки с
типами. Целостность стерегут ограничения: первичные и внешние ключи,
NOT NULL, CHECK.
Работа идёт транзакциями - группами операций, которые применяются
целиком или не применяются вовсе. Транзакция либо фиксируется
(COMMIT), либо откатывается (ROLLBACK). Это та единица, вокруг
которой крутится вся согласованность, и к ней мы будем возвращаться
постоянно.
Слово «отношение» (relation) встретится часто: так движок называет и
таблицы, и индексы - всё, что имеет строки и лежит в файлах. Когда
увидишь pg_relation_size или relfilenode, знай: речь про таблицу
или индекс.
1.6 Маршрут книги
Дальше путь такой. Сначала спускаемся на самый низ - смотрим, как данные физически лежат на диске: кластер, файлы, страницы, кортежи. Потом поднимаемся к многоверсионности: как из одной таблицы разные транзакции видят разные данные. Затем - как сервер убирает мусор, который оставляет многоверсионность.
Выше идут буферный кеш и журнал, блокировки, планировщик с индексами и, наконец, репликация и эксплуатация. Каждый слой опирается на предыдущий: MVCC не понять без устройства строки, vacuum - без MVCC, планы - без страниц и индексов. Поэтому читать лучше по порядку, хотя продвинутые врезки можно откладывать.
Резюме
- PostgreSQL даёт две услуги: надёжное хранение и согласованный конкурентный доступ многим клиентам.
- Это сервер с моделью «процесс на соединение»: postmaster порождает backend на каждого клиента.
- Подсистемы: хранение, MVCC, vacuum, буфер и журнал, блокировки, планировщик и индексы.
- Понимание изнутри окупается в двух случаях: нужна производительность или что-то сломалось.
- Отношение - это таблица или индекс; работа идёт транзакциями, вокруг которых строится согласованность.
Контрольные вопросы
Какие два обещания PostgreSQL даёт пользователю, и какие подсистемы их обслуживают?
Показать ответ
Первое - надёжно хранить данные: записанное переживёт сбой. За это отвечают журнал предзаписи (WAL) и контрольные точки. Второе - согласованный конкурентный доступ: много клиентов работают одновременно, каждый видит непротиворечивую картину. За это отвечают многоверсионность (MVCC) и блокировки. Остальные подсистемы (буферный кеш, vacuum, планировщик, индексы) делают эти обещания быстрыми.
Что означает модель «процесс на соединение» и какие у неё последствия?
Показать ответ
На каждое клиентское соединение PostgreSQL поднимает отдельный backend-процесс операционной системы, который живёт, пока открыто соединение. Последствия: тысячи соединений стоят дорого (память и переключение контекста), поэтому нужны пулы соединений; а общие данные (буферный кеш, список транзакций) процессы видят через разделяемую память.
Почему книга делает упор на модель устройства, а не на готовые рецепты настройки?
Показать ответ
Потому что рецепты устаревают с версиями и не переносятся между ситуациями, а модель устройства - переносится. Зная механизм, ты ставишь диагноз: понимаешь, почему симптом именно такой, и выводишь лечение. Не зная - крутишь параметры наугад. Большинство проблем производительности упираются в конкретный механизм, и понимание его и есть инструмент решения.
Что в PostgreSQL называют «отношением»?
Показать ответ
Отношение (relation) - это любой объект, имеющий строки и хранящийся в файлах: и таблица, и индекс. Поэтому системные функции и колонки с корнем
rel(pg_relation_size,relfilenode,relpages) относятся и к таблицам, и к индексам. Это шире, чем «таблица».Почему книгу советуют читать по порядку, а не выбирать главы вразнобой?
Показать ответ
Потому что слои опираются друг на друга. Многоверсионность не понять без устройства строки и её заголовка; vacuum - без многоверсионности; планы запросов - без страниц и индексов. Каждая часть предполагает, что модель из предыдущих уже в голове. Продвинутые врезки - исключение: их можно отложить и вернуться позже.