Подготовка к устной защитеБез «Практики+»

От команд — к пониманию

PostgreSQL.
Разобраться
и объяснить.

Транзакции, версии строк, блокировки и восстановление. Один связный конспект по твоим лекциям и выполненной лабораторной.

СнимокЧто я вижу?БлокировкаЧего я жду?WALЧто переживёт сбой?

Маршрут на 2–3 часа

Понять, затем объяснить

Этот конспект связывает пять лекций с тем, что ты уже сделал в лабораторной № 8. Читай по порядку ниже, проговаривай ответы вслух и проверяй себя без подсказки. Цель подготовки: объяснить почему получился такой результат, а затем назвать механизм PostgreSQL.

Как пользоваться

Слева находятся главы и поиск. Кнопка «Изучено» сохраняет отметку на этом устройстве; это отметка чтения, а не оценка знаний. В разделе самопроверки сначала сформулируй ответ сам и только потом раскрывай объяснение. Если сегодня есть ещё 20–30 минут, подробно прочитай «Инструменты» и «Путь запроса».

Приоритеты: обязательно — все вопросы из задания; углубление — статусы транзакций и аномалии; прошлые темы — архитектура ИС. Дополнительные знания включены для подготовки, но выполнять «Практику+» не требуется. Гарантировать список устных вопросов нельзя: здесь покрыты предоставленные материалы и задание.

DEV1 · база для объяснения команд

Инструменты и устройство сервера

Клиент, сервер, кластер и база — разные вещи

PostgreSQL — серверная СУБД. psql — отдельная клиентская программа: отправляет SQL серверу и показывает ответ. Закрыть psql — закончить клиентский сеанс, а не остановить сервер. SSH даёт доступ к командной строке удалённой машины; уже внутри неё ты запускаешь psql.

Кластер PostgreSQL — набор баз, обслуживаемых одним экземпляром сервера и объединённых общим каталогом данных. Здесь слово «кластер» не означает группу компьютеров. База содержит схемы, а схемы — таблицы и другие объекты. Одно обычное подключение работает с одной базой. Роли действуют на уровне кластера.

Твой терминалSSH → виртуальная машина
→
psqlклиент · текущий сеанс
→
PostgreSQLкластер 16 main → база → схема → таблица

Установка и расширения

В лекции три варианта: готовые пакеты ОС, сборка из исходных кодов, облачный сервис. Пакеты обычно проще: интегрируют запуск с ОС и определяют расположение файлов. В учебной Ubuntu сервер уже установлен из пакетов. Расширение добавляет функциональность: типы, функции, операторы и другие возможности. Наличие файлов расширения в системе и его подключение командой CREATE EXTENSION в базе — разные шаги.

Где что лежит в нашей машине

ОбъектРасположение / смысл
Программы сервера/usr/lib/postgresql/16/bin
PGDATA/var/lib/postgresql/16/main — каталог данных кластера, владелец ОС postgres
Основная конфигурация/etc/postgresql/16/main/postgresql.conf — путь зависит от пакетной установки
Автоматическая конфигурацияPGDATA/postgresql.auto.conf — изменения ALTER SYSTEM
Журнал сообщений/var/log/postgresql/postgresql-16-main.log — читаемый текст
WALPGDATA/pg_wal — двоичные записи для восстановления
Статусы транзакцийPGDATA/pg_xact — служебные файлы

Не путай пользователя ОС postgres, которому принадлежат файлы кластера, с ролью БД. В лабораторной ты входил в ОС и в psql как student. Права роли БД определяют, какие SQL-команды доступны; sudo относится к ОС.

Терминал · Linux
pg_lsclusters
sudo pg_ctlcluster 16 main status
sudo pg_ctlcluster 16 main reload

reload перечитывает конфигурацию без остановки. restart останавливает и запускает сервер. Часть параметров можно менять на лету, часть требует перезапуска; проверяй context и pending_restart в pg_settings.

Как подключаться и читать приглашение

Терминал · Linux
psql -d tools_overview -U student
# Для TCP-подключения явно задают также -h и -p:
psql -h localhost -p 5432 -U student -d tools_overview

Без параметров имя роли обычно берётся из имени пользователя ОС, а имя базы — из имени роли; локальное соединение обычно использует Unix-сокет. В виртуальной машине значения настроены так, что достаточно psql.

ПриглашениеЧто означает
student:~$Оболочка Linux; здесь выполняются ps, cat, pg_lsclusters.
lab8_report=#psql, команда завершена; # обычно означает роль суперпользователя.
isolation_lab=*#Открытая транзакция.
isolation_lab=!#Транзакция в ошибочном состоянии; нужен ROLLBACK или откат к допустимой точке сохранения.
lab8_report-#SQL ещё не завершён: например, не введена точка с запятой.

Шпаргалка по psql

КомандаНазначение
\conninfoПоказать текущее подключение.
\c имя_базыСоздать новое подключение к другой базе.
\l / \dt / \d booksБазы / таблицы / структура объекта.
\? / \h SELECTСправка по psql / синтаксис SQL.
\i /путь/ddl.sqlПрочитать и выполнить файл на стороне клиента psql.
\! cat /путь/ddl.sqlВыполнить команду ОС из psql.
\pset pager offОтключить постраничный просмотр.
\x / \gxРасширенный вывод постоянно / для одного запроса.
\a / \tПереключить выравнивание / заголовки и итог.
\o файл / \oНаправить результат в файл / вернуть на экран.
\qВыйти из psql.
Команды psql
\set topic 'MVCC'
\echo :topic
\unset topic

Переменные psql обрабатывает клиент. :name — подстановка, :'name' — SQL-литерал, :"name" — SQL-идентификатор. Команды запуска можно хранить в ~/.psqlrc. SQL завершают ;, команды с обратной косой чертой завершаются концом строки.

Терминал · варианты запуска
psql -d lab8_report -f /home/student/lab8/ddl.sql
psql -d lab8_report -c "SELECT * FROM books;"

work_mem: что именно ты менял

work_mem — базовый лимит памяти для отдельных операций сортировки и хеширования до использования временных файлов. Это не размер общего буферного кеша и не общий лимит на весь сервер. В запросе могут быть несколько таких операций, параллельные процессы и множество одновременно работающих сеансов; для хеширования учитывается также hash_mem_multiplier. Поэтому «чем больше, тем лучше» — плохое универсальное правило. Уточнение: документация PostgreSQL 16.

СпособОбласть действия
SET work_mem = '8MB';Текущий сеанс.
SET LOCAL work_mem = '8MB';Текущая транзакция; после её завершения значение восстанавливается.
ALTER SYSTEM SET work_mem = '8MB';Запись в postgresql.auto.conf; затем нужно перечитать конфигурацию.
ALTER SYSTEM RESET work_mem;Удалить переопределение из auto.conf; затем reload. Итог берётся из оставшихся настроек, не обязательно из встроенного значения.
SQL · psql
SHOW work_mem;
SELECT name, setting, unit, context, source, pending_restart
FROM pg_settings WHERE name = 'work_mem';

DEV2 · темы, которые легко упустить

Как запрос становится результатом

Четыре этапа

РазборСинтаксис, имена, типы
ПереписываниеПредставления и правила
ПланированиеСпособ доступа и соединения
ВыполнениеЧтение версий и результат

На разборе сервер понимает структуру SQL и обращается к системному каталогу: существует ли таблица, какие у столбцов типы. Переписывание преобразует дерево запроса по правилам, например раскрывает представления. Планировщик выбирает план по оценкам стоимости и статистике: читать всю таблицу или индекс, в каком порядке соединять данные. Исполнитель выполняет выбранный план. Каталог — метаданные, обычные таблицы — пользовательские данные; оба вида данных могут кешироваться.

Подготовленный оператор — не подготовленная транзакция

SQL · psql
PREPARE get_book(integer) AS
    SELECT * FROM books WHERE id = $1;
EXECUTE get_book(2);
SELECT name, parameter_types, generic_plans, custom_plans
FROM pg_prepared_statements;
DEALLOCATE get_book;

PREPARE сохраняет подготовленный запрос для повторных вызовов в текущем сеансе. Значения параметров привязываются при EXECUTE. План может быть специализированным под значения либо общим; нельзя обещать, что любой запрос всегда планируется ровно один раз. Подготовка особенно полезна при повторении одной формы запроса. PREPARE TRANSACTION относится к двухфазной фиксации и решает другую задачу. Справочник PREPARE; PREPARE TRANSACTION.

Зачем нужен курсор

Курсор хранит состояние выполнения и позволяет получать результат порциями. Представь миллион строк: приложению может быть удобнее обрабатывать по тысяче, чем принимать весь результат разом. Но FETCH по одной строке через сеть добавляет много обменов. Размер порции — компромисс памяти и числа обращений.

SQL · psql
BEGIN;
DECLARE book_cursor CURSOR FOR
    SELECT * FROM books ORDER BY id;
FETCH 2 FROM book_cursor;
FETCH 2 FROM book_cursor;
CLOSE book_cursor;
COMMIT;

В нашей таблице первая порция содержит две строки, вторая — одну, следующая была бы пустой. Обычный курсор закрывается при завершении транзакции; вариант WITH HOLD может пережить COMMIT. Курсор не является новой базой или новой транзакцией.

Процессы, память и пул соединений

Главный процесс postmaster принимает подключения и управляет серверными процессами. В обычной модели каждое клиентское соединение обслуживает отдельный backend. У backend есть локальная память: разобранные запросы, кеш метаданных, состояние курсоров и рабочая память операций. Общая память доступна нескольким процессам: буферный кеш, WAL-буферы, структуры блокировок. Фоновые процессы выполняют обслуживание независимо от отдельных запросов.

