Добавил:
ИВТ (советую зайти в "Несортированное")rnПИН МАГА Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Database 2024 / Books / Мониторинг PostgreSQL.pdf
Скачиваний:
26
Добавлен:
20.11.2024
Размер:
6.87 Mб
Скачать

166Глава 6. Журнал упреждающей записи

Результат показывает, что наибольший объем записи в журнал генерирует запрос, связанный

собновлением строк в pgbench_accounts (678 ГБ), с большим отрывом опережающий запрос, занявший второе место.Получить данные из мониторинга можно следующим запросом:

#topk_avg(5,

sum by (queryid,query) ( rate(postgres_statements_wal_bytes_all_total{

service_id="primary"

}[1m]) + on(database,user,queryid) group_left(query)

0 * postgres_statements_query_info{service_id="primary"} ), "other")

График на рис. 6.5 подтверждает результат запроса к pg_stat_statements: в динамике видно, что запрос на обновление pgbench_accounts пишет в среднем примерно 500 КБ в секунду и по объему записи значительно опережает остальные запросы.

Рис. 6.5.Запросы,пишущие в журнал больше остальных

6.3. Архивирование журнала

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

6.3. Архивирование журнала

167

При таком подходе требуется постоянное архивирование сегментов журнала в отдельное от СУБД хранилище1. По умолчанию архивирование сегментов журнала выключено и требует отдельной настройки. При включении архивирования СУБД запустит фоновый процесс archiver. Когда запись в отдельный сегмент журнала завершается и он готов для архивирования, archiver запускает команду архивирования из параметра archive_command и ждет ее завершения. Если команда завершилась ошибкой, через некоторое время процесс предпримет еще одну попытку заархивировать сегмент и будет повторять такие попытки до тех пор, пока команда не завершится успехом. Очевидно, что это может привести к ситуации, когда из-за «сломанного» архивирования начнет увеличиваться количество сегментов, и в какой-то момент это может привести к исчерпанию свободного места на диске и аварийной остановке СУБД при попытке записи в журнал.Притаких рисках у администратора появляется еще одна обязанность—наблюдение за работой архивирования,отслеживание потенциальных ошибок и их устранение.

Представление pg_stat_archiver

Для отслеживания процесса архивирования есть представление pg_stat_archiver, которое содержит всего одну строку со следующими полями:

archived_count—общее количество сегментов,отправленных в архив;

last_archived_wal—имя последнего сегмента,отправленного в архив;

last_archived_time—отметка времени последней отправки сегмента в архив;

failed_count—количество неудачных попыток отправки в архив;

last_failed_wal—имя сегмента,при отправке которого произошла последняя ошибка;

last_failed_time — отметка времени, когда произошла последняя ошибка при отправке в архив;

stats_reset—отметка времени,когда была сброшена статистика.

Втестовом окружении настроено псевдоархивирование: когда наступает время отправки сегмента в архив,вызывается команда /bin/true,которая ничего неделаетилишьвозвращаеткод успешного завершения.Тем не менее это позволяет увидеть статистику архивирования:

# TABLE pg_stat_archiver;

-[ RECORD 1 ]------

+------------------------------

archived_count

| 45711

last_archived_wal

| 00000001000000B20000009D

last_archived_time

| 2022-12-07 06:43:05.091157+00

failed_count

| 21

last_failed_wal

| 000000010000004600000073

last_failed_time

| 2022-11-17 05:52:27.826036+00

stats_reset

| 2022-11-04 05:01:49.427562+00

1 postgrespro.ru/docs/postgresql/current/continuous-archiving

168Глава 6. Журнал упреждающей записи

Чтобы понять,как лучше использовать эту статистику,важно понимать классы проблем,которые могут возникнуть при архивировании журнала:

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

ошибка при выполнении команды архивирования,например из-за ошибки в скрипте или его отсутствия;

зависание процесса (по каким-то неизвестным причинам), ответственного за непосредственную отправку в архив;

