Создание записей XLOG в PostgreSQL
Настало время поговорить о процессе создания записей XLOG.
Для начала выполним следующую операцию:
testdb=# INSERT INTO tbl VALUES ('A');
При выполнении вышеприведенного запроса вызывается внутренняя функция exec_simple_query(). Псевдокод функции exec_simple_query() показан ниже:
exec_simple_query() @postgres.c
(1) ExtendCLOG() @clog.c /* Write the state of this transaction * "IN_PROGRESS" to the CLOG. */ (2) heap_insert()@heapam.c /* Insert a tuple, creates a XLOG record, * and invoke the function XLogInsert. */ (3) XLogInsert() @xloginsert.c (9.4 or earlier, xlog.c) /* Write the XLOG record of the inserted tuple * to the WAL buffer, and update page's pd_lsn. */ (4) finish_xact_command() @postgres.c /* Invoke commit action.*/ XLogInsert() @xloginsert.c (9.4 or earlier, xlog.c) /* Write a XLOG record of this commit action * to the WAL buffer. */ (5) XLogWrite() @xloginsert.c (9.4 or earlier, xlog.c) /* Write and flush all XLOG records on * the WAL buffer to WAL segment. */ (6) TransactionIdCommitTree() @transam.c /* Change the state of this transaction * from "IN_PROGRESS" to "COMMITTED" * on the CLOG. */
В следующих параграфах дается объяснение каждой части псевдокода, что облегчит понимание процесса создания записей XLOG. Смотрите рисунки 107 и 108.
(1) Функция ExtendCLOG() записывает состояние транзакции 'IN_PROGRESS' в CLOG;
(2) Функция heap_insert() вставляет кортеж в целевую страницу в общем буферном пуле, создает запись XLOG для этой страницы и вызывает функцию XLogInsert();
(3) Функция XLogInsert() создает запись XLOG, созданную функцией heap_insert(), в буфер WAL по адресу LSN_1, а затем обновляет pd_lsn измененной страницы с LSN_0 до LSN_1;
(4) Функция finish_xact_command(), вызванная для фиксации этой транзакции, создает запись XLOG для фиксации, а затем функция XLogInsert() записывает эту запись в буфер WAL по адресу LSN_2.
Формат записей XLOG в версии 9.4.
(5) Функция XLogWrite() записывает и стирает все записи XLOG в буфере WAL в файл сегмента WAL.
Если параметр wal_sync_method имеет значение 'open_sync' или 'open_datasync', записи записываются синхронно, поскольку функция записывает все записи с помощью системного вызова open() с флагом 'O_SYNC' или 'O_DSYNC'.
Если параметр имеет значение 'fsync', 'fsync_writethrough' или 'fdatasync', то будет выполнен соответствующий системный вызов - fsync(), fcntl() с опцией F_FULLFSYNC или fdatasync(). В любом случае все записи XLOG гарантированно будут записаны в хранилище;
(6) Функция TransactionIdCommitTree() изменяет состояние этой транзакции с 'IN_PROGRESS' на 'COMMITTED' в CLOG.
В примере, приведенном выше, действие фиксации вызвало процесс создания записей XLOG в сегменте WAL, но такая запись может быть вызвана и любым из следующих действий:
Одна выполняющаяся транзакция зафиксирована или прервана;
Буфер WAL заполнен большим количеством кортежей. (Размер буфера WAL устанавливается параметром wal_buffers.)
Если происходит хотя бы одно из вышеперечисленных событий, все записи WAL в буфере WAL записываются в файл сегмента WAL, независимо от того, были ли зафиксированы транзакции или нет.
Считается само собой разумеющимся, что операции DML (Data Manipulation Language) записывают не только XLOG-записи, но и операции, не относящиеся к DML. Как было отмечено чуть выше, действие фиксации записывает запись XLOG, содержащую идентификатор зафиксированной транзакции. Еще один пример - действие контрольной точки, которое записывает запись XLOG, содержащую общую информацию о контрольной точке.
Кроме того, в особых случаях оператор SELECT создает XLOG-записи. Например, если во время выполнения оператора SELECT происходит удаление ненужных кортежей и дефрагментация нужных кортежей на страницах с помощью HOT (Heap Only Tuple), то в буфер WAL записываются XLOG-записи измененных страниц.
Примечание: Прямой ввод/вывод
PostgreSQL версии 15 и более ранние версии не поддерживают функцию прямого ввода/вывода, хотя разработчики уже давно хотели внедрить ее (предпосылки ее появления в PostgreSQL подробно описаны в данных статьях: статья 1 и статья 2).
В версии 16 появилась опция debug-io-direct ,предназначенная для разработчиков. Благодаря ей можно существенно улучшить использование прямого ввода-вывода в PostgreSQL.