Много соединений — много процессов и затрат памяти. Пул соединений переиспользует серверные подключения для множества клиентских запросов. При пуле в режиме транзакций следующая транзакция клиента может попасть в другой backend: сеансовые настройки и сеансовые advisory locks требуют особого внимания. Пул не отменяет транзакции и не делает запросы автоматически корректными.

Страницы, кеш ОС и расширяемость

Данные таблиц и индексов хранятся в файлах страницами, обычно по 8 Кбайт. Запросу нужна строка, но в память читается целая страница. Кеш PostgreSQL работает поверх файловой системы: у ОС тоже есть кеш. Поэтому отсутствие страницы в shared_buffers ещё не доказывает физическое чтение с накопителя.

PostgreSQL расширяется типами данных, функциями, операторами, триггерами, методами индексов, процедурными языками и фоновыми worker-процессами. FDW (Foreign Data Wrapper) позволяет обращаться к внешним источникам через внешние таблицы. Не всё расширение — это отдельный сервер; многое встраивается в механизм запросов.

Обязательное · лекция 5 и DEV2

Транзакции и ACID

Одна осмысленная операция, несколько SQL-команд

Транзакция — логическая единица работы с БД: последовательность операций, которую фиксируют целиком или отменяют. Классическое определение лекции: переводит БД из одного согласованного состояния в другое. Согласованность означает соблюдение ограничений и бизнес-правил, а не просто отсутствие синтаксических ошибок.

Пример: перевести 1000 рублей от Алисы Бобу. Одно списание без зачисления нарушает смысл перевода. Поэтому обе команды входят в одну транзакцию. Для примера считаем, что оба счёта существуют, owner уникален, а приложение проверяет достаточность средств и число изменённых строк.

SQL · psql
BEGIN;
UPDATE accounts SET balance = balance - 1000
WHERE owner = 'Alice';
UPDATE accounts SET balance = balance + 1000
WHERE owner = 'Bob';
COMMIT;
СвойствоСмысл на примере переводаЧем поддерживается
A · Atomicity / атомарностьОба изменения принимаются целиком; при отмене не останется только списания.Границы транзакции, статусы, невидимость отменённых версий.
C · Consistency / согласованностьСохраняются правила: ссылки на существующие счета, допустимый баланс, сумма денег.Ограничения БД и правильная логика приложения.
I · Isolation / изоляцияПараллельные операции наблюдают данные по правилам выбранного уровня.MVCC, снимки, блокировки; для сериализуемости — дополнительный контроль.
D · Durability / долговечностьУспешно зафиксированный перевод переживает сбой при надёжной конфигурации.WAL, синхронизация с постоянным хранилищем, восстановление.

BEGIN, COMMIT, ROLLBACK и autocommit

BEGIN начинает явную транзакцию. COMMIT фиксирует изменения. ROLLBACK отменяет незавершённую работу. В psql по умолчанию включён autocommit: отдельная успешно выполненная SQL-команда вне явного блока фиксируется автоматически. Это не значит, что она выполняется «без транзакции».

psql + SQL
\echo :AUTOCOMMIT
BEGIN;
-- Здесь несколько команд в одной транзакции.
ROLLBACK;

В открытой явной транзакции ошибка обычно переводит её в состояние failed: последующие команды не выполняются до ROLLBACK либо ROLLBACK TO подходящей точки сохранения. В случае обрыва соединения незавершённая обычная транзакция отменяется. Если соединение оборвалось во время COMMIT и ответ не получен, клиент не всегда знает, успела ли фиксация произойти: результат нужно проверять, а не слепо повторять списание.

SAVEPOINT: отменить часть работы

SQL · psql
BEGIN;
INSERT INTO books VALUES (10, 'Оставить');
SAVEPOINT sp;
INSERT INTO books VALUES (11, 'Отменить');
ROLLBACK TO sp;
RELEASE SAVEPOINT sp;
COMMIT;

Будет зафиксирована только строка 10. ROLLBACK TO не завершает внешнюю транзакцию и сохраняет саму указанную точку; RELEASE убирает точку сохранения, но не фиксирует транзакцию. Блокировки, полученные после точки сохранения, при откате к ней освобождаются. Savepoint не делает промежуточные данные видимыми другим сеансам.

DDL, DML и исключения

INSERT, UPDATE, DELETE изменяют данные; CREATE, ALTER, DROP меняют структуру объектов. SELECT читает данные (в разных учебных классификациях его относят к DML или DQL). В PostgreSQL большинство DDL также транзакционны: CREATE TABLE можно отменить. CREATE DATABASE и VACUUM — примеры команд, запрещённых в обычном явном блоке транзакции. Значения sequence, уже выданные nextval, при откате не возвращаются: пропуски в идентификаторах нормальны.

SQL · psql
BEGIN;
CREATE TABLE rollback_example (id integer);
ROLLBACK;
-- Таблица rollback_example не останется.

Модели транзакций и двухфазная фиксация

В лекции модели различаются структурой, параллельностью и длительностью. Плоская транзакция имеет одну внешнюю границу. Точки сохранения дают частичный откат внутри неё. Цепочечная работа связывает несколько последовательных транзакций; распределённая работа охватывает несколько участников. Эти признаки не следует считать синонимами: цепочка не обязательно распределённая, а savepoint — не независимый COMMIT вложенной транзакции.

2PC (two-phase commit) нужен координатору для общего решения нескольких участников. Сначала каждый участник подготавливает свою транзакцию и гарантирует возможность последующего решения. Затем координатор сообщает: всем фиксировать или отменять. Подготовленная транзакция сохраняет ресурсы и блокировки, даже когда исходный сеанс уже закончился.

SQL · psql
-- Только схема 2PC, не требуется выполнять для ЛР № 8.
BEGIN;
-- Изменения участника.
PREPARE TRANSACTION 'transfer_42';
-- Позднее, вне блока BEGIN, по решению координатора:
COMMIT PREPARED 'transfer_42';
-- Альтернатива: ROLLBACK PREPARED 'transfer_42';

Обязательное · объяснение опыта с двумя терминалами

Изоляция: что увидит другой сеанс

Изоляция — набор гарантий, а не отключение параллельности

Несколько транзакций работают одновременно. Уровень изоляции определяет, какие последствия чужих изменений им разрешено наблюдать. Чем строже требования, тем больше может быть затрат и повторных выполнений. Сериализуемость означает, что результат успешно завершённых транзакций эквивалентен некоторому последовательному порядку; сервер при этом вполне может выполнять их параллельно.

Четыре явления на конкретных примерах

ЯвлениеЧто происходитКак отличить
Грязное чтениеB прочитал баланс 200, изменённый A, хотя A ещё не сделал COMMIT. Потом A откатился.B использовал чужие незавершённые данные.
Неповторяемое чтениеA прочитал цену 100. B изменил её на 120 и зафиксировал. Повторный запрос A получил 120.Изменилось значение уже прочитанной строки; удаление тоже меняет результат повторного чтения.
Фантомное чтениеA посчитал товары дешевле 100: их 3. B добавил ещё один подходящий товар и зафиксировал. A повторил запрос: стало 4.Изменился набор строк по условию запроса.
Аномалия сериализацииДве транзакции приняли решения по совместно устаревшей картине; общий результат нельзя получить ни в одном последовательном порядке.Более общее нарушение, чем различие двух SELECT.

Матрица: стандарт SQL и PostgreSQL 16

УровеньГрязноеНеповторяемоеФантомыАномалия сериализации
Read Uncommitted · стандартДопускаетсяВозможноВозможноВозможно
Read Uncommitted · PostgreSQLНет; работает как RCВозможноВозможноВозможно
Read Committed · PostgreSQLНетВозможноВозможноВозможно
Repeatable Read · стандартНетНетДопускаютсяВозможно
Repeatable Read · PostgreSQLНетНетНетВозможно
Serializable · PostgreSQLНетНетНетНет у успешно зафиксированных транзакций

Стандарт задаёт минимальные гарантии; реализация может быть строже. Команда с READ UNCOMMITTED в PostgreSQL допустима, но фактически даёт Read Committed. Поэтому фраза «этого уровня вообще нельзя указать» неточна. Repeatable Read в PostgreSQL предотвращает и фантомы. Сверка таблицы: документация PostgreSQL 16.

Когда возникает снимок

Read Committed используется по умолчанию: обычный SELECT видит снимок на начало своего оператора. Другая транзакция может зафиксироваться между двумя SELECT, и второй получит другой результат. COMMIT, произошедший посреди одного SELECT, не меняет его снимок в середине выполнения.

Repeatable Read: снимок создаётся при первом операторе, которому нужен снимок, после BEGIN, и используется до завершения транзакции. Важно уточнение: не обязательно в момент самой команды BEGIN. Транзакция видит собственные уже выполненные изменения; неизменный снимок не запрещает ей менять данные.

Опыт из лабораторной · один DELETE, два уровня изоляции

Сначала: строка существует

Сеанс A

BEGIN → SELECT

RC: 1 строка · RR: 1 строка
Сеанс B

Пока не менял данные.

id = 1 · Первая строка

Оба варианта A сделали первое чтение до удаления. Это учебное сравнение двух отдельных запусков опыта.

B удалил, но ещё не зафиксировал

Сеанс A

SELECT

RC: 1 строка · RR: 1 строка
Сеанс B

BEGIN → DELETE

Удаление пока не видно A

Чужое незавершённое удаление не должно скрыть строку от обычного чтения A. Это не грязное чтение.

B сделал COMMIT

Read Committed · A

Повторный SELECT → новый снимок.

0 строк
Repeatable Read · A

Повторный SELECT → прежний снимок.

1 строка

В RR старая версия остаётся видна. DELETE уже зафиксирован: различие объясняется видимостью, а не неуспехом удаления.

A завершил транзакцию

Сеанс A

COMMIT → новый SELECT

RC: 0 строк · RR: 0 строк
Сервер

Старая версия больше не нужна этому снимку.

После завершения A новый запрос использует новый снимок. Физическое освобождение места — отдельная задача очистки.

