Часто встречающиеся проблемы и пути их устранения#

Проблема:

Если включено расширение pg_pathman, pg_repack входит в бесконечный цикл при обработке его таблиц, что приводит к реорганизации не отдельной таблицы, а всей базы.

Решение:

Явно исключить pg_pathman из обработки с помощью ключа: -C pg_pathman.

Проблема:

При работе pg_bouncer в транзакционном режиме может наблюдаться ошибка:

ERROR: prepared statement "S_2" does not exist

Решение:

В качестве временного решения рекомендуется, до момента устранения данного ограничения, либо:

  • отключить prepare statement;

  • включить сессионный режим pgBouncer;

  • выставить prepareThreshold=0 в параметры jdbc (возможно увеличение latency). Пример строки подключения JDBC:

    JDBC:postgresql:127.0.0.1:6543/dbname?prepareThreshold=0
    

Дополнительно: рекомендуется завершать открытые соединения в случае если они не используются.

Проблема:

СУБД не переключилась в режим резервного копирования (РК).

pg_is_in_backup
-----------------
f

Процессы РК не запустились. На стороне СРК ошибки:

[Critical] From: test@test.ru "pvlad-sverk0001_PG_FULL"  Time: 7/24/2022 22:53:13
      04_manage_backup.sh on host <hostname>
      Script execution timed out => aborted by the Session Manager

[Critical] From: test@test.ru "pvlad-sverk0001_PG_FULL"  Time: 7/24/2022 22:53:13
      Session remote exec script "04_manage_backup.sh start"
      on host <hostname> failed.

[Critical] From: test@test.ru "pvlad-sverk0001_PG_FULL"  Time: 7/24/2022 22:53:13
      None of the Disk Agents completed successfully.
      Session has failed.

Из /var/log/messages:

Jul 24 22:23:13 pvlad-sverk0001 xinetd[1400]: START: omni pid=2697897 from=<IP-адрес>

Решение:

Возможно, БД находится в режиме неисключительной резервной копии до сих пор. Если это так, то:

  • стоит вывести ее из режима pg_stop_backup(false). И настроить для контрольных точек параметр checkpoint_timeout, чтобы они выполнялись не реже 10-15 минут;

  • или поправить скрипт, где разрешить pg_start_backup выполнять дополнительную контрольную точку:

    pg_start_backup ( '<текст>', TRUE, FALSE )
    

Проблема:

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

Решение:

Уменьшить work_mem — это позволит не выбиваться за пределы памяти.

Проблема:

Потеря соединений с БД. Из лога pgbouncer:

2022-07-12 12:15:01.824 MSK [2310345] WARNING C-0x7f9b50ab0838 (328863): (nodb)/aposs_adm@<IP-адрес> authentication context expired. user: db=aposs user=aposs_adm
2022-07-12 12:15:01.824 MSK AUDIT aposs/aposs_adm@<IP-адрес> login attempt tls=no
2022-07-12 12:15:01.825 MSK AUDIT aposs/aposs_adm@<IP-адрес> send auth startup packet
2022-07-12 12:15:01.895 MSK AUDIT aposs/aposs_adm@<IP-адрес> auth server login ok
2022-07-12 12:15:41.512 MSK [2310345] LOG stats: 53 xacts/s, 97 queries/s, in 45910 B/s, out 19511 B/s, xact 1097 us, query 424 us, wait 0 us
2022-07-12 12:16:05.629 MSK AUDIT aposs/aposs_adm@<IP-адрес> closing because: client close request (age=545s)
2022-07-12 12:16:41.512 MSK [2310345] LOG stats: 53 xacts/s, 97 queries/s, in 45956 B/s, out 19530 B/s, xact 1126 us, query 427 us, wait 10 us
2022-07-12 12:17:07.182 MSK AUDIT aposs/aposs_adm@<IP-адрес> closing because: client unexpected eof (age=3298s)
2022-07-12 12:17:07.182 MSK AUDIT aposs/aposs_adm@<IP-адрес> closing because: client unexpected eof (age=3623s)
2022-07-12 12:17:07.182 MSK AUDIT aposs/aposs_adm@<IP-адрес> closing because: client unexpected eof (age=3623s)
2022-07-12 12:17:07.182 MSK AUDIT aposs/aposs_adm@<IP-адрес> closing because: client unexpected eof (age=3623s)
2022-07-12 12:17:30.658 MSK AUDIT aposs/aposs_adm@<IP-адрес> connection received

