Рубрики
Без рубрики

Как работает реляционная база данных

Автор оригинала: Vlad Mihalcea.

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

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

Доступ к диску осуществляется медленно. С другой стороны, память на порядки быстрее даже, чем твердотельные накопители. По этой причине поставщики баз данных стараются как можно дольше задерживать доступ к диску. Независимо от того, говорим ли мы о таблицах или индексах, данные разделяются на страницы определенного размера (например, 8 КБ).

Когда ему нужно прочитать данные (таблицы или индексы), реляционная база данных сопоставит страницы на диске с буферами памяти. Когда требуется изменить данные, реляционная база данных изменяет страницы в памяти. Для синхронизации страниц в памяти с диском необходимо выполнить сброс (например, fsync ).

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

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

Поскольку изменения в памяти могут быть доступны для нескольких одновременных транзакций, для обеспечения целостности данных необходимо использовать механизм управления параллелизмом (например, 2PL и MVCC ). Поэтому, как только транзакция изменила строку таблицы, незафиксированные изменения применяются к структурам в памяти, в то время как предыдущие данные временно хранятся в структуре журнал отмены только для добавления.

Хотя в Oracle и MySQL эта структура называется *журнал отмены*, в SQL Server эту роль играет журнал транзакций. В PostgreSQL нет журнала отмены, но та же цель достигается с помощью структуры таблиц с несколькими версиями, поскольку таблицы могут хранить несколько версий одной и той же строки. Однако все эти структуры данных используются для обеспечения возможности отката, что является обязательным требованием для атомарности.

Если текущая транзакция откатывается, журнал отмены будет использоваться для восстановления страниц в памяти на момент начала транзакции.

После фиксации транзакции изменения в памяти должны сохраняться. Однако это не означает, что каждая фиксация транзакции будет инициировать fsync . На самом деле, это было бы очень вредно для производительности приложения. Однако из свойств транзакции ACID мы знаем, что зафиксированная транзакция должна обеспечивать долговечность , а это означает, что зафиксированные изменения должны сохраняться, даже если мы отключим компонент database engine.

Итак, как реляционная база данных обеспечивает долговечность без выдачи fsync при каждой фиксации транзакции?

Вот тут-то и вступает в игру журнал повтора . Журнал повтора также представляет собой дисковую структуру, доступную только для добавления, в которой хранятся все изменения, внесенные в данную транзакцию. Таким образом, когда транзакция фиксируется, каждое изменение страницы данных также будет записываться в журнал повтора . По сравнению с очисткой неизменного количества страниц данных запись в журнал повтора выполняется очень быстро, поскольку последовательный доступ к диску намного быстрее, чем произвольный доступ. Следовательно, это также позволяет совершать транзакции быстро.

Хотя в Oracle и MySQL эта структура называется *журнал повтора*, в SQL Server эту роль также играет журнал транзакций. Вместо этого PostgreSQL называет это журналом предварительной записи (WAL).

Но тогда, когда изменения в памяти сбрасываются на диск?

Система реляционных баз данных использует контрольные точки для синхронизации “грязных” страниц в памяти с их дисковыми аналогами. Чтобы избежать перегрузки трафика ввода-вывода, синхронизация обычно выполняется частями в течение более длительного периода времени.

Но что произойдет, если реляционная база данных выйдет из строя перед сбросом всех грязных страниц в памяти на диск?

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

Эти конструктивные соображения были приняты для преодоления высокой задержки дисковых хранилищ при одновременном обеспечении гарантий постоянного хранения. Таким образом, журнал отмены необходим для обеспечения атомарности (возможности отката), в то время как журнал повтора необходим для обеспечения долговечности страниц на диске (таблиц и индексов).