Почему Repeatable Read ещё не Serializable

Дежурят два врача: Анна и Борис. Правило: хотя бы один обязан остаться. Две RR-транзакции одновременно видят обоих дежурными. Первая снимает Анну, вторая снимает Бориса. Они меняют разные строки и могут обе зафиксироваться: дежурных не останется. Каждый снимок был согласован, а общий результат нарушил правило. Это write skew, пример аномалии сериализации.

При последовательной работе второй врач увидел бы, что остался один, и не ушёл бы. PostgreSQL Serializable добавляет обнаружение опасных зависимостей; одну из конфликтующих транзакций может завершить ошибкой сериализации. Приложение должно повторить всю транзакцию с новым чтением, а не только последнюю команду. RR тоже может выдать ошибку сериализации при попытке изменить строку, изменённую после его снимка.

Обязательное + углубление про clog

MVCC: версии, снимки и очистка

Как можно читать строку, которую уже удалили

MVCC — Multiversion Concurrency Control, многоверсионное управление конкурентным доступом. Вместо требования всем читать единственную текущую копию сервер хранит несколько версий строки. Снимок выбирает подходящую версию. Поэтому обычный читатель и писатель обычно не ждут друг друга из-за блокировки строки.

INSERT создаёт версию. UPDATE в обычной модели создаёт новую версию и отмечает завершение жизни прежней; это не простая перезапись значения на месте. DELETE отмечает удаление версии, но не обязан немедленно убрать её байты. После COMMIT старая версия может ещё требоваться транзакции со старым снимком. Здесь и находится ответ на опыт с Repeatable Read.

xmin, xmax, xid и ctid

Поле / терминЧто понимать
xidИдентификатор транзакции; номера назначаются не обязательно сразу при BEGIN. В версиях строк используются 32-битные XID с циклическим пространством.
xmin версии строкиТранзакция, создавшая эту версию.
xmax версии строкиВ простом случае транзакция, удалившая или заменившая версию. Может также отражать блокировку или MultiXact: ненулевое значение само по себе не доказывает удаления.
ctidФизический адрес версии: номер страницы и позиция в ней. Может меняться; не является постоянным бизнес-идентификатором.
pg_current_xact_id()Возвращает расширенный идентификатор текущей транзакции и при необходимости назначает его. Это не PID процесса.
SQL · psql
SELECT id, value, xmin, xmax, ctid FROM test_rows;

Системные столбцы не входят в SELECT *, но доступны явно. Они полезны для учебного разбора и диагностики, а не для замены первичного ключа или собственной бизнес-логики. Видимость определяют не только сравнения номеров, но и состояние транзакций, активность в момент снимка, собственные изменения и служебные признаки.

Жизнь одной строки · условные XID 100 и 120

INSERT зафиксирован

v1 · значение A
xmin = 100 · xmax = 0

Транзакция 100 создала строку и зафиксировалась. Новое обычное чтение видит A. Номера здесь иллюстративные.

UPDATE ещё не завершён

v1 · A
xmin = 100 · xmax = 120
→v2 · B
xmin = 120 · xmax = 0

Транзакция 120 меняет значение. Сама видит B, другая транзакция пока читает A. Одного xmax = 120 недостаточно: нужно знать статус 120.

UPDATE зафиксирован

v1 · A
для старого RR-снимка
→v2 · B
для нового снимка

Обе версии физически могут существовать одновременно. Старый RR-снимок и новый RC-снимок законно получают разные значения.

Старые снимки закончились

v1 · можно очистить→v2 · B · остаётся

Когда v1 больше не нужна ни одному релевантному снимку, её место может освободить VACUUM или другая допустимая очистка. Ветка с ROLLBACK 120 была бы иной: B не стало бы видимым другим, A осталось бы актуальным.

Снимок — не фотография таблицы

Снимок — компактная служебная информация: границы XID и список транзакций, ещё активных в момент создания снимка, плюс данные для правил видимости. Он не копирует все строки. Транзакция, начавшаяся раньше снимка, могла ещё не зафиксироваться; поэтому одного порогового номера недостаточно, нужен список активных. Если такая транзакция зафиксируется позднее, это не сделает её изменения видимыми старому RR-снимку.

Не путай xmin/xmax снимка с одноимёнными полями версии строки. Снимок задаёт границы и набор активных транзакций, а поля версии рассказывают её историю. Два связанных, но разных набора метаданных.

VACUUM и горизонт очистки

VACUUM освобождает для повторного использования место от версий, которые уже никому не нужны. Autovacuum запускает обслуживание автоматически. Старые версии нельзя убирать только на основании того, что DELETE сделал COMMIT: нужно учитывать самые старые ещё нужные снимки и другие удерживающие горизонт факторы. Долгая транзакция может мешать очистке и приводить к разрастанию таблиц.

Обычный VACUUM обычно не уменьшает файл таблицы до минимального размера: освобождённое пространство остаётся для повторной записи; свободный хвост файла иногда можно усечь. VACUUM FULL переписывает таблицу и требует сильной блокировки. ANALYZE собирает статистику для планировщика; это другая цель, хотя команды часто объединяют.

Из-за цикличности 32-битных XID очень старые версии должны быть безопасно «заморожены». Freeze позволяет не интерпретировать древний xid как будущий после оборота счётчика. Поэтому autovacuum нужен не только ради свободного места, но и для предотвращения проблем wraparound.

clog / pg_xact: два бита, большой смысл

Commit log, исторически clog, хранит статусы транзакций. В PostgreSQL 16 каталог называется PGDATA/pg_xact. На транзакцию отводится два бита статуса: in progress, committed, aborted, subcommitted. Страницы статусов хранятся в служебных файлах и буферизуются в общей памяти. Текущую активность сервер также отслеживает в оперативных структурах; флаги-подсказки в версиях помогают не перечитывать статус каждый раз.

Чтобы решить, видна ли версия с xmin = 120, недостаточно номера: нужно понять, зафиксировалась ли 120 и была ли она видима снимку. После ROLLBACK её версии становятся невидимыми остальным. Не требуется для каждой изменённой строки немедленно восстанавливать прежнее содержимое; физическая очистка происходит позднее. Это не обещание, что любой откат имеет нулевую стоимость: освобождение ресурсов тоже требует работы.

Обязательное · лекция 6

Блокировки: кто и чего ждёт

Зачем нужны блокировки при наличии MVCC

MVCC отвечает за видимость версий, блокировки — за допустимость одновременного доступа к ресурсу. Версии позволяют обычному SELECT читать старые данные параллельно UPDATE. Но два писателя не должны бесконтрольно менять одну строку, а DROP TABLE не должен уничтожить таблицу посреди чужого запроса.

Блокировка связана с ресурсом, владельцем и режимом доступа. Совместимые режимы можно держать одновременно; конфликтующие заставляют ждать или завершают попытку ошибкой при соответствующей настройке. На низком уровне используются общая память, примитивы синхронизации ОС и атомарные инструкции CPU. Не стоит смешивать короткие защёлки памяти с длительными SQL-блокировками объектов.

Табличные режимы: «row» в названии не значит блокировку строки

Режим уровня таблицыТипичный источникС чем конфликтует
ACCESS SHAREОбычный SELECTТолько ACCESS EXCLUSIVE.
ROW SHARESELECT FOR UPDATE / SHARE и родственныеEXCLUSIVE, ACCESS EXCLUSIVE.
ROW EXCLUSIVEINSERT, UPDATE, DELETE, MERGESHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE.
SHARE UPDATE EXCLUSIVEVACUUM без FULL, ANALYZE, CREATE INDEX CONCURRENTLYСам с собой, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE.
SHARECREATE INDEX без CONCURRENTLYROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE.
SHARE ROW EXCLUSIVEНапример, CREATE TRIGGERROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, сам с собой, EXCLUSIVE, ACCESS EXCLUSIVE.
EXCLUSIVEНапример, REFRESH MATERIALIZED VIEW CONCURRENTLYВсе режимы, кроме ACCESS SHARE.
ACCESS EXCLUSIVEDROP TABLE, TRUNCATE, VACUUM FULL, многие ALTER TABLEВсе режимы, включая ACCESS SHARE.

Примеры команд и матрица конфликтов уточнены по официальному справочнику. Для защиты прежде всего запомни: SELECT берёт ACCESS SHARE; изменение данных — ROW EXCLUSIVE; DROP требует ACCESS EXCLUSIVE. Два ROW EXCLUSIVE совместимы: само наличие табличной блокировки не запрещает менять разные строки.

Строковые блокировки

UPDATE и DELETE блокируют изменяемые строки от конфликтующих изменений. Обычный SELECT при этом читает подходящую версию и не ждёт завершения писателя из-за этой строковой блокировки. Но SELECT ... FOR UPDATE специально захватывает блокировку: он способен ждать и сам задерживать других писателей. Не говори «любой читатель никогда никого не блокирует»: SELECT также держит табличный ACCESS SHARE и мешает DROP.

Строковый режимИдея
FOR KEY SHAREЗащитить строку от удаления и изменения ключа; совместим с обычным неклю­чевым обновлением.
FOR SHAREРазделяемая защита от изменения и удаления.
FOR NO KEY UPDATEИзменение, не затрагивающее защищаемый ключ; мягче FOR UPDATE.
FOR UPDATEНаиболее сильный строковый режим; конфликтует со всеми четырьмя режимами.
SQL · psql
BEGIN;
SELECT * FROM books WHERE id = 1 FOR UPDATE;
-- До COMMIT/ROLLBACK конкурентное изменение этой строки ждёт.
COMMIT;

Матрица конфликтов строковых режимов

«Конфликт» означает: разные транзакции не могут одновременно удерживать эти режимы на одной строке. Это отдельная таблица от режимов уровня таблицы.