Причины:

  1. В логе очень много сообщений вида:

    AUDIT aposs/aposs_adm@<IP-адрес> closing because: client unexpected eof (age=1815s)
    

    Данное сообщение свидетельствует о том, что pgbouncer обнаружил отсутствие клиента с противоположной стороны. Возможно, это обрывы сети, но вероятнее некорректное закрытие приложения (без закрытия пула соединений).

  2. По причине 1 появляются сообщения вида:

    AUDIT aposs/aposs_adm@<IP-адрес> closing because: unclean server (age=1564s)
    

    Данные события происходят когда теряется связь между клиентом и pgbouncer в момент передачи запроса, либо результатов запроса (pgbouncer закрывает ставшую ненужной сессию в которой могли остаться незафиксированные изменения). Данное событие является прямым следствием причины 1.

  3. В логе периодически встречаются сообщения вида:

    AUDIT aposs/aposs_adm@<IP-адрес> closing because: server_lifetime (age=3600s)
    

    Данное сообщение говорит о том, что pgbouncer закрыл соединение по достижению параметра по умолчанию server_lifetime. Данное событие может приводить к причине 1 (например, приложение написано так, что падает при обрыве сессии).

Решение:

В первую очередь нужно понять почему происходит падение приложения (причина 1). Штатно ли закрываются пулы HikariCP или нет.

Дополнительно можно увеличить параметр server_lifetime pgbouncer до 7200s и явно задать параметр maxLifetime в HikariCP (например 1800s). Параметр maxLifeTime в HikariCP определяет время жизни соединения, после которого его нужно пересоздать (касается только неактивных соединений, поэтому, если есть длинные транзакции, нужно определить максимальное время их выполнения и задать выше этого времени параметр server_lifetime pgbouncer).

Проблема:

При работе с хранилищем паролей (утилита pg_auth_config), а именно при удалении записи (remove) или очистке хранилища паролей (reset) возникает ошибка:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid

Решение:

Запустите выполнение команды с ключом -s (без подтверждения операции):

-- Удаление записи из хранилища паролей
pg_auth_config  remove -s -h <host> -p 5433 -U <username> -d <database>

Проблема:

Для транзакций не имеющих флаг READ ONLY при выполнении DML на мастер-узле возникают ошибки вида

ERROR:  cannot execute UPDATE in a read-only transaction

Причины:

PgBouncer в транзакционном режиме по умолчанию не сбрасывает настройки сессии в сторону БД. Как результат может возникает ситуация, когда RW транзакция попадает в сессию с параметрами для RO транзакции.

Решение:

  1. Настройте принудительный сброс параметров для сессий в pgBouncer. Для этого добавьте/скорректируйте следующие параметры:

    $ grep server_reset_query /etc/pgbouncer/pgbouncer.ini
    server_reset_query_always = 1
    server_reset_query = DISCARD ALL
    

Внимание!

В этом случае будут сбрасываться все параметры сессии, в том числе search_path, set role и т.д.

  1. Примените настройки:

    sudo systemctl reload pgbouncer
    

Проблема:

Pgbouncer блокирует УЗ при включенной сквозной аутентификации.

Решение:

  • Компенсационные меры:

    Создайте bash скрипт c текстом sudo systemctl restart pgbouncer и с именем reload_pgbouncer.sh, поместите его в каталог /etc/patroni/. В файле конфигурации postgres.yml, в разделе postgresql: добавьте следующую строку:

    callbacks:
    on_restart: /etc/patroni/reload_pgbouncer.sh
    

    В результате после перезагрузки экземпляра СУБД, Patroni выполнит скрипт reload_pgbouncer.sh, который перезагрузит PgBouncer и соответственно токен клиента обновится.

  • Обходное решение:

    Отключите использование сквозной аутентификации.

Проблема:

Не работает аутентификация по сертификатам, если не настроен TLS.

