За счет чего достигается durability в PostgreSQL?
Что проверяют
Знаете ли вы механизм, а не только аббревиатуру WAL: что именно попадает на диск в момент COMMIT. Следом спрашивают, чем synchronous_commit = off отличается от fsync = off, и что делать в Go-коде, если соединение оборвалось на коммите.
Как отвечать
Durability это буква D в ACID: подтверждённая транзакция переживает падение сервера. В PostgreSQL её обеспечивают:
- WAL (журнал упреждающей записи): любое изменение сначала описывается в журнале. При
COMMITсервер сбрасывает журнал до записи о коммите на диск и только потом отвечает клиенту. Страницы таблиц в этот момент меняются лишь вshared_buffersи попадают в файлы позже; - контрольные точки: checkpointer и background writer постепенно пишут грязные страницы на диск. После сбоя сервер берёт последнюю контрольную точку и проигрывает журнал от неё;
full_page_writes: при первом изменении страницы после контрольной точки в журнал пишется её полный образ. Это защита от наполовину записанной страницы при отключении питания;fsync: включён по умолчанию. Выключенный ускоряет запись, но после сбоя грозит не потерей, а повреждением кластера;synchronous_commit: по умолчаниюon. Приoffклиент получает ответ до сброса журнала: при сбое пропадут последние транзакции, но база останется целой. Его ставят и точечно:SET LOCAL synchronous_commit = off. При синхронной репликацииonждёт ещё и записи на реплике, аremote_applyеё применения.
И диск должен честно выполнять fsync: кэш записи без батареи может подтвердить то, что ещё не записано.
Где спотыкаются
Считают, что при коммите данные пишутся в файлы таблиц. Пишется только журнал, последовательно, иначе каждая транзакция стоила бы случайной записи по диску.
Путают fsync = off и synchronous_commit = off. Первое грозит повреждением базы, второе только потерей последних подтверждений.
Относят к durability бэкапы и контрольные суммы страниц: бэкап спасает от потери сервера целиком, контрольные суммы лишь обнаруживают повреждение. А в Go-коде сетевую ошибку на tx.Commit() трактуют как откат, хотя транзакция могла закоммититься. Статус неизвестен, спасает идемпотентность.