Запрашиваемый / уже удерживаетсяKEY SHARESHARENO KEY UPDATEUPDATE
FOR KEY SHAREСовместимСовместимСовместимКонфликт
FOR SHAREСовместимСовместимКонфликтКонфликт
FOR NO KEY UPDATEСовместимКонфликтКонфликтКонфликт
FOR UPDATEКонфликтКонфликтКонфликтКонфликт

DELETE берёт сильный режим FOR UPDATE. UPDATE обычно использует FOR NO KEY UPDATE, а при изменении некоторых ключевых столбцов — FOR UPDATE. Не всякий столбец с любым UNIQUE-индексом автоматически относится к защищаемому ключу: важна возможность использования соответствующего уникального индекса для внешнего ключа.

Как ограничить ожидание

СредствоПоведение
NOWAITПри невозможности получить требуемую блокировку сразу выдаёт ошибку.
SKIP LOCKEDПропускает строки с конфликтующей строковой блокировкой. Полезно для очереди задач, но даёт неполную картину данных.
lock_timeoutОграничивает длительность ожидания блокировки.
statement_timeoutОграничивает общую длительность оператора.
idle_in_transaction_session_timeoutОтключает сеанс, который слишком долго бездействует внутри транзакции.
deadlock_timeoutЗадержка перед проверкой на взаимоблокировку; не общий предел ожидания.
SQL · psql
BEGIN;
SET LOCAL lock_timeout = '500ms';
LOCK TABLE books IN ACCESS EXCLUSIVE MODE;
-- При конфликте ждём не более заданного времени.
ROLLBACK;

Когда блокировки освобождаются

Обычные транзакционные блокировки сохраняются до COMMIT или ROLLBACK, а не только до конца одного SQL-оператора. В autocommit эти моменты обычно совпадают. При ROLLBACK TO освобождаются блокировки, полученные после точки сохранения. При обрыве соединения обычная незавершённая транзакция отменяется и её блокировки снимаются. Для подготовленных 2PC-транзакций и сеансовых advisory locks правила иные.

Страницы и рекомендательные блокировки

Внутренние блокировки страниц и буферов защищают физические структуры при коротких операциях чтения, изменения, записи или перестроения. Они обычно снимаются сразу после операции, а не удерживаются до COMMIT. Приложение не управляет ими командой LOCK TABLE.

Advisory lock блокирует согласованный приложением числовой ключ: один bigint или пару integer. Это может обозначать обработку заказа, даже если строки заказа пока нет. Другие программы должны соблюдать тот же протокол; обычный UPDATE не начнёт сам уважать придуманную приложением блокировку.

ФункцииВремя жизни и ожидание
pg_advisory_lock(42)Сеансовая: ждёт; живёт до явного unlock или конца соединения, переживает ROLLBACK.
pg_try_advisory_lock(42)Сеансовая: сразу возвращает true или false.
pg_advisory_unlock(42)Снять один захват сеансовой блокировки; функции pg_try_advisory_unlock не существует.
pg_advisory_xact_lock(42)Транзакционная: ждёт; снимается автоматически при завершении транзакции.
pg_try_advisory_xact_lock(42)Транзакционная: не ждёт; удобно для попытки стать единственным обработчиком.

Повторные захваты сеансового ключа одним сеансом учитываются: требуется соответствующее число unlock. Не вызывай блокирующую функцию в выражении с LIMIT, рассчитывая, что она выполнится только для итоговых строк: порядок вычисления может удивить. Сначала выдели набор ключей. Сеансовые advisory locks особенно опасны при пуле соединений в transaction mode: владение связано с реальным backend, а не с логическим клиентом.

Deadlock: цикл ожиданий

A держит строку 1ждёт строку 2, занятую B
⇄
B держит строку 2ждёт строку 1, занятую A

Обычное ожидание может закончиться чужим COMMIT. При взаимоблокировке участники ждут друг друга по циклу. PostgreSQL обнаруживает циклы собственных блокировок и прерывает одну из транзакций; приложение должно обработать ошибку и повторить операцию. Профилактика: одинаковый порядок захвата объектов, короткие транзакции, отсутствие ожидания действий пользователя внутри них. Зависимость, уходящая в приложение или внешнее соединение, не всегда полностью видна серверу.

Как посмотреть ожидание

SQL · psql
SELECT pid, state, wait_event_type, wait_event,
       pg_blocking_pids(pid) AS blockers, query
FROM pg_stat_activity
WHERE wait_event_type = 'Lock';

SELECT pid, locktype, mode, relation::regclass, granted
FROM pg_locks WHERE NOT granted;

granted = false означает ожидаемую, а не полученную блокировку. Не любое wait_event — ожидание SQL-блокировки: бывает ожидание клиента, диска и внутренних структур. pg_cancel_backend прерывает текущий запрос, pg_terminate_backend завершает сеанс; это разные действия, доступные при соответствующих правах.

Обязательное · центральный вопрос защиты

Буферный кеш, WAL и восстановление

Почему данные сначала оказываются в памяти

Читать и менять данные постранично в оперативной памяти быстрее, чем каждый раз обращаться к накопителю. Буферный кеш PostgreSQL — общий массив буферов, содержащих страницы таблиц и индексов и служебные данные. Размер задаёт shared_buffers. Изменённая страница в кеше называется грязной: её содержимое расходится с файлом данных на диске.

Грязный буфер не равен грязному чтению. Первое — состояние страницы в памяти; второе — аномалия видимости чужой незавершённой транзакции. Грязная страница может содержать и зафиксированные, и ещё незавершённые изменения разных строк.

Чтение, вытеснение и EXPLAIN

Если нужная страница уже в shared_buffers, получаем попадание — hit. Если нет, её читают в буфер — read. При нехватке места выбирается буфер для повторного использования. Если он грязный, его предварительно безопасно записывают. В лекции это объясняется как вытеснение редко используемых страниц; для PostgreSQL точнее говорить о clock-sweep с учётом использования, а не о буквальном LRU-списке. Реализация clock-sweep в PostgreSQL 16.

SQL · psql
EXPLAIN (ANALYZE, BUFFERS, COSTS OFF, TIMING OFF)
SELECT * FROM books;

EXPLAIN показывает план, а ANALYZE в его параметрах реально выполняет запрос. Buffers: shared hit — обращения к уже кешированным страницам; shared read — страницы, загруженные в shared_buffers, возможно из кеша ОС. Повторный запуск часто быстрее, но маленькая таблица books не обязана показать заметную разницу. Числа из лекции относятся к её тестовой таблице, не к любому запросу.

Что такое WAL и где он хранится

WAL — Write-Ahead Log, журнал предзаписи. Это логический поток записей об изменениях, достаточный для восстановления. Физически он хранится сегментами в PGDATA/pg_wal; обычный размер сегмента — 16 Мбайт, другой задают при инициализации. WAL не является просто списком исходных SQL-запросов и не просматривается обычным cat как текстовый журнал сообщений.

Каждая позиция в потоке имеет LSN (Log Sequence Number), 64-битное смещение, обычно записанное двумя шестнадцатеричными частями через «/». Разница LSN показывает объём потока в байтах, не количество транзакций. Уровни wal_level: minimal — достаточно для локального восстановления; replica — также для физической репликации и соответствующих резервных копий; logical — дополнительные данные для логического декодирования. Значение по умолчанию — replica.

SQL · psql
SELECT pg_current_wal_lsn();
SELECT name, size FROM pg_ls_waldir() ORDER BY name LIMIT 5;

Два правила, которые нужно произнести точно

Это нормальный ответ на вопрос из задания: транзакция уже зафиксирована, а часть страниц остаётся в памяти; потерянное из памяти будет восстановлено по WAL. Страницы могут попадать на диск и до COMMIT: сама запись страницы не означает фиксацию всех транзакций на ней. Статусы и MVCC не дают читать отменённые изменения как зафиксированные.

Путь изменения · обычная журналируемая таблица, синхронный COMMIT

Изменение в памяти

Оперативная памятьСтраница данных · грязнаяWAL-буфер · запись изменения
Постоянное хранилищеФайл данных · прежнее содержимое

Backend изменяет страницу в кеше и формирует WAL. Потеря памяти в этот момент не должна превратить незавершённую транзакцию в зафиксированную.

COMMIT подтверждён

В памятиСтраница всё ещё может быть грязной
На дискеWAL: изменение + COMMIT сохраненыСтраница данных ещё прежняя

Клиент получил успех. При стандартной надёжной конфигурации данные можно восстановить, даже если сами страницы ещё не записаны. Это главный момент схемы.

Обычная фоновая запись

В памятиБуфер после записи чистый, если снова не изменён
На дискеФайл данных обновлёнНужный WAL уже был сохранён раньше

Страницы записывают checkpointer, background writer или backend при необходимости. Контрольные точки ограничивают объём восстановления.

А если сбой произошёл после шага 2?

Память потерянаГрязной страницы больше нет
ВосстановлениеWAL → REDO → файл данных

Сервер находит REDO-позицию последней завершённой контрольной точки и воспроизводит нужные записи. Зафиксированное изменение восстанавливается; незавершённые транзакции не становятся видимыми как committed.

Порядок предзаписи и восстановление REDO сверены по документации PostgreSQL 16. Схема показывает один возможный порядок; записывать страницу строго только после COMMIT сервер не обязан.

Кто записывает данные и журнал

ПроцессРольЧего не следует утверждать
backendОбслуживает запрос; может обеспечивать запись/синхронизацию WAL при COMMIT и записывать вытесняемые грязные страницы.Не только «читатель»; не вся запись делается фоновыми процессами.
walwriterФоновая запись WAL-буферов.Не единственный процесс, способный записывать WAL.
background writerЗаранее записывает часть грязных буферов, облегчая получение свободных буферов.Не записывает вообще все страницы при каждом COMMIT.
checkpointerВыполняет контрольные точки и обеспечивает сохранение требуемых страниц.Контрольная точка не фиксирует пользовательские транзакции.
startup / recovery processПри запуске после сбоя выполняет восстановление.REDO не повторяет SQL на уровне пользовательских команд.