зависаниепроцессаarchiver—этомаловероятныйсценарий,однакоегонельзяисключать полностью.

Впервых двух сценариях необходимо отслеживать количество неудачных попыток архивирования. А если архивирование уже сломалось, важно понимать и то, как долго оно находится в таком состоянии. Для оценки хорошо подходят поля failed_count и last_archived_time. Привозникновенииошибоксчетчикfailed_countначнетувеличиваться(аростarchived_count остановится). Факт увеличения количества ошибок более красноречив, чем отсутствие попыток архивирования, ведь система может быть не под нагрузкой и простаивать, а отсутствие успешных попыток архивирования может быть нормальным. То же самое справедливо и для времени: возраст now() - last_archived_time будет увеличиваться до тех пор, пока архивирование не будет восстановлено, и тоже является хорошим маркером наличия проблем с архивированием.

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

С проблемами вроде зависаний дело обстоит сложнее: в этой ситуации команда запустилась, но не может завершиться, а процесс архивирования ожидает ее завершения. В таком случае archived_count, failed_count и last_failed_time остаются без изменений, но при этом воз-

раст now() - last_archived_time начинает расти, что указывает на остановку архивирования. На рис. 6.7 изображен график, демонстрирующий ту же самую остановку архивирования, что и на рис. 6.6. В среднем архивирование сегментов выполняется каждые 54 секунды, но был период,когда время увеличилось до 11 минут.

Ориентироваться на возраст последней успешной отправки удобно в активных системах с интенсивнойипостояннойзаписьювжурнал,гдеархивированиесегментовпроисходитрегулярно.Для систем с малой активностью, эпизодической и небольшой записью в журнал, где между архивированием даже двух сегментов может проходить много времени, большой возраст now() - last_archived_time может и не указывать на проблему. Конечно, для принудительного архивирования можно использовать тайм-аут (см. archive_timeout), по истечении которого выполняется переключение на запись в следующий сегмент журнала, а предыдущий отправляется в архив.

6.3. Архивирование журнала

169

Рис. 6.6.Успешные и неудачные попытки отправки сегментов в архив

Рис. 6.7.Время с момента последней успешной отправки сегмента в архив

Очередь архивирования

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

Внутри каталога pg_wal естьподкаталогarchive_status с набором файлов,описывающих статус архивирования конкретных сегментов.

170

Глава 6.

Журнал упреждающей записи

 

 

 

 

 

# ls -l /var/lib/postgresql/data/pg_wal/archive_status/

 

-rw-------

1

postgres postgres

0

Nov

4

05:03 000000010000000000000011.0001F7A0.backup.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:00 00000001000000B7000000D7.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:01 00000001000000B7000000D8.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:02 00000001000000B7000000D9.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:04 00000001000000B7000000DA.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:05 00000001000000B7000000DB.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:06 00000001000000B7000000DC.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:06 00000001000000B7000000DD.done

 

-rw-------

1

postgres postgres

0

Dec

8

06:08 00000001000000B7000000DE.done

В этом каталоге нас интересуют файлы с расширениями ready и done. Статус ready указывает на то, что соответствующий сегмент готов для архивирования, а статус done — на то, что сегмент был успешно отправлен в архив. Таким образом, чтобы получить число сегментов в очереди на отправку, нам нужно лишь подсчитать количество файлов с расширением ready. Размерочередиможноперевестивбайты(умножитьнаразмерсегмента,поумолчанию16МБ) и получить представление о том, сколько места на диске занимают сегменты, требующие архивирования. Для подсчета потребуется функция pg_ls_archive_statusdir либо ее более универсальный аналог pg_ls_dir:

#SELECT count(*)

FROM pg_ls_archive_statusdir()

WHERE name ~'.ready'; count

-------

0

В тестовом окружении настроено псевдоархивирование командой /bin/true, при вызове которой не происходит реального копирования, однако и такое архивирование отражается в статистике в pg_stat_archiver. В целях экспериментов архивирование можно «сломать», указав вместо /bin/true команду /bin/false.

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