Пример:

  • Ошибка при подключении через SSL (сертификаты) к порту 6544 (PgBouncer). При этом получается подключиться напрямую в Pangolin к порту 5433, пароль не проверяется и устанавливается зашифрованное соединение:

    [postgres@<hostname> /home/postgres]$ psql -p 5433 -U postgres
    
    psql (11.12)
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
    Type "help" for help.
    
    postgres=#
    
  • Аутентификация по порту 6544 (через pgBouncer) прошла не успешно. Соединение не установлено:

    [postgres@<hostname> /home/postgres]$ psql -p 6544 -U postgres
    psql: ERROR: authentication failed for user "postgres": host rejected
    
  • Лог PgBouncer пишет следующее:

    2021-12-29 11:22:54.889 MSK AUDIT postgres/postgres@<IP-адрес> login attempt tls=no
    2021-12-29 11:22:54.889 MSK AUDIT postgres/(nouser)@<IP-адрес> new connection to auth server (from <IP-адрес>)
    2021-12-29 11:22:54.897 MSK AUDIT postgres/postgres@<IP-адрес> send auth startup packet
    2021-12-29 11:22:54.948 MSK AUDIT postgres/postgres@<IP-адрес> auth server login failed
    2021-12-29 11:22:54.948 MSK AUDIT postgres/postgres@<IP-адрес> closing because: authentication failed for user "postgres": host rejected (age=0s)
    2021-12-29 11:22:54.948 MSK [3254560] WARNING C-0xabe600 (2): postgres/postgres@<IP-адрес> pooler error: authentication failed for user "postgres": host rejected
    

Решение:

Решением является настройка TLS параметров соединения между PgBouncer и Pangolin в файле конфигурации pgbouncer.ini. А именно необходимо раскомментировать все строчки под TLS SETTINGS, указать пути до актуальных сертификатов.

Проблема:

Файловая система /pgarclogs заполнена на 100%.

Решение:

  1. Очистите каталог /pgarclogs/wal/clustername (в случае длительной недоступности каталога архивов часть wal-файлов гарантированно потеряется и восстановиться с их помощью уже не будет возможности);

  2. Убедитесь, что новые архивы создаются, сессии резервного копирования wal-архивов периодически отрабатывают и чистят каталог;

  3. Выполните полное копирование (Full Backup).

В случае, если закончится место в pgarchlogs, начнет заполняться каталог pg_xlog. По переполнению каталога pg_xlog, СУБД аварийно завершит свою работу.

Проблема:

Все соединения с БД завершаются по причине client_login_timeout:

2022-08-17 19:47:53.155 MSK [1347149] DEBUG C-0x1b0c040 (32): ufs/aplj@$IP-адрес:$Порт client_proto: evtype = FLUSH, state = CL_LOGIN
2022-08-17 19:47:53.155 MSK [1347149] LOG C-0x1b076a0 (1): ufs/aplj@$IP-адрес:$Порт closing because: client_login_timeout (age=177s)
2022-08-17 19:47:53.155 MSK [1347149] WARNING C-0x1b076a0 (1): ufs/aplj@$IP-адрес:$Порт pooler error: client_login_timeout

Решение:

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

Проблема:

При разблокировке пользователя в однопользовательском режиме возникает ошибка:

ERROR: Can't find role with Oid <roloid> in password policy cache

Решение:

Выполните команду:

backend> update pg_pp_policy set lockout='f' WHERE roloid = to_regrole('postgres');

Для выхода из однопользовательского режима нажмите Crl-D.

Проблема:

Заблокированы все администраторы. В случае блокировки всех администраторов БД, в том числе пользователя postgres, восстановить УЗ функцией unblock_role не получится, так как все пользователи с правами на ее запуск не могут подключиться к БД.

В такой ситуации patroni не сможет подключиться к экземпляру PostgreSQL и кластер потеряет лидера. Это можно увидеть в таблице вывода: столбец Role будет пустой.

$ list
+ Cluster: clustername (6857170778029161231) ----------------------------------------+--------------+---------+----+-----------+
|                 Member                |                    Host                    |     Role     |  State  | TL | Lag in MB |
+---------------------------------------+--------------------------------------------+--------------+---------+----+-----------+
| <hostname>                            | <hostname>                                 |              | running |    |   unknown |
| <hostname>                            | <hostname>                                 |              | running |    |   unknown |
+---------------------------------------+--------------------------------------------+--------------+---------+----+-----------+

В логе patroni появится запись об ошибке:

psycopg2.OperationalError: FATAL: Password policy. Auth check. User blocked: too many login fails
...
INFO: Error communicating with PostgreSQL. Will try again later

Решение:

Для разблокировки и восстановления работы кластера необходимо последовательно выполнить следующие действия:

  1. Определить, на каком хосте был последний активный лидер.

  2. Остановить службу Patroni на хосте последнего лидера.

  3. Запустить PostgreSQL в single user режиме.

  4. В single режиме разблокировать пользователя postgres.

  5. Запустить службу Patroni.

  6. Проверить работоспособность кластера.

  7. Разблокировать остальных администраторов БД стандартным образом.

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