Контрольная точка и объём WAL

Контрольная точка создаёт гарантированную основу восстановления: необходимые грязные страницы записываются, а контрольная информация позволяет найти позицию REDO. При восстановлении стартуют с REDO-позиции последней завершённой контрольной точки. Она может предшествовать моменту завершения checkpoint: сервер в это время продолжал работать. Поэтому фраза «с самого последнего байта перед сбоем» неверна.

Старые сегменты WAL можно удалить или переиспользовать, когда они больше не нужны. Но необходимость архивирования, репликации или replication slot может удерживать их. Нельзя считать max_wal_size жёстким пределом размера pg_wal или вручную удалять нужные сегменты. В лекции ограничение объёма checkpoint объяснено как общая идея, а не безусловная гарантия фиксированного размера.

Почему WAL выгоден и где предел гарантии

Последовательная запись WAL обычно дешевле немедленной синхронизации множества разрозненных страниц. Одна синхронизация может обслужить несколько фиксаций — group commit. WAL используется также для физической репликации, резервного копирования и восстановления на момент времени: для PITR нужны подходящая базовая копия и непрерывная цепочка WAL, а не только каталог журнала от текущего момента.

Обычная гарантия ответа COMMIT предполагает надёжное хранилище и настройки вроде fsync = on и synchronous_commit = on. При synchronous_commit = off успех может вернуться до надёжного сохранения соответствующего WAL: недавние транзакции могут потеряться при сбое. Изменения временных и UNLOGGED-таблиц не защищаются обычным WAL так же, как данные обычных таблиц; UNLOGGED после аварии очищаются. Из этого не следует, что внутренние метаданные вообще никогда не журналируются. Настройки надёжности WAL.

fast, immediate и smart

ОстановкаКлиенты и транзакцииКонтрольная точкаСледующий запуск
smartЖдёт завершения существующих подключений.Штатная завершающая.После чистой остановки восстановление после аварии не требуется.
fastОтключает клиентов, отменяет активные транзакции.Выполняет перед остановкой.Обычный запуск после согласованного завершения.
immediateОстанавливает процессы без штатного завершения работы с данными.Нет завершающей контрольной точки.Автоматическое восстановление по WAL.

Сообщение invalid record length ... expected at least 24, got 0 в твоём журнале сопровождалось успешным завершением REDO и запуском: в данном контексте это достижение конца доступных записей WAL, а не доказательство повреждения. Оценивать похожую строку нужно вместе с последующими сообщениями.

Прошлые темы · лекция 7 целиком по смыслу

Архитектура информационных систем

Сначала раздели две разные «трёхуровневости»

ANSI-SPARC — уровни описания данных: внешний, концептуальный, внутренний. Трёхзвенная ИС — распределение функций между клиентом, сервером приложений и сервером БД. Первое отвечает «как описаны данные», второе — «где выполняются части приложения». Их нельзя подменять друг другом.

Две разные оси архитектуры

Представление данных · ANSI-SPARC

Внешние схемычто видит преподаватель / студент
↓
Концептуальная схемаstudent, subject, debt и связи
↓
Внутренняя схемафайлы, страницы, индексы

Распределение работы · три звена

Клиентпоказать журнал успеваемости
↓ запрос приложения
Сервер приложенийправа и правила выставления оценки
↓ SQL
Сервер БДхранение, запросы и транзакции

ANSI-SPARC и независимость данных

УровеньСодержаниеПример в учебном заведении
ВнешнийНесколько пользовательских представлений одних данных.Студент видит свои оценки; преподаватель — ведомость своей дисциплины.
Концептуальный / логическийОбщая структура сущностей, связей и ограничений.Студенты, дисциплины, задолженности, внешние ключи.
Внутренний / физическийРазмещение данных, файлы, индексы и способы доступа.Таблица разбита на страницы, индекс ускоряет поиск по student_id.

Физическая независимость: меняем хранение или добавляем индекс, сохраняя логическую схему и интерфейс приложения. Логическая независимость: меняем концептуальную схему, стараясь сохранить внешние представления и работу приложений, например через совместимое VIEW. Это цель разделения уровней, а не обещание, что любое изменение бесплатно и никогда не потребует правок.

Полнота, непротиворечивость и целостность

Полнота — данные достаточно описывают предметную область: например, для учёта задолженностей есть студент, дисциплина и результат. Минимальная избыточность уменьшает дублирование и расхождения. Непротиворечивость — сведения не конфликтуют друг с другом. Целостность обеспечивается ключами, ограничениями допустимых значений, ссылками, транзакциями и правильной конкурентной работой.

Уточнение лекции: не любое повторение значения запрещено — двух студентов могут звать одинаково. Дублирование запрещается там, где этого требует ключ или бизнес-правило. Ссылочную целостность обеспечивает внешний ключ; CASCADE — лишь один вариант реакции на изменение или удаление, а не обязательный способ. RESTRICT / NO ACTION тоже могут сохранять целостность.

Что такое информационная система

ИС объединяет хранение информации, прикладную обработку и представление результата пользователю. СУБД — важная часть ИС, но не всё приложение. Клиент и сервер — роли программ, а не обязательно разные физические компьютеры. Сервер приложений одновременно может быть клиентом сервера БД.

Тип ИСКак организованоПлюсы и ограничения
ЛокальнаяПриложение и данные на автономном компьютере; обычно персональная работа.Просто и дёшево, но ограничено совместное использование. Примеры лекции — Access, FoxPro, Paradox; способ обработки зависит от конкретной СУБД, не все обязаны грузить таблицу целиком.
ЦентрализованнаяОсновная БД на центральном узле, пользователи обращаются удалённо.Единое управление целостностью и доступом; нагрузка, задержки и зависимость от центрального узла.
РаспределённаяДанные и управление размещены на нескольких узлах.Локальность, гибкость, потенциальная отказоустойчивость; сложнее координация, согласование и восстановление.

Распределение может быть фрагментацией: на узлах разные части данных; или репликацией: несколько согласуемых копий. Несколько клиентов одной централизованной БД ещё не делают БД распределённой. Данные на нескольких узлах сами по себе не гарантируют доступность при любом сбое.

Другие признаки классификации ИС

На схеме лекции 7 (стр. 13) перечислены и другие независимые основания классификации. Одна система может одновременно относиться к нескольким категориям. Примеры ниже добавлены для понимания: на самом слайде перечислены признаки, а не развёрнутые классы.

Все признаки со схемы и примеры
ПризнакКак понять на примере
Характер обработки информацииУчёт операций, вычисления, поиск или анализ данных.
Масштаб примененияОт одного рабочего места до организации или группы организаций.
Функциональный признакБухгалтерия, кадры, склад: какую функцию поддерживает система.
Использование вычислительных ресурсовКак распределена работа между клиентом и серверами.
Сфера деятельностиОбразование, медицина, промышленность и другие области.
Класс технологических операцийХранение, поиск, обработка документов, расчёты.
Степень автоматизацииРучные действия, автоматизированная работа с участием человека или автоматическая обработка.
Место в управлении предприятиемКакие процессы управления поддерживает система.
Квалификация персонала и уровень управленияКто работает: операторы, специалисты, руководители.
Оперативность обработкиНасколько быстро нужны результаты; например, оперативная обработка или отложенный расчёт.
Характер использования информацииПреимущественно поиск и выдача сведений либо подготовка решений.
Централизация обработкиОбработка сосредоточена в центре или распределена по узлам.
Структурированность задачСтрого заданный алгоритм либо задача с существенной долей экспертного решения.
Режим работыНапример, пакетное выполнение или интерактивный диалог.
Концепция построенияОбщая организация: например, локальное приложение или клиент-серверная ИС.

Файл-сервер и клиент-сервер

ВопросФайл-серверКлиент-сервер с сервером БД
Что предоставляет сервер?Доступ к файлам БД.Сервис SQL и обработки данных.
Где в основном выполняется запрос?На клиенте, который получает нужные данные из общих файлов.На сервере БД; клиент получает результат.
Что передаётся по сети?Файловые данные / блоки, объём зависит от реализации.Запрос и результат, обычно меньше лишнего обмена.
Кто централизованно управляет транзакциями?Зависит от файловой СУБД и протокола доступа.Серверная СУБД.
Наш опытНе этот вариант.psql отправлял SQL PostgreSQL, который выполнял SELECT и DELETE.

Два звена: где разместить прикладную логику

Выделим три функции: представление, прикладная обработка, управление данными. В двухзвенной модели их распределяют между клиентом и сервером. Терминология RDA/DBS ниже соответствует именно предоставленной лекции.

МодельКлиентСерверКомпромисс
RDA · Remote Data AccessПредставление + основная прикладная логика.Управление данными, SQL-запросы.Легко строить клиентские приложения, но логика дублируется и обновляется на клиентах; возможен активный сетевой обмен.
DBS · DataBase Server / удалённое представлениеГлавным образом представление.Данные + прикладная логика, процедуры и триггеры.Централизованная логика и меньше её дублирования; зависимость от средств конкретной СУБД и нагрузка на сервер.
Распределённое представлениеЧасть отображения и взаимодействия.Основная обработка и данные; терминальный вариант.Простое обслуживание клиентов, высокие требования к центральному узлу. Пример лекции — X-терминалы.
Распределённая БД в двухзвенной моделиЛокальная обработка и собственные данные.Удалённые данные и обработка.Можно работать с фрагментами или копиями на обеих сторонах; сложнее согласование.

На практике функции RDA и DBS часто смешиваются: часть проверок в приложении, часть правил и процедур на сервере. «Толстый клиент» обычно содержит больше прикладной логики, «тонкий» — меньше; это характеристики распределения функций, а не размера окна или мощности видеокарты.