#SELECT *, now() - last_archived_time AS last_archived_age FROM pg_stat_archiver;

-[ RECORD 1 ]------

+------------------------------

archived_count

| 47058

last_archived_wal

| 00000001000000B7000000E0

last_archived_time

| 2022-12-08 06:10:14.254712+00

failed_count

| 0

last_failed_wal

|

last_failed_time

|

stats_reset

| 2022-11-04 05:01:49.427562+00

last_archived_age

| 00:00:09.227001

6.3. Архивирование журнала

171

Теперь следует изменить параметр archive_command:

#ALTER SYSTEM SET archive_command TO '/bin/false';

ALTER SYSTEM

#SELECT pg_reload_conf();

pg_reload_conf

----------------

t

Понаблюдаем за тем,что теперь происходит в статистике:

# SELECT *, now() - last_archived_time AS last_archived_age FROM pg_stat_archiver;

-[ RECORD 1 ]------

+------------------------------

archived_count

| 47061

last_archived_wal

| 00000001000000B7000000E3

last_archived_time

| 2022-12-08 06:13:06.971114+00

failed_count

| 75

last_failed_wal

| 00000001000000B7000000E4

last_failed_time

| 2022-12-08 06:17:23.115775+00

stats_reset

| 2022-11-04 05:01:49.427562+00

last_archived_age

| 00:04:21.452935

Счетчик archived_count остановился, а failed_count начал расти; время с момента последней успешной попытки архивирования в добавленном поле last_archived_age также растет и достигло четырех минут.Проверим,что в каталоге статусов:

#SELECT *

FROM pg_ls_archive_statusdir() ORDER BY modification;

name

| size |

modification

-----------------------------------------------

+

------

+

------------------------

 

000000010000000000000011.0001F7A0.backup.done |

0

|

2022-11-04 05:03:21+00

00000001000000B7000000E0.done

|

0

|

2022-12-08 06:10:14+00

00000001000000B7000000E1.done

|

0

|

2022-12-08 06:11:08+00

00000001000000B7000000E2.done

|

0

|

2022-12-08 06:12:06+00

00000001000000B7000000E3.done

|

0

|

2022-12-08 06:13:06+00

00000001000000B7000000E4.ready

|

0

|

2022-12-08 06:14:15+00

00000001000000B7000000E5.ready

|

0

|

2022-12-08

06:15:17+00

00000001000000B7000000E6.ready

|

0

|

2022-12-08

06:16:19+00

00000001000000B7000000E7.ready

|

0

|

2022-12-08

06:17:29+00

Появились файлы с расширением ready,можно их посчитать и определить количество сегментов в очереди на архивирование:

#SELECT count(*)

FROM pg_ls_archive_statusdir() WHERE name ~'.ready';

count

-------

4

172Глава 6. Журнал упреждающей записи

Соответствующие измерения можно отразить на графике (рис.6.8):

Рис. 6.8.Очередь архивирования в байтах

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

После экспериментов не забываем откатить конфигурацию:

#ALTER SYSTEM RESET archive_command;

#SELECT pg_reload_conf();

Резюме

Журнал упреждающей записи — важный компонент любой СУБД, который хранит историю всех изменений.

Журнал представляет собой непрерывную последовательность файлов-сегментов.

Для детального анализа содержимого журнала используются утилита pg_waldump и рас-

ширение pg_walinspect.

Дляотслеживанияобщейактивности,связаннойсжурналом,используетсяпредставление pg_stat_wal.

pg_stat_statements содержит статистику записи в журнал для конкретных запросов.

Журнал также используется для резервного копирования и репликации.

Журнал можно архивировать для задач резервного копирования и восстановления.

Для отслеживания архивирования используется представление pg_stat_archiver.

Отслеживание очереди архивирования — наиболее универсальный способ выявления проблем.

Соседние файлы в папке Books