Три звена: AS-модель

Application Server: клиент занимается интерфейсом, сервер приложений — бизнес-логикой, сервер БД — хранением и запросами. Пример: браузер запрашивает ведомость у веб-приложения, оно проверяет права и отправляет SQL в PostgreSQL. Преимущество — независимое развитие и масштабирование слоёв; цена — дополнительный обмен, инфраструктура и сложность. Три звена можно разместить на одном компьютере: звено — логическая ответственность, узел — физическое размещение.

ODBC: совместимость через драйвер

ODBC (Open Database Connectivity) — стандартный интерфейс доступа к различным СУБД. Он помогает приложению использовать общий набор вызовов, а специфическое взаимодействие выполняет драйвер. Для PostgreSQL существует psqlODBC. ODBC не является сервером БД и не гарантирует одинаковые SQL-диалекты или поведение всех СУБД.

Приложениевызывает ODBC API
Менеджер драйвероввыбирает и загружает драйвер
ODBC-драйверпередаёт команды и ответы
Источник данныхСУБД и параметры доступа

Практика без «Практики+»

Твоя лабораторная: команды и выводы

Это разбор уже выполненной работы, а не скрипт для безусловного повторного запуска. Базы и таблицы у тебя существуют: повторный CREATE без подготовки выдаст ошибку, повторный INSERT с тем же первичным ключом тоже. В учебных SQL ниже показан первоначальный порядок. На защите важнее объяснить результат, чем снова создать объекты.

Часть 1 · установка, управление и psql

psql + SQL · выполнено
SHOW work_mem;
ALTER SYSTEM SET work_mem = '8MB';
SELECT pg_reload_conf();
\c tools_overview
SHOW work_mem;
ALTER SYSTEM RESET work_mem;
SELECT pg_reload_conf();
\c tools_overview
SHOW work_mem;

На скриншоте: значение стало 8MB, после сброса вернулось 4MB. Сервер не перезапускался: для этого параметра было достаточно перечитать конфигурацию. Отдельное переподключение — способ проверить новое значение без прежних настроек сеанса.

Содержимое ddl.sql
CREATE TABLE books (
    id integer PRIMARY KEY,
    title text NOT NULL
);
Содержимое populate.sql
INSERT INTO books (id, title) VALUES
    (1, 'Основы PostgreSQL'),
    (2, 'Транзакции'),
    (3, 'Журнал WAL');
psql + SQL · первоначальный запуск для отчёта
\c lab8_report
\! cat /home/student/lab8/ddl.sql
\! cat /home/student/lab8/populate.sql
\i /home/student/lab8/ddl.sql
\i /home/student/lab8/populate.sql
\d books
SELECT * FROM books ORDER BY id;

Файлы находятся на виртуальной машине, где запущен psql. В lab8_report вывод был CREATE TABLE, INSERT 0 3 и три строки. «0» в INSERT 0 3 — историческое поле OID, а «3» — число добавленных строк. Внутри .sql нет служебных строк SQL от shell here-document: там только SQL-команды.

Терминал · Linux
pg_lsclusters
sudo grep "^$(date +%F)" /var/log/postgresql/postgresql-16-main.log

pg_lsclusters показал 16 main, порт 5432, статус online, каталог данных и путь к журналу. grep выбрал строки за текущую дату виртуальной машины. В журнале были запуск, готовность к подключениям и плановая контрольная точка. Это текстовые сообщения, не содержимое pg_wal.

Часть 2 · два настоящих сеанса

Начальное состояние: в isolation_lab есть таблица test_rows(id integer PRIMARY KEY, value text) с одной зафиксированной строкой id = 1. Два отдельных psql — два подключения. Открыть две вкладки, но выполнять всё по очереди в одном подключении — не тот опыт.

ПорядокСеанс AСеанс B
1BEGIN ISOLATION LEVEL READ COMMITTED;
SELECT * FROM test_rows; → 1 строка
Пока не действует.
2Транзакция остаётся открытой.BEGIN;
DELETE FROM test_rows WHERE id = 1;
COMMIT;
3SELECT * FROM test_rows; → 0 строк
COMMIT;
Завершил удаление.
4Вне явного блока: INSERT INTO test_rows VALUES (1, 'Первая строка');Не действует.
5BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM test_rows; → 1 строка
Не действует.
6Транзакция остаётся открытой.Повторяет BEGIN, DELETE и COMMIT.
7SELECT * FROM test_rows; → 1 строкаУдаление уже зафиксировано.
8COMMIT;
SELECT * FROM test_rows; → 0 строк
Не действует.

Часть 3 · процессы и остановка

Терминал · Linux
ps -ww -eo pid,user,args | grep -E '[p]ostgres.*(checkpointer|background writer|walwriter)'

Ты нашёл checkpointer, background writer и walwriter. PID — текущий номер процесса ОС: после перезапуска он меняется. Это не xid и не постоянный идентификатор роли процесса.

Терминал · опыт fast
sudo pg_ctlcluster 16 main stop -m fast
sudo pg_ctlcluster 16 main start
pg_lsclusters
sudo tail -n 40 /var/log/postgresql/postgresql-16-main.log
Смысловые строки журнала fast
received fast shutdown request
aborting any active transactions
checkpoint starting: shutdown immediate
checkpoint complete
database system is shut down
...
database system is ready to accept connections
Терминал · опыт immediate
sudo pg_ctlcluster 16 main stop -m immediate --skip-systemctl-redirect
sudo pg_ctlcluster 16 main start
pg_lsclusters
sudo tail -n 50 /var/log/postgresql/postgresql-16-main.log
Смысловые строки журнала immediate
received immediate shutdown request
...
database system was interrupted
automatic recovery in progress
redo starts at ...
redo done at ...
checkpoint starting: end-of-recovery immediate wait
checkpoint complete
database system is ready to accept connections

В immediate нет завершающей контрольной точки перед остановкой; checkpoint после восстановления этому не противоречит. Отсутствие большого числа изменённых страниц не отменяет механизм REDO: небольшой объём работы в журнале — нормальный результат.

Что именно показали твои скриншоты

НаблюдениеВывод для защиты
8MB → сброс → 4MBИзменение общей конфигурации применилось и было отменено.
CREATE TABLE, INSERT 0 3, SELECT → 3 строкиФайлы действительно выполнены, структура и данные проверены.
Сегодняшние строки server logНайден журнал сообщений сервера и выполнена фильтрация по дате.
RC: 1 → 0; RR: 1 → 1 → COMMIT → 0Различие времени создания снимка, проявленное на одном удалении.
Три фоновых процессаНайдены компоненты, обслуживающие кеш страниц и WAL.
fast: checkpoint; immediate: recovery и redoСравнены штатное согласованное завершение и остановка с последующим восстановлением.

68 вопросов · сначала ответь, потом открой

Репетиция защиты

Отвечай вслух до раскрытия. Хороший ответ: определение → механизм → пример из лабы → важное ограничение. Кнопки самооценки сохраняются локально и помогают вернуться к трудным вопросам; автоматической проверки правильности здесь нет.

Транзакции

01Что такое транзакция и зачем она нужна?

Логическая единица работы, объединяющая операции в целое. Перевод денег требует вместе списать и зачислить сумму: либо фиксируем оба изменения, либо отменяем.

Вернуться к объяснению →
02Расшифруй ACID и приведи один пример для каждого свойства.

A — весь перевод или ничего. C — соблюдены правила и ограничения. I — параллельные операции наблюдают данные по правилам уровня. D — подтверждённое изменение сохраняется после сбоя при надёжной конфигурации.

Вернуться к объяснению →
03Гарантирует ли СУБД правильность любого бизнес-правила?

Нет. Она проверяет объявленные ограничения и обеспечивает механизмы транзакций. Если приложение неверно сформулировало перевод или не проверило наличие получателя, сама атомарность не исправит логику.

Вернуться к объяснению →
04Есть ли транзакция у одиночного INSERT без BEGIN?

Да. При включённом autocommit одиночная успешно выполненная команда выполняется в собственной неявной транзакции и фиксируется.

Вернуться к объяснению →
05Чем ROLLBACK TO отличается от ROLLBACK и RELEASE?

ROLLBACK отменяет всю текущую транзакцию и завершает её. ROLLBACK TO отменяет работу после savepoint, оставляя внешнюю транзакцию открытой. RELEASE удаляет точку сохранения, но не делает COMMIT.

Вернуться к объяснению →
06Можно ли откатить CREATE TABLE? А CREATE DATABASE?

В PostgreSQL CREATE TABLE обычно транзакционен и может быть отменён. CREATE DATABASE нельзя выполнять в обычном явном блоке транзакции; VACUUM — другой пример такого исключения.

Вернуться к объяснению →
07Что делать после SQL-ошибки в явной транзакции?

Обычно транзакция становится failed. Выполнить ROLLBACK либо ROLLBACK TO допустимой точки сохранения. Просто продолжать запросы в failed-транзакции нельзя.

Вернуться к объяснению →
08Чем PREPARE отличается от PREPARE TRANSACTION?

Первый готовит повторно вызываемый SQL-оператор в сеансе. Второй подготавливает текущую транзакцию к 2PC; затем нужны COMMIT PREPARED или ROLLBACK PREPARED.

Вернуться к объяснению →
09Что такое 2PC и чем он отличается от 2PL?

2PC — подготовка участников и затем общее решение о фиксации/отмене. 2PL — протокол блокировок с фазами накопления и освобождения. Это разные механизмы.

Вернуться к объяснению →

Изоляция и MVCC

10Что увидит RC после чужого DELETE и COMMIT?

Следующий обычный SELECT получит новый снимок и уже не увидит удалённую строку. Именно 1 → 0 ты наблюдал в лабораторной.

Вернуться к объяснению →
11Почему RR продолжает видеть удалённую строку?

Первое чтение зафиксировало снимок до удаления. Старая версия ещё видима этому снимку и сохраняется для него. После завершения RR новый SELECT строку не увидит.

Вернуться к объяснению →
12Когда именно создаётся снимок Repeatable Read?

При первом операторе, требующем снимка, после начала транзакции, а не обязательно в момент BEGIN. Затем он сохраняется для транзакции.

Вернуться к объяснению →
13Может ли RR увидеть собственный INSERT?

Да. Транзакция видит свои уже выполненные изменения; сохранённый снимок ограничивает видимость чужих изменений.

Вернуться к объяснению →
14Что такое снимок и зачем список активных транзакций?

Это служебные границы и список активности, а не копия таблицы. Более ранняя транзакция могла оставаться незавершённой при создании снимка — её изменения нужно исключить.

Вернуться к объяснению →
15Назови грязное, неповторяемое и фантомное чтение.

Грязное — прочитали чужое незафиксированное. Неповторяемое — повторное чтение ранее прочитанной строки изменилось после чужого COMMIT. Фантомное — изменился набор строк, подходящих условию запроса.

Вернуться к объяснению →
16Можно ли включить грязное чтение в PostgreSQL через Read Uncommitted?

Нет. Имя READ UNCOMMITTED допустимо, но поведение соответствует Read Committed, без грязного чтения.

Вернуться к объяснению →
17Возможны ли фантомы на Repeatable Read?

Стандарт допускает, но PostgreSQL предотвращает их. При этом другие аномалии сериализации в RR возможны. Всегда уточняй, спрашивают про стандарт или реализацию.

Вернуться к объяснению →
18Приведи пример аномалии сериализации без изменения одной строки.

Два врача видят, что дежурят оба, и каждый в своей RR-транзакции снимает с дежурства себя. Строки разные, но оба уходят. Последовательное корректное выполнение такого результата не дало бы.

Вернуться к объяснению →
19Что делать при serialization failure?

Повторить всю логическую транзакцию с новым чтением исходных данных. Повтор только последнего UPDATE может сохранить решение, принятое на устаревшей картине.

Вернуться к объяснению →
20Что физически делает UPDATE в модели MVCC?

Создаёт новую версию и помечает завершение жизни предыдущей. Старый снимок может продолжить видеть старую версию, новый — новую после COMMIT.

Вернуться к объяснению →
21Что означают xmin и xmax?

xmin — создатель версии; xmax в простом случае — удалившая/заменившая транзакция. Ненулевой xmax не доказывает удаления: там может отражаться блокировка или отменённая операция, важны статусы и флаги.

Вернуться к объяснению →
22Почему ctid нельзя использовать как постоянный первичный ключ?

Это физический адрес версии. Он может измениться при обновлении или перемещении данных; бизнес-идентификатор должен быть отдельным устойчивым ключом.

Вернуться к объяснению →
23Что делает VACUUM и почему ему мешают долгие транзакции?

Убирает версии, которые уже не нужны релевантным снимкам. Долгая транзакция может удерживать старый снимок и горизонт, поэтому часть старых версий пока нельзя удалить.

Вернуться к объяснению →
24Обязательно ли после VACUUM уменьшится файл таблицы?

Нет. Обычный VACUUM в основном освобождает место для повторного использования внутри таблицы; свободный хвост иногда усекается. VACUUM FULL переписывает таблицу и требует сильной блокировки.

Вернуться к объяснению →
25Зачем freeze и как связан с XID wraparound?

Номера в версиях 32-битные и циклические. Замораживание старых версий предотвращает неправильное понимание древних XID после оборота счётчика.

Вернуться к объяснению →
26Что такое clog, где он находится и как используется?

Историческое имя структуры статусов транзакций. В PostgreSQL 16 — pg_xact в PGDATA. Два бита на статус, страницы на диске и буферы в памяти. Статусы участвуют в определении видимости версий.

Вернуться к объяснению →
27Почему ROLLBACK не обязан переписывать назад каждую строку?

Версии отменённой транзакции не считаются зафиксированными и не видны другим как результат успешной работы. Старая версия остаётся подходящей; ненужные версии очистят позднее.

Вернуться к объяснению →

Блокировки

28Зачем блокировки, если есть MVCC?

MVCC даёт видимость версий, но не разрешает всем одновременно менять один ресурс. Нужна координация писателей и защита структуры таблицы от несовместимого DDL.

Вернуться к объяснению →
29Правда ли SELECT вообще никого не блокирует?

Обычный SELECT не захватывает конфликтующую строковую блокировку писателя, но берёт ACCESS SHARE на таблицу и мешает ACCESS EXCLUSIVE, например DROP. SELECT FOR UPDATE ещё и блокирует строки.

Вернуться к объяснению →
30Блокирует ли ROW EXCLUSIVE всю таблицу для других INSERT?

Нет. Это название табличного режима, совместимого с другим ROW EXCLUSIVE. Он не запрещает двум транзакциям менять разные строки.

Вернуться к объяснению →
31Что произойдёт с двумя UPDATE одной строки?

Один может ожидать завершения другого из-за строковой блокировки. Дальнейшее поведение зависит от уровня изоляции: в RC возможно продолжение на новой версии, в RR возможна ошибка сериализации.

Вернуться к объяснению →
32Когда освобождаются обычные транзакционные блокировки?

При COMMIT/ROLLBACK; блокировки после savepoint освобождаются при откате к нему. Конец отдельного оператора внутри явной транзакции обычно недостаточен.

Вернуться к объяснению →
33Чем NOWAIT отличается от SKIP LOCKED?

NOWAIT выдаёт ошибку при конфликте. SKIP LOCKED пропускает строки с конфликтующими строковыми блокировками, например при разборе очереди. Это не полная согласованная выборка всех строк.

Вернуться к объяснению →
34Чем lock_timeout отличается от deadlock_timeout?

Первый ограничивает ожидание блокировки. Второй задаёт задержку перед проверкой на deadlock и не является универсальным пределом ожидания.

Вернуться к объяснению →
35Что такое deadlock и как уменьшить риск?

Цикл: A держит X и ждёт Y, B держит Y и ждёт X. Брать объекты в одном порядке, сокращать транзакции; после ошибки повторять операцию.

Вернуться к объяснению →
36Как найти ожидающего и блокирующего?

pg_stat_activity с wait_event_type = Lock показывает ожидающих. pg_blocking_pids(pid) даёт блокирующие PID. pg_locks с NOT granted показывает неудовлетворённые запросы блокировок.

Вернуться к объяснению →
37Что такое рекомендательная блокировка?

Блокировка числового ключа по соглашению приложения. Может обозначать ещё не существующий объект. Другой код должен использовать то же соглашение; обычные операции SQL не обязаны её учитывать автоматически.

Вернуться к объяснению →
38Чем advisory lock сеанса отличается от xact lock?

Сеансовая живёт до unlock или разрыва соединения и переживает ROLLBACK. Транзакционная снимается автоматически при завершении транзакции. try-вариант не ждёт, а возвращает boolean.

Вернуться к объяснению →
39Почему session advisory locks опасны с пулом в transaction mode?

Следующая транзакция клиента может попасть на другой backend; блокировка осталась на реальном серверном сеансе, а приложение больше не управляет им ожидаемым образом.

Вернуться к объяснению →

Кеш и WAL

40Чем work_mem отличается от shared_buffers?

work_mem — базовый лимит для отдельных рабочих операций запроса. shared_buffers — общий кеш страниц таблиц и индексов. Это разные потребители памяти.

Вернуться к объяснению →
41Что такое грязный буфер? Это грязное чтение?

Грязный буфер содержит изменённую страницу, ещё не совпадающую с файлом данных. Грязное чтение — чтение чужих незавершённых изменений. Термины относятся к разным механизмам.

Вернуться к объяснению →
42Почему Buffers: shared read не всегда означает чтение с накопителя?

Страница не нашлась в кеше PostgreSQL и была загружена через ОС. Она могла уже находиться в кеше операционной системы.

Вернуться к объяснению →
43Сформулируй правило предзаписи WAL.

До сохранения изменённой страницы данных должны быть надёжно сохранены описывающие изменение записи WAL. Иначе восстановление не сможет опираться на целостную историю.

Вернуться к объяснению →
44Как COMMIT успешен, если страницы ещё не на диске?

При стандартной синхронной фиксации WAL до записи COMMIT уже сохранён. Страницы можно записать позже; после сбоя нужные изменения восстановит REDO.

Вернуться к объяснению →
45Может ли страница с незавершёнными изменениями попасть на диск?

Да, если соблюдено правило WAL. Наличие байтов на диске не делает транзакцию зафиксированной: видимость зависит от снимков и статусов.

Вернуться к объяснению →
46Где лежит WAL, что такое сегмент и LSN?

В PGDATA/pg_wal. Сегменты обычно по 16 Мбайт. LSN — позиция в логическом потоке, а не номер транзакции; разница позиций измеряет байты.

Вернуться к объяснению →
47Чем WAL отличается от server log и pg_xact?

WAL — двоичные записи восстановления. Server log — текстовые сообщения и диагностика. pg_xact — статусы транзакций, используемые для видимости.

Вернуться к объяснению →
48Зачем checkpoint и откуда начинается REDO?

Checkpoint обеспечивает сохранение требуемых страниц и базу восстановления. REDO начинается с позиции последней завершённой контрольной точки; не обязательно с самого момента её завершения.

Вернуться к объяснению →
49Кто такие checkpointer, background writer, walwriter?

Первый выполняет контрольные точки, второй заранее записывает часть грязных страниц, третий фоново пишет WAL. Backend тоже способен записывать страницы и WAL; это не исключительно фоновые обязанности.

Вернуться к объяснению →
50В чём разница fast и immediate?

Fast отменяет активные транзакции, отключает клиентов и делает завершающий checkpoint. Immediate останавливает без него; при следующем старте нужно автоматическое восстановление.

Вернуться к объяснению →
51Значит ли shutdown immediate в строке checkpoint, что использован режим immediate?

Нет. Нужно смотреть received ... shutdown request. В строке checkpoint immediate описывает способ выполнения самой контрольной точки.

Вернуться к объяснению →
52Зачем WAL кроме аварийного восстановления?

Для физической репликации, резервного копирования и PITR; logical-уровень добавляет информацию для логического декодирования. Для PITR нужны базовая копия и необходимая непрерывная история WAL.

Вернуться к объяснению →
53Гарантирует ли COMMIT сохранность при synchronous_commit = off?

Не ту же гарантию ответа, что при on: клиент может получить успех до надёжного сохранения нужного WAL. При сбое недавние подтверждённые транзакции могут потеряться.

Вернуться к объяснению →

Инструменты и запросы

54Что такое кластер PostgreSQL?

Набор баз под управлением одного экземпляра сервера, с общим каталогом данных. Это не обязательно кластер компьютеров. Одно обычное подключение выбирает одну базу.

Вернуться к объяснению →
55Что сделает ALTER SYSTEM и нужен ли restart?

Запишет переопределение в postgresql.auto.conf. Для work_mem достаточно reload. Другие параметры могут требовать restart: проверяют pg_settings и документацию.

Вернуться к объяснению →
56Почему после ALTER SYSTEM RESET значение не всегда встроенное?

RESET убирает именно переопределение из auto.conf. Остаются основной конфиг, настройки роли/базы и сеанса; итог зависит от применимых источников.

Вернуться к объяснению →
57Какие этапы проходит запрос?

Разбор с проверкой имён/типов, переписывание по правилам, планирование по статистике, выполнение выбранного плана.

Вернуться к объяснению →
58Зачем курсор и почему не всегда FETCH по одной строке?

Для получения результата порциями и сохранения позиции. FETCH по одной строке через сеть создаёт много обменов; размер порции выбирают под задачу.

Вернуться к объяснению →
59Чем локальная память отличается от общей?

Локальная принадлежит backend: состояние курсоров, кеши, рабочие операции. Общая доступна нескольким процессам: кеш страниц, WAL-буферы и структуры координации.

Вернуться к объяснению →

Архитектура ИС

60Назови уровни ANSI-SPARC.

Внешние схемы — представления групп пользователей; концептуальная — общая логическая структура; внутренняя — физическое размещение и доступ. Цель — независимость данных.

Вернуться к объяснению →
61Чем физическая независимость отличается от логической?

Физическая: меняем хранение, не меняя логический интерфейс. Логическая: меняем общую логическую схему, сохраняя внешние представления и приложения насколько возможно.

Вернуться к объяснению →
62Чем ANSI-SPARC отличается от трёхзвенной ИС?

Первое — уровни описания данных. Второе — клиент, сервер приложений, сервер БД: распределение ответственности приложения. Это разные классификации.

Вернуться к объяснению →
63Как отличить локальную, централизованную и распределённую ИС?

Локальная работает автономно с локальными данными. Централизованная предоставляет доступ к основной центральной БД. Распределённая хранит и обрабатывает данные на нескольких узлах.

Вернуться к объяснению →
64Чем файл-сервер отличается от сервера БД?

Файл-сервер предоставляет файлы и их блоки, а основной запрос обрабатывает клиент. Сервер БД сам выполняет SQL и возвращает результат.

Вернуться к объяснению →
65Сравни RDA, DBS и AS.

По лекции RDA: интерфейс и прикладная логика на клиенте, данные на сервере. DBS: интерфейс у клиента, логика и данные на сервере БД. AS: логика вынесена в отдельный сервер приложений.

Вернуться к объяснению →
66Всегда ли три звена — три компьютера?

Нет. Звенья — логическое разделение функций; их можно разместить на одном или нескольких физических узлах.

Вернуться к объяснению →
67Что такое ODBC и какие четыре компонента в его архитектуре?

Унифицированный интерфейс доступа к СУБД. Приложение, менеджер драйверов, ODBC-драйвер, источник данных. Для PostgreSQL — psqlODBC.

Вернуться к объяснению →
68Чем фрагментация отличается от репликации?

Фрагментация распределяет разные части данных, репликация создаёт копии. Оба способа требуют правил доступа и согласования; несколько клиентов одного сервера не равны распределённой БД.

Вернуться к объяснению →

Короткое повторение · 10–15 минут

Перед входом в аудиторию

Транзакция

Логическая единица работы: BEGIN → операции → COMMIT или ROLLBACK. Одиночный запрос при autocommit тоже транзакционен.

ACID

Всё или ничего; соблюдение правил; гарантии параллельного выполнения; сохранность фиксации.

RC и RR

RC — снимок на оператор. RR — от первого оператора, которому нужен снимок, до конца транзакции. Собственные изменения видны.

Наши два сеанса

RC: 1 → чужой DELETE + COMMIT → 0. RR: 1 → чужой DELETE + COMMIT → 1 → свой COMMIT → 0.

MVCC

Несколько версий; xmin — создатель, xmax — удаление/замена или сведения блокировки. Статусы и снимок решают видимость.

Очистка

VACUUM убирает ненужные версии. Старые снимки могут мешать. Freeze защищает от проблем цикличности XID.

clog

Историческое имя структуры статусов; PostgreSQL 16: pg_xact, два бита на транзакцию, файлы и буферы.

Блокировки

MVCC — что видно; locks — кто может работать с ресурсом. SELECT держит ACCESS SHARE; DROP нужен ACCESS EXCLUSIVE.

Deadlock

Цикл ожиданий, а не любое ожидание. Один порядок захвата и короткие транзакции снижают риск.

Кеш

shared_buffers — общий кеш страниц; work_mem — рабочая память отдельных операций. Грязный буфер ≠ грязное чтение.

WAL

Предзапись: WAL раньше страницы. Синхронный COMMIT ждёт сохранения WAL, не всех страниц. После сбоя — REDO.

Фоновые процессы

walwriter — WAL; background writer — часть грязных страниц; checkpointer — контрольные точки. Backend тоже пишет.

fast / immediate

Fast: checkpoint перед остановкой. Immediate: без него, затем recovery, redo и checkpoint после восстановления.

Архитектура

ANSI-SPARC: внешний / концептуальный / внутренний. AS: интерфейс / логика / данные. RDA оставляет логику клиенту, DBS — серверу БД.

ODBC

Приложение → менеджер драйверов → драйвер → источник данных. Унификация доступа не делает диалекты SQL одинаковыми.

Пять фраз, на которых легко потерять точность

Не говориСкажи точнее
«COMMIT сразу записал всю таблицу на диск».Нужный WAL сохранён; страницы могут записаться позже.
«Снимок — копия таблицы».Снимок — метаданные для выбора видимых версий.
«MVCC отменяет все блокировки».MVCC уменьшает конфликты чтения и записи; блокировки остаются.
«В RR возможны фантомы в PostgreSQL».Стандарт допускает, реализация PostgreSQL предотвращает.
«WAL, clog и текстовый лог — одно».WAL — восстановление; pg_xact — статусы; server log — диагностика.

Карта лекций и уточнения

Откуда взят материал

Номера ниже — страницы PDF, начиная с первой; они могут не совпадать с номерами, напечатанными на слайдах. Повторяющиеся слайды объединены. Устные объяснения и примеры в конспекте — учебный пересказ, а не дословные цитаты. Две лекции DEV прочитаны через распознавание изображений и визуальную проверку ключевых схем.

Исходник и страницыЧто включеноГлава
Лекция DEV 1 · стр. 3–10Кластер, установка, расширения, pg_ctlcluster, пути и server log.Инструменты
Лекция DEV 1 · стр. 11–16Конфигурация, ALTER SYSTEM, SET, SHOW, pg_settings.Инструменты
Лекция DEV 1 · стр. 17–26Подключение psql, справка, форматы, файлы, переменные, .psqlrc.Инструменты
Лекция DEV 2-4 · стр. 3–8Клиент-серверный протокол, транзакции, autocommit, savepoint.Транзакции
Лекция DEV 2-4 · стр. 9–23Обработка запроса, PREPARE, курсоры, процессы, пул, память, хранение и расширяемость.Путь запроса
Лекция DEV 2-4 · стр. 26–43Снимки, уровни, видимость xmin/xmax и версии.Изоляция, MVCC
Лекция DEV 2-4 · стр. 44–50Очистка, горизонт, блокировки, статусы.MVCC, Блокировки
Лекция DEV 2-4 · стр. 53–67Кеш, вытеснение, EXPLAIN BUFFERS, WAL, LSN, checkpoint, восстановление, процессы, wal_level.Кеш и WAL
Лекция 5. Транзакции · стр. 2–34Определение, виды, TCL, savepoint, DDL/DML, ACID и WAL.Транзакции, WAL
Лекция 5. Транзакции · стр. 35–50Изоляция, MVCC, аномалии, уровни и 2PC.Изоляция, 2PC
Лекция 6. Блокировки · стр. 4–34Механизм, владельцы, сроки, таблицы, строки, страницы и тайм-ауты.Блокировки
Лекция 6. Блокировки · стр. 36–53Advisory locks, ошибки использования, deadlock и мониторинг.Блокировки
Лекция 7. ИС · стр. 3–28ANSI-SPARC, требования к данным, классификация ИС, файл-сервер и клиент-сервер.Архитектура ИС
Лекция 7. ИС · стр. 30–66Функции, двухзвенные модели, RDA/DBS, AS и ODBC.Архитектура ИС

Где уточнены формулировки лекций

Официальные источники для точных деталей

Основной конспект, шрифты и схемы работают без сети. Интернет нужен только для перехода к внешней документации. Оригиналы лекций доступны в каталоге lectures этого сайта. Конспект не меняет настройки сервера и не запускает приведённые команды.