Ручное обновление с переносом данных СУБД Pangolin#

Данный раздел рассматривает ручное обновление с переносом данных СУБД Pangolin с версии 5.4.x/5.5.x до 6.5.x.

Внимание

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

Например, сочетание (master, replica) означает, что действия, указанные в пункте, необходимо выполнить сначала на основном узле, затем на реплике (при этом выполнять действия на арбитре не нужно).

Обновление СУБД может осуществляться пользователем с правами суперпользователя, а также пользователем postgres.

В примерах команд при необходимости в блоках кода замените наименование ОС в названиях rpm-пакетов и пакетного менеджера.

Важно

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

Обозначения переменных

В разделе будут использоваться переменные для динамической настройки. Перед выполнением команд эти переменные будут экспортироваться. Скорректируйте значения относительно конкретного обновления.

  • PANGOLIN_VER - новая версия СУБД Pangolin (формат - x.x.x);

  • PANGOLIN_BACKUP_TOOLS - новая версия компонента pangolin-backup-tools (формат - x.x.x);

  • PANGOLIN_POOLER - новая версия компонента pangolin-pooler (формат - x.x.x);

  • PANGOLIN_MANGER - новая версия компонента pangolin-manager (формат - x.x.x);

  • PANGOLIN_TIMESCALEDB - новая версия компонента pangolin-timescaledb (формат - x.x.x);

  • PANGOLIN_OLD_VER - исходная версия СУБД Pangolin (формат - x.x.x);

  • PANGOLIN_FULL_VER - новая версия СУБД Pangolin (формат - 0x.00x.0x);

  • PANGOLIN_FULL_OLD_VER - исходная версия СУБД Pangolin (формат - 0x.00x.0x).

Список ограничений перед проведением обновления с переносом данных СУБД Pangolin#

Проверка и устранение данных ограничений происходит автоматически при выборе автоматизированного способа обновления.

Указанные далее ограничения являются ограничениям при переходе от одной мажорной версии ядра PostgreSQL к другой.

Ниже представлены скрипты для более удобного поиска данных объектов перед обновлением, в случае если эти объекты не были обнаружены и удалены\изменены — есть риск возникновения критической ошибки:

  • Возможные предупреждения (WARNINGS) (рекомендуется устранить, решение за пользователем):

    • проверьте наличие расширений, установленных в схему public или в системный каталог (рекомендуется: перенести в схему ext);

    • в случае использования кластерной конфигурации (cluster) при обновлении — утилита confd будет автоматически удалена. Поэтому до обновления измените строку подключения к СУБД (проверьте значения портов) и убедитесь что в строке указаны оба узла кластера (active и standby). Например, неактуальную строку:

      jdbc:postgresql://127.0.0.1:6544,127.0.0.2:6544/dbname?prepareThreshold=0`
      

      Исправьте на:

      jdbc:postgresql://127.0.0.1:6544,127.0.0.2:6544/dbname?targetServerType=master&prepareThreshold=0
      
  • Возможные ошибки (ERRORS) (обязательно должны быть устранены, иначе обновление не будет доступно). Проверьте:

    • что в БД не используются данные устаревших типов (например, abstime, reltime, tinterval):

      Скрипт search_deprecated_data_types.sql
      SELECT format('%1$s.%2$s(%3$s)',ns.nspname,cl.relname,att.attname) tbl_fld
         FROM pg_attribute att
         JOIN pg_type tp ON att.atttypid =tp.oid
         JOIN pg_class cl ON att.attrelid =cl.oid
         JOIN pg_namespace ns ON cl.relnamespace = ns.oid
         WHERE tp.typname IN ('abstime','reltime','tinterval') AND NOT (ns.nspname SIMILAR TO '(pg_|information_schema)%');
      
      Скрипт search_deprecated_types_missing.sql
      WITH RECURSIVE src AS (
      SELECT
      	pgc.relnamespace::regnamespace
      	,pa.attrelid::regclass
      	,pa.attname
      	,pa.atttypid::regtype
      	,pgc.relkind::TEXT
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pgc ON pa.attrelid =pgc.oid
       JOIN pg_catalog.pg_type pt ON pa.atttypid=pt."oid"
       WHERE
      	format('%1$I.%2$I',pt.typnamespace::regnamespace::TEXT,pt.typname) IN (
      	VALUES
      ('information_schema.sql_languages'), -- {463}
      ('information_schema.sql_packages'), -- {463}
      ('information_schema.sql_sizing_profiles'), -- {463}
      ('pg_catalog.abstime'), -- {463}
      ('pg_catalog._abstime'), -- {463}
      ('pg_catalog.opaque'), -- {463}
      ('pg_catalog.pg_pltemplate'), -- {463}
      ('pg_catalog.reltime'), -- {463}
      ('pg_catalog._reltime'), -- {463}
      ('pg_catalog.smgr'), -- {463}
      ('pg_catalog.tinterval'), -- {463}
      ('pg_catalog._tinterval') -- {463}
      	)
      	AND pa.attnum >0
      UNION ALL
      SELECT
      	pgc.relnamespace::regnamespace
      	,pa.attrelid::regclass
          ,pa.attname
      	,pa.atttypid::regtype
      	,pgc.relkind::TEXT
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pgc ON pa.attrelid =pgc.oid
       JOIN pg_catalog.pg_type pt ON pt.oid=pa.atttypid
       JOIN src ON pt.typrelid=src.attrelid
       WHERE
      	pa.attnum > 0
      )
      SELECT format('%1$s %2$I.%3$I.%4$I::%5$s '
      		,COALESCE(relk.relkind_desc,src.relkind)
      		,src.relnamespace::regnamespace::TEXT
      		,src.attrelid::regclass::TEXT
      		,src.attname::TEXT
      		,src.atttypid::regtype::TEXT
      	)
      FROM src
      	LEFT JOIN
      (VALUES
      	('r', 'Table'),
      	('i', 'Index'),
      	('S', 'Sequence'),
      	('t', 'TOAST'),
      	('v', 'View'),
      	('m', 'MatView'),
      	('c', 'CompositeType'),
      	('f', 'ForeignTable'),
      	('p', 'PartitionedTable'),
      	('I', 'PartitionedIndex'),
      	('G', 'GlobalIndex')
      ) AS relk(relkind, relkind_desc) using(relkind)
      WHERE relnamespace::regnamespace::text !~ '^(information_schema|pg_)';
      
      Скрипт search_deprecated_types_infoschema.sql
      WITH RECURSIVE src AS (
      SELECT
      	pgc.relnamespace::regnamespace
      	,pa.attrelid::regclass
      	,pa.attname
      	,pa.atttypid::regtype
      	,pgc.relkind::TEXT
      	,pt.typcategory::text
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pgc ON pa.attrelid =pgc.oid
       JOIN pg_catalog.pg_type pt ON pa.atttypid=pt."oid"
       WHERE
      	format('%1$I.%2$I',pt.typnamespace::regnamespace::TEXT,pt.typname) IN (
      	VALUES
      ('information_schema._administrable_role_authorizations'), -- {610}
      ('information_schema.administrable_role_authorizations'), -- {463,550,610}
      ('information_schema._applicable_roles'), -- {610}
      ('information_schema.applicable_roles'), -- {463,550,610}
      ('information_schema.attributes'), -- {463,550,610}
      ('information_schema._attributes'), -- {610}
      ('information_schema._cardinal_number'), -- {463,550,610}
      ('information_schema.cardinal_number'), -- {463,550,610}
      ('information_schema._character_data'), -- {463,550,610}
      ('information_schema.character_data'), -- {463,550,610}
      ('information_schema._character_sets'), -- {610}
      ('information_schema.character_sets'), -- {463,550,610}
      ('information_schema._check_constraint_routine_usage'), -- {610}
      ('information_schema.check_constraint_routine_usage'), -- {463,550,610}
      ('information_schema._check_constraints'), -- {610}
      ('information_schema.check_constraints'), -- {463,550,610}
      ('information_schema._collation_character_set_applicability'), -- {610}
      ('information_schema.collation_character_set_applicability'), -- {463,550,610}
      ('information_schema.collations'), -- {463,550,610}
      ('information_schema._collations'), -- {610}
      ('information_schema._column_column_usage'), -- {610}
      ('information_schema.column_column_usage'), -- {550,610}
      ('information_schema._column_domain_usage'), -- {610}
      ('information_schema.column_domain_usage'), -- {463,550,610}
      ('information_schema._column_options'), -- {610}
      ('information_schema.column_options'), -- {463,550,610}
      ('information_schema._column_privileges'), -- {610}
      ('information_schema.column_privileges'), -- {463,550,610}
      ('information_schema.columns'), -- {463,550,610}
      ('information_schema._columns'), -- {610}
      ('information_schema._column_udt_usage'), -- {610}
      ('information_schema.column_udt_usage'), -- {463,550,610}
      ('information_schema._constraint_column_usage'), -- {610}
      ('information_schema.constraint_column_usage'), -- {463,550,610}
      ('information_schema._constraint_table_usage'), -- {610}
      ('information_schema.constraint_table_usage'), -- {463,550,610}
      ('information_schema._data_type_privileges'), -- {610}
      ('information_schema.data_type_privileges'), -- {463,550,610}
      ('information_schema._domain_constraints'), -- {610}
      ('information_schema.domain_constraints'), -- {463,550,610}
      ('information_schema.domains'), -- {463,550,610}
      ('information_schema._domains'), -- {610}
      ('information_schema._domain_udt_usage'), -- {610}
      ('information_schema.domain_udt_usage'), -- {463,550,610}
      ('information_schema._element_types'), -- {610}
      ('information_schema.element_types'), -- {463,550,610}
      ('information_schema._enabled_roles'), -- {610}
      ('information_schema.enabled_roles'), -- {463,550,610}
      ('information_schema._foreign_data_wrapper_options'), -- {610}
      ('information_schema.foreign_data_wrapper_options'), -- {463,550,610}
      ('information_schema._foreign_data_wrappers'), -- {610}
      ('information_schema.foreign_data_wrappers'), -- {463,550,610}
      ('information_schema._foreign_server_options'), -- {610}
      ('information_schema.foreign_server_options'), -- {463,550,610}
      ('information_schema._foreign_servers'), -- {610}
      ('information_schema.foreign_servers'), -- {463,550,610}
      ('information_schema._foreign_table_options'), -- {610}
      ('information_schema.foreign_table_options'), -- {463,550,610}
      ('information_schema._foreign_tables'), -- {610}
      ('information_schema.foreign_tables'), -- {463,550,610}
      ('information_schema._information_schema_catalog_name'), -- {610}
      ('information_schema.information_schema_catalog_name'), -- {463,550,610}
      ('information_schema._key_column_usage'), -- {610}
      ('information_schema.key_column_usage'), -- {463,550,610}
      ('information_schema.parameters'), -- {463,550,610}
      ('information_schema._parameters'), -- {610}
      ('information_schema.__pg_foreign_data_wrappers'), -- {610}
      ('information_schema._pg_foreign_data_wrappers'), -- {463,550,610}
      ('information_schema.__pg_foreign_servers'), -- {610}
      ('information_schema._pg_foreign_servers'), -- {463,550,610}
      ('information_schema.__pg_foreign_table_columns'), -- {610}
      ('information_schema._pg_foreign_table_columns'), -- {463,550,610}
      ('information_schema.__pg_foreign_tables'), -- {610}
      ('information_schema._pg_foreign_tables'), -- {463,550,610}
      ('information_schema.__pg_user_mappings'), -- {610}
      ('information_schema._pg_user_mappings'), -- {463,550,610}
      ('information_schema._referential_constraints'), -- {610}
      ('information_schema.referential_constraints'), -- {463,550,610}
      ('information_schema._role_column_grants'), -- {610}
      ('information_schema.role_column_grants'), -- {463,550,610}
      ('information_schema._role_routine_grants'), -- {610}
      ('information_schema.role_routine_grants'), -- {463,550,610}
      ('information_schema._role_table_grants'), -- {610}
      ('information_schema.role_table_grants'), -- {463,550,610}
      ('information_schema._role_udt_grants'), -- {610}
      ('information_schema.role_udt_grants'), -- {463,550,610}
      ('information_schema._role_usage_grants'), -- {610}
      ('information_schema.role_usage_grants'), -- {463,550,610}
      ('information_schema._routine_column_usage'), -- {610}
      ('information_schema.routine_column_usage'), -- {610}
      ('information_schema._routine_privileges'), -- {610}
      ('information_schema.routine_privileges'), -- {463,550,610}
      ('information_schema._routine_routine_usage'), -- {610}
      ('information_schema.routine_routine_usage'), -- {610}
      ('information_schema.routines'), -- {463,550,610}
      ('information_schema._routines'), -- {610}
      ('information_schema._routine_sequence_usage'), -- {610}
      ('information_schema.routine_sequence_usage'), -- {610}
      ('information_schema._routine_table_usage'), -- {610}
      ('information_schema.routine_table_usage'), -- {610}
      ('information_schema.schemata'), -- {463,550,610}
      ('information_schema._schemata'), -- {610}
      ('information_schema.sequences'), -- {463,550,610}
      ('information_schema._sequences'), -- {610}
      ('information_schema._sql_features'), -- {610}
      ('information_schema.sql_features'), -- {463,550,610}
      ('information_schema._sql_identifier'), -- {463,550,610}
      ('information_schema.sql_identifier'), -- {463,550,610}
      ('information_schema._sql_implementation_info'), -- {610}
      ('information_schema.sql_implementation_info'), -- {463,550,610}
      ('information_schema.sql_languages'), -- {463}
      ('information_schema.sql_packages'), -- {463}
      ('information_schema._sql_parts'), -- {610}
      ('information_schema.sql_parts'), -- {463,550,610}
      ('information_schema._sql_sizing'), -- {610}
      ('information_schema.sql_sizing'), -- {463,550,610}
      ('information_schema.sql_sizing_profiles'), -- {463}
      ('information_schema._table_constraints'), -- {610}
      ('information_schema.table_constraints'), -- {463,550,610}
      ('information_schema._table_privileges'), -- {610}
      ('information_schema.table_privileges'), -- {463,550,610}
      ('information_schema.tables'), -- {463,550,610}
      ('information_schema._tables'), -- {610}
      ('information_schema._time_stamp'), -- {463,550,610}
      ('information_schema.time_stamp'), -- {463,550,610}
      ('information_schema.transforms'), -- {463,550,610}
      ('information_schema._transforms'), -- {610}
      ('information_schema._triggered_update_columns'), -- {610}
      ('information_schema.triggered_update_columns'), -- {463,550,610}
      ('information_schema.triggers'), -- {463,550,610}
      ('information_schema._triggers'), -- {610}
      ('information_schema._udt_privileges'), -- {610}
      ('information_schema.udt_privileges'), -- {463,550,610}
      ('information_schema._usage_privileges'), -- {610}
      ('information_schema.usage_privileges'), -- {463,550,610}
      ('information_schema._user_defined_types'), -- {610}
      ('information_schema.user_defined_types'), -- {463,550,610}
      ('information_schema._user_mapping_options'), -- {610}
      ('information_schema.user_mapping_options'), -- {463,550,610}
      ('information_schema._user_mappings'), -- {610}
      ('information_schema.user_mappings'), -- {463,550,610}
      ('information_schema._view_column_usage'), -- {610}
      ('information_schema.view_column_usage'), -- {463,550,610}
      ('information_schema._view_routine_usage'), -- {610}
      ('information_schema.view_routine_usage'), -- {463,550,610}
      ('information_schema.views'), -- {463,550,610}
      ('information_schema._views'), -- {610}
      ('information_schema._view_table_usage'), -- {610}
      ('information_schema.view_table_usage'), -- {463,550,610}
      ('information_schema._yes_or_no'), -- {463,550,610}
      ('information_schema.yes_or_no') -- {463,550,610}
      	)
      	AND pa.attnum >0
      UNION ALL
      SELECT
      	pgc.relnamespace::regnamespace
      	,pa.attrelid::regclass
          ,pa.attname
      	,pa.atttypid::regtype
      	,pgc.relkind::TEXT
      	,pt.typcategory::text
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pgc ON pa.attrelid =pgc.oid
       JOIN pg_catalog.pg_type pt ON pt.oid=pa.atttypid
       JOIN src ON pt.typrelid=src.attrelid
       WHERE
      	pa.attnum > 0
      )
      SELECT format('%1$s %2$I.%3$I.%4$I::%5$s '
      		,COALESCE(relk.relkind_desc,src.relkind)
      		,src.relnamespace::regnamespace::TEXT
      		,src.attrelid::regclass::TEXT
      		,src.attname::TEXT
      		,src.atttypid::regtype::TEXT
      	)
      FROM src
      	LEFT JOIN
      (VALUES
      	('r', 'Table'),
      	('i', 'Index'),
      	('S', 'Sequence'),
      	('t', 'TOAST'),
      	('v', 'View'),
      	('m', 'MatView'),
      	('c', 'CompositeType'),
      	('f', 'ForeignTable'),
      	('p', 'PartitionedTable'),
      	('I', 'PartitionedIndex'),
      	('G', 'GlobalIndex')
      ) AS relk(relkind, relkind_desc) using(relkind)
      WHERE relnamespace::regnamespace::text !~ '^(information_schema|pg_)' AND src.typcategory='A';
      
    • наличие полей в таблицах с типом xid:

      Скрипт search_deprecated_xid_table.sql
      WITH RECURSIVE src AS (
      SELECT
          pc.relnamespace::regnamespace,
          pa.attrelid::regclass,
          pa.attname,
          pa.atttypid::regtype,
          pc.relkind
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pc ON pa.attrelid = pc.oid
       WHERE
          pa.atttypid::regtype::text IN ('xid','xid[]') AND
          pa.attnum > 0 AND
          pc.relkind != 'v'
      UNION ALL
      SELECT
          pc.relnamespace::regnamespace,
          pa.attrelid::regclass,
          pa.attname,
          pa.atttypid::regtype,
          pc.relkind
       FROM pg_catalog.pg_attribute pa
       JOIN pg_catalog.pg_class pc ON pa.attrelid = pc.oid
       JOIN pg_catalog.pg_type pt ON pt.oid = pa.atttypid
       JOIN src ON pt.typrelid = src.attrelid
       WHERE pa.attnum > 0 AND pc.relkind != 'v')
      SELECT format('%1$s(%2$s)',attrelid,attname) tbl_xid FROM src WHERE relnamespace::regnamespace::text !~ '^(information_schema|pg_)';
      
    • наличие использования устаревших функций для работы с массивами:

      Скрипт search_deprecated_polymorph_usage.sql
      WITH depr(elem) AS (
      	VALUES
      ('array_append(anyarray,anyelement)'),
      ('array_cat(anyarray,anyarray)'),
      ('array_prepend(anyelement,anyarray)'),
      ('array_remove(anyarray,anyelement)'),
      ('array_replace(anyarray,anyelement,anyelement)'),
      ('array_position(anyarray,anyelement)'),
      ('array_position(anyarray,anyelement,integer)'),
      ('array_positions(anyarray,anyelement)'),
      ('width_bucket(anyelement,anyarray)')
      )
      SELECT 
      	'aggregate (transform) ' objkind
      	, p.oid::regprocedure::text objname
      FROM pg_proc AS p
      	JOIN pg_aggregate AS a ON a.aggfnoid=p.oid
      	JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn
      	JOIN depr ON a.aggtransfn=depr.elem::regprocedure
      WHERE p.oid >= 16384
      	AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[])
      UNION ALL
      SELECT 
      	'aggregate (final)' AS objkind
      	, p.oid::regprocedure::text AS objname
      FROM pg_proc AS p
      	JOIN pg_aggregate AS a ON a.aggfnoid=p.oid
      	JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn
      	JOIN depr ON a.aggtransfn=depr.elem::regprocedure
      WHERE p.oid >= 16384
      	AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[])
      UNION ALL
      SELECT 
      	'operator' AS objkind
      	,op.oid::regoperator::text AS objname
      FROM pg_operator AS op
      	JOIN depr ON op.oprcode=depr.elem::regprocedure
      WHERE op.oid >= 16384
      	AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);
      
    • наличие использования устаревших операторов:

      Скрипт search_deprecated_operators.sql
      WITH depr(oprname,oprleft,oprright) AS (
      VALUES
      ('#<','tinterval','reltime'),
      ('#<=','tinterval','reltime'),
      ('#<>','tinterval','reltime'),
      ('#=','tinterval','reltime'),
      ('#>','tinterval','reltime'),
      ('#>=','tinterval','reltime'),
      ('&&','tinterval','tinterval'),
      ('+','abstime','reltime'),
      ('-','abstime','reltime'),
      ('<','abstime','abstime'),
      ('<','reltime','reltime'),
      ('<','tinterval','tinterval'),
      ('<#>','abstime','abstime'),
      ('<<','tinterval','tinterval'),
      ('<=','abstime','abstime'),
      ('<=','reltime','reltime'),
      ('<=','tinterval','tinterval'),
      ('<>','abstime','abstime'),
      ('<>','reltime','reltime'),
      ('<>','tinterval','tinterval'),
      ('<?>','abstime','tinterval'),
      ('=','abstime','abstime'),
      ('=','reltime','reltime'),
      ('=','tinterval','tinterval'),
      ('>','abstime','abstime'),
      ('>','reltime','reltime'),
      ('>','tinterval','tinterval'),
      ('>=','abstime','abstime'),
      ('>=','reltime','reltime'),
      ('>=','tinterval','tinterval'),
      ('|','-','tinterval'),
      ('~=','tinterval','tinterval')
      )
      SELECT depr.* FROM depr JOIN pg_operator op ON
      (depr.oprname,depr.oprleft::name,depr.oprright::name)=(op.oprname,op.oprleft::regtype::name,op.oprright::regtype::name)
      AND op.oprowner <> 'postgres'::regrole;
      
    • наличие использования устаревших семейств операторов:

      Скрипт search_deprecated_operator_family.sql
      WITH depr(opfname) AS (
      VALUES
      ('abstime_minmax_ops'),
      ('abstime_ops'),
      ('abstime_ops'),
      ('reltime_minmax_ops'),
      ('reltime_ops'),
      ('reltime_ops'),
      ('tinterval_ops')
      )
      SELECT depr.* FROM depr JOIN pg_catalog.pg_opfamily opf using(opfname)
      WHERE opf.opfowner <> 'postgres'::regrole;
      
    • наличие устаревших языков для написания функций и хранимых процедур:

      Скрипт search_deprecated_language.sql
      WITH pc(lanname,lanacl,lanowner) AS (
      SELECT lanname,lanacl,lanowner FROM pg_language pl),
      depr(lanname) AS (
      VALUES
       ('internal'),
       ('c'),
       ('sql'),
       ('plpgsql')
      )
      SELECT pc.* FROM pc JOIN depr using(lanname) WHERE (pc.lanowner != 'postgres'::regrole OR coalesce(cardinality(pc.lanacl),0) >0 OR cardinality(pc.lanacl) =0);
      
      
      SELECT
          format('%1$I.%2$I %3$s',pronamespace::regnamespace::TEXT,proname,lanname)
      FROM pg_catalog.pg_proc pp JOIN pg_catalog.pg_language pl ON pp.prolang =pl.oid
      AND pl.lanname IN('plpythonu','plpython2u');
      
    • наличие использования устаревших функций:

      Скрипт search_deprecated_functions.sql
      WITH pc(proname,proargs,proresult,proacl,proowner) AS (
      SELECT pc.proname,pg_get_function_arguments(pc.oid),pg_get_function_result(pc.oid),pc.proacl,pc.proowner::regrole::text FROM pg_proc pc),
      depr(proname,proargs) AS (
      VALUES
      ('abstime','timestamp without time zone'), -- {463}
      ('abstime','timestamp with time zone'), -- {463}
      ('abstimeeq','abstime, abstime'), -- {463}
      ('abstimege','abstime, abstime'), -- {463}
      ('abstimegt','abstime, abstime'), -- {463}
      ('abstimein','cstring'), -- {463}
      ('abstimele','abstime, abstime'), -- {463}
      ('abstimelt','abstime, abstime'), -- {463}
      ('abstimene','abstime, abstime'), -- {463}
      ('abstimeout','abstime'), -- {463}
      ('abstimerecv','internal'), -- {463}
      ('abstimesend','abstime'), -- {463}
      ('array_append','anyarray, anyelement'), -- {463,550}
      ('array_cat','anyarray, anyarray'), -- {463,550}
      ('array_position','anyarray, anyelement'), -- {463,550}
      ('array_position','anyarray, anyelement, integer'), -- {463,550}
      ('array_positions','anyarray, anyelement'), -- {463,550}
      ('array_prepend','anyelement, anyarray'), -- {463,550}
      ('array_remove','anyarray, anyelement'), -- {463,550}
      ('array_replace','anyarray, anyelement, anyelement'), -- {463,550}
      ('ascii_to_mic','integer, integer, cstring, internal, integer'), -- {463}
      ('ascii_to_utf8','integer, integer, cstring, internal, integer'), -- {463}
      ('big5_to_euc_tw','integer, integer, cstring, internal, integer'), -- {463,550}
      ('big5_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('big5_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('binary_upgrade_set_next_toast_pg_type_oid','oid'), -- {463,550}
      ('btabstimecmp','abstime, abstime'), -- {463}
      ('btreltimecmp','reltime, reltime'), -- {463}
      ('bttintervalcmp','tinterval, tinterval'), -- {463}
      ('close_lb','line, box'), -- {463,550}
      ('close_sl','lseg, line'), -- {463,550}
      ('currtid','oid, tid'), -- {463,550}
      ('date','abstime'), -- {463}
      ('date_part','text, reltime'), -- {463}
      ('date_part','text, abstime'), -- {463}
      ('dist_bl','box, line'), -- {550}
      ('dist_lb','line, box'), -- {463,550}
      ('euc_cn_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_cn_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_jis_2004_to_shift_jis_2004','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_jis_2004_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_jp_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_jp_to_sjis','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_jp_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_kr_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_kr_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_tw_to_big5','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_tw_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('euc_tw_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('gb18030_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('gbk_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('get_bit','bytea, integer'), -- {463}
      ('interval','reltime'), -- {463}
      ('interval_transform','internal'), -- {463}
      ('intinterval','abstime, tinterval'), -- {463}
      ('isfinite','abstime'), -- {463}
      ('iso8859_1_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('iso8859_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('iso_to_koi8r','integer, integer, cstring, internal, integer'), -- {463,550}
      ('iso_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('iso_to_win1251','integer, integer, cstring, internal, integer'), -- {463,550}
      ('iso_to_win866','integer, integer, cstring, internal, integer'), -- {463,550}
      ('johab_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8r_to_iso','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8r_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8r_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8r_to_win1251','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8r_to_win866','integer, integer, cstring, internal, integer'), -- {463,550}
      ('koi8u_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('lag','anyelement, integer, anyelement'), -- {463,550}
      ('latin1_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('latin2_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('latin2_to_win1250','integer, integer, cstring, internal, integer'), -- {463,550}
      ('latin3_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('latin4_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('lead','anyelement, integer, anyelement'), -- {463,550}
      ('max','abstime'), -- {463}
      ('mic_to_ascii','integer, integer, cstring, internal, integer'), -- {463}
      ('mic_to_big5','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_euc_cn','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_euc_jp','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_euc_kr','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_euc_tw','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_iso','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_koi8r','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_latin1','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_latin2','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_latin3','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_latin4','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_sjis','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_win1250','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_win1251','integer, integer, cstring, internal, integer'), -- {463,550}
      ('mic_to_win866','integer, integer, cstring, internal, integer'), -- {463,550}
      ('min','abstime'), -- {463}
      ('mktinterval','abstime, abstime'), -- {463}
      ('numeric_fac','bigint'), -- {463,550}
      ('numeric_transform','internal'), -- {463}
      ('opaque_in','cstring'), -- {463}
      ('opaque_out','opaque'), -- {463}
      ('path_center','path'), -- {463,550}
      ('pg_backup_start_time',''), -- {463,550}
      ('pg_create_logical_replication_slot','slot_name name, plugin name, temporary boolean DEFAULT false'), -- {463,550}
      ('pg_is_in_backup',''), -- {463,550}
      ('_pg_keysequal','smallint[], smallint[]'), -- {463}
      ('pg_terminate_backend','integer'), -- {463,550}
      ('pm_grant_to_policy','policy_name name, db_name name, object_kind name, object_name name, actions anyarray'), -- {463}
      ('pm_protect_object','db_name name, object_kind name, object_name name'), -- {463}
      ('pm_revoke_from_policy','policy_name name, db_name name, object_kind name, object_name name, actions anyarray'), -- {463}
      ('pm_unprotect_object','db_name name, object_kind name, object_name name'), -- {463}
      ('point','path'), -- {463,550}
      ('reltime','interval'), -- {463}
      ('reltimeeq','reltime, reltime'), -- {463}
      ('reltimege','reltime, reltime'), -- {463}
      ('reltimegt','reltime, reltime'), -- {463}
      ('reltimein','cstring'), -- {463}
      ('reltimele','reltime, reltime'), -- {463}
      ('reltimelt','reltime, reltime'), -- {463}
      ('reltimene','reltime, reltime'), -- {463}
      ('reltimeout','reltime'), -- {463}
      ('reltimerecv','internal'), -- {463}
      ('reltimesend','reltime'), -- {463}
      ('set_bit','bytea, integer, integer'), -- {463}
      ('shell_out','opaque'), -- {463}
      ('shift_jis_2004_to_euc_jis_2004','integer, integer, cstring, internal, integer'), -- {463,550}
      ('shift_jis_2004_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('sjis_to_euc_jp','integer, integer, cstring, internal, integer'), -- {463,550}
      ('sjis_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('sjis_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('smgreq','smgr, smgr'), -- {463}
      ('smgrin','cstring'), -- {463}
      ('smgrne','smgr, smgr'), -- {463}
      ('smgrout','smgr'), -- {463}
      ('time','abstime'), -- {463}
      ('timemi','abstime, reltime'), -- {463}
      ('timenow',''), -- {463}
      ('timepl','abstime, reltime'), -- {463}
      ('timestamp','abstime'), -- {463}
      ('timestamp_izone_transform','internal'), -- {463}
      ('timestamp_transform','internal'), -- {463}
      ('timestamptz','abstime'), -- {463}
      ('timestamp_zone_transform','internal'), -- {463}
      ('time_transform','internal'), -- {463}
      ('tinterval','abstime, abstime'), -- {463}
      ('tintervalct','tinterval, tinterval'), -- {463}
      ('tintervalend','tinterval'), -- {463}
      ('tintervaleq','tinterval, tinterval'), -- {463}
      ('tintervalge','tinterval, tinterval'), -- {463}
      ('tintervalgt','tinterval, tinterval'), -- {463}
      ('tintervalin','cstring'), -- {463}
      ('tintervalle','tinterval, tinterval'), -- {463}
      ('tintervalleneq','tinterval, reltime'), -- {463}
      ('tintervallenge','tinterval, reltime'), -- {463}
      ('tintervallengt','tinterval, reltime'), -- {463}
      ('tintervallenle','tinterval, reltime'), -- {463}
      ('tintervallenlt','tinterval, reltime'), -- {463}
      ('tintervallenne','tinterval, reltime'), -- {463}
      ('tintervallt','tinterval, tinterval'), -- {463}
      ('tintervalne','tinterval, tinterval'), -- {463}
      ('tintervalout','tinterval'), -- {463}
      ('tintervalov','tinterval, tinterval'), -- {463}
      ('tintervalrecv','internal'), -- {463}
      ('tintervalrel','tinterval'), -- {463}
      ('tintervalsame','tinterval, tinterval'), -- {463}
      ('tintervalsend','tinterval'), -- {463}
      ('tintervalstart','tinterval'), -- {463}
      ('uhc_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_ascii','integer, integer, cstring, internal, integer'), -- {463}
      ('utf8_to_big5','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_euc_cn','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_euc_jis_2004','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_euc_jp','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_euc_kr','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_euc_tw','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_gb18030','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_gbk','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_iso8859','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_iso8859_1','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_johab','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_koi8r','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_koi8u','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_shift_jis_2004','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_sjis','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_uhc','integer, integer, cstring, internal, integer'), -- {463,550}
      ('utf8_to_win','integer, integer, cstring, internal, integer'), -- {463,550}
      ('varbit_transform','internal'), -- {463}
      ('varchar_transform','internal'), -- {463}
      ('width_bucket','anyelement, anyarray'), -- {463,550}
      ('win1250_to_latin2','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win1250_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win1251_to_iso','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win1251_to_koi8r','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win1251_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win1251_to_win866','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win866_to_iso','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win866_to_koi8r','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win866_to_mic','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win866_to_win1251','integer, integer, cstring, internal, integer'), -- {463,550}
      ('win_to_utf8','integer, integer, cstring, internal, integer'), -- {463,550}
      ('xideqint4','xid, integer'),
      ('xidneqint4','xid, integer')
      )
      SELECT pc.* FROM pc JOIN depr using(proname)
      WHERE
      pc.proargs like depr.proargs||'%'
      and ((pc.proowner != 'postgres'::regrole::text)
      OR CARDINALITY(COALESCE(pc.proacl,'{}')) >0
      OR CARDINALITY(pc.proacl)=0);
      
    • наличие устаревших классов операторов:

      Скрипт search_extensions.sql
      WITH depr(opcname,opcmethod) AS (
      VALUES
      ('abstime_minmax_ops','brin'),
      ('abstime_ops','btree'),
      ('abstime_ops','hash'),
      ('reltime_minmax_ops','brin'),
      ('reltime_ops','hash'),
      ('reltime_ops','btree'),
      ('tinterval_ops','btree')
      )
      SELECT depr.* FROM depr JOIN pg_opclass opc using(opcname) JOIN pg_am am ON opc.opcmethod =am.oid AND am.amname =depr.opcmethod
      WHERE opc.opcowner <> 'postgres'::regrole;
      
    • состояние близости БД к порогу заморозки транзакций autovacuum_freeze_max_age:

      Скрипт search_tables_with_autovacuum_freeze_max_age_problem.sql
      WITH tab_opts_toasts AS
        (
        	SELECT c.oid reloid,
                 c.reltoastrelid reltoast,
                 c.relkind relkind,
                 ot.option_value::bigint force_freeze_age,
                 c.relnamespace::regnamespace tab_schema,
                 c.relname relname,
                 age(c.relfrozenxid) tab_frozen_age
        	  FROM pg_class c LEFT OUTER JOIN pg_options_to_table(c.reloptions) ot ON ot.option_name = 'autovacuum_freeze_max_age'
        	 WHERE relkind = ANY('{"r","t","m"}')
        )
      
      SELECT 
               current_database() db,
               CASE tot.relkind WHEN 'r' THEN 'table  autovacuum_freeze_max_age'
                                WHEN 't' THEN 'TOAST  autovacuum_freeze_max_age'
                                WHEN 'm' THEN 'mview  autovacuum_freeze_max_age'
               END reason,
               CASE WHEN tot.relkind = 't' THEN parents.tab_schema ELSE tot.tab_schema END tab_schema,       
               CASE WHEN tot.relkind = 't' THEN 'TOAST of '||parents.relname ELSE tot.relname END tabname,
               tot.tab_frozen_age,
               tot.force_freeze_age
          FROM tab_opts_toasts tot LEFT OUTER JOIN tab_opts_toasts parents ON parents.reltoast = tot.reloid
        WHERE tot.force_freeze_age IS NOT NULL and tot.tab_frozen_age >= tot.force_freeze_age::bigint * 0.8
      
      UNION ALL
      
      SELECT
               current_database() db,
               'SYSTEM autovacuum_freeze_max_age' reason,
               CASE WHEN tot.relkind = 't' THEN parents.tab_schema ELSE tot.tab_schema END tab_schema,       
               CASE WHEN tot.relkind = 't' THEN 'TOAST of '||parents.relname ELSE tot.relname END tabname,
               tot.tab_frozen_age,
               current_setting('autovacuum_freeze_max_age')::bigint force_freeze_age
          FROM tab_opts_toasts tot LEFT OUTER JOIN tab_opts_toasts parents ON parents.reltoast = tot.reloid
         WHERE tot.tab_frozen_age >= current_setting('autovacuum_freeze_max_age')::bigint * 0.8
      ;
      
    • значение параметра max_worker_process конфигурационного файла не превышает сумму количества баз данных на узле (включая системные template1, postgres) + 6. Например, если количество БД = 26, то значение параметра должно быть не меньше 32.

Шаг 1. Резервное копирование рабочих файлов компонентов#

  1. (master, replica) Сохраните рабочие файлы компонентов СУБД Pangolin:

    • general:

      sudo mkdir -p ~/pangolin/cache/backup/general                                                      # дополнительно создать на узле arbiter  
      sudo cp -ra /usr/local/sbin/dynmotd.sh                        ~/pangolin/cache/backup/general/     # дополнительно сохранить на узле arbiter
      sudo cp -ra /home/postgres/.bash_profile                      ~/pangolin/cache/backup/general/
      sudo cp -ra /etc/sudoers.d/10-kmadmin_pg                      ~/pangolin/cache/backup/general/
      sudo cp -ra /etc/sudoers.d/10-postgres                        ~/pangolin/cache/backup/general/
      sudo cp -ra /etc/postgres/enc_connection_settings_cert.cfg    ~/pangolin/cache/backup/general/
      sudo cp -ra /etc/postgres/enc_connection_settings.cfg         ~/pangolin/cache/backup/general/
      sudo cp -ra /etc/postgres/enc_utils_auth_settings.cfg         ~/pangolin/cache/backup/general/
      
    • Pangolin Pooler:

      sudo mkdir -p ~/pangolin/cache/backup/pgbouncer
      sudo cp -ra /etc/systemd/system/pgbouncer.service             ~/pangolin/cache/backup/pgbouncer/
      sudo cp -ra /etc/pgbouncer/pgbouncer.ini                      ~/pangolin/cache/backup/pgbouncer/
      sudo cp -ra /etc/pgbouncer/userlist.txt                       ~/pangolin/cache/backup/pgbouncer/
      sudo cp -ra /usr/local/bin/pgbouncer                          ~/pangolin/cache/backup/pgbouncer/
      sudo cp -ra /usr/local/share/man/man1/pgbouncer.1             ~/pangolin/cache/backup/pgbouncer/
      sudo cp -ra /usr/local/share/man/man5/pgbouncer.5             ~/pangolin/cache/backup/pgbouncer/
      
    • Pangolin Manager:

      sudo mkdir -p ~/pangolin/cache/backup/patroni
      sudo cp -ra /etc/systemd/system/patroni.service               ~/pangolin/cache/backup/patroni/
      sudo cp -ra /etc/patroni/postgres.yml                         ~/pangolin/cache/backup/patroni/
      sudo cp -ra /etc/patroni/reload_pgbouncer.sh                  ~/pangolin/cache/backup/patroni/
      sudo cp -ra /usr/patroni                                      ~/pangolin/cache/backup/patroni/
      sudo cp -ra /pgdata/05/data/patroni.dynamic.json              ~/pangolin/cache/backup/patroni/  
      
    • pangolin_reencrypt:

      sudo mkdir -p ~/pangolin/cache/backup/pangolin_reencrypt
      sudo cp -ra /etc/systemd/system/pangolin_reencrypt@.service   ~/pangolin/cache/backup/pangolin_reencrypt/
      sudo cp -ra /opt/pangolin-common/bin/pg_auth_reencrypt        ~/pangolin/cache/backup/pangolin_reencrypt/
      sudo cp -ra /etc/postgres/enc_util.cfg                        ~/pangolin/cache/backup/pangolin_reencrypt/
      sudo cp -ra /etc/postgres/enc_params.cfg.kmadmin_pg           ~/pangolin/cache/backup/pangolin_reencrypt/ 
      sudo cp -ra /etc/postgres/enc_params.cfg.postgres             ~/pangolin/cache/backup/pangolin_reencrypt/ 
      
    • pg_certs_rotate:

      sudo mkdir -p ~/pangolin/cache/backup/pg_certs_rotate_agent
      sudo cp -ra /etc/systemd/system/pg_certs_rotate_agent.service ~/pangolin/cache/backup/pg_certs_rotate_agent/
      sudo cp -ra /opt/pangolin-common/bin/pg_certs_rotate_agent    ~/pangolin/cache/backup/pg_certs_rotate_agent/
      sudo cp -ra /etc/postgres/pg_certs_rotate_agent.yml           ~/pangolin/cache/backup/pg_certs_rotate_agent/   
      
    • manage_backup:

      sudo mkdir -p ~/pangolin/cache/backup/manage_backup
      sudo cp -ra /opt/omni/lbin/                                   ~/pangolin/cache/backup/manage_backup/
      
    • pangolin_dbms:

      export PANGOLIN_OLD_VER={pangolin_old_version}
      sudo mkdir -p ~/pangolin/cache/backup/pangolin_dbms
      sudo dnf download --destdir=/home/<user>/pangolin/cache/backup/pangolin_dbms/ platform-v-pangolin-dbms
      sudo cp -ra /usr/pangolin-$PANGOLIN_OLD_VER/                               ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/postgresql.conf                    ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/pg_hba.conf                        ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/postgresql.base.conf               ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/postgresql.auto.conf               ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/pg_quota.conf                      ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /pgdata/05/data/pg_ident.conf                      ~/pangolin/cache/backup/pangolin_dbms/
      sudo cp -ra /etc/systemd/system/postgresql.service             ~/pangolin/cache/backup/pangolin_dbms/
      
  2. (master) Создайте каталог для резервной копии:

    sudo mkdir -p /pgarclogs/cache/backup/pangolin_dbms /pgarclogs/cache/backup/pangolin_dbms{backups,wal}
    sudo chmod -R 0700 /pgarclogs/cache/backup/pangolin_dbms
    sudo chown -R postgres:postgres /pgarclogs/cache/
    
  3. (master) Добавьте запись host replication postgres 127.0.0.1/32 scram-sha-256 первой строкой в файл /pgdata/05/data/pg_hba.conf или в файл /etc/patroni/postgres.yml в секцию pg_hba для конфигурации с patroni.

  4. (master) Перечитайте обновленный конфигурационный файл БД.

    • Для конфигурации без patroni:

      /usr/pangolin/bin/pg_ctl reload -D /pgdata/05/data
      
    • Для конфигурации с patroni:

      /usr/patroni/patroni_venv/bin/patronictl -c /etc/patroni/postgres.yml reload clustername
      
    Ошибка This system supports the C.UTF-8 locale which is recommended

    Если при вызове утилиты возникает ошибка в локалях кодировки: This system supports the C.UTF-8 locale which is recommended, то выполните следующую команду:

    echo "
    export LC_ALL=C.UTF-8
    export LANG=C.UTF-8" >> .bash_profile &&\
    source .bash_profile
    
  5. (master) Выполните резервное копирование:

    /usr/pangolin/bin/pg_probackup init -B /pgarclogs/cache/backup/pangolin_dbms
    /usr/pangolin/bin/pg_probackup add-instance -B /pgarclogs/cache/backup/pangolin_dbms -D /pgdata/05/data --instance clustername
    PGPASSWORD=<password_postgres> /usr/pangolin/bin/pg_probackup backup -B /pgarclogs/cache/backup/pangolin_dbms --instance clustername -b FULL -h 127.0.0.1 -p 5433 -U postgres --compress-algorithm=zlib --compress-level=4 -j 14 --temp-slot --stream --progress -w
    
  6. (master) Удалите строку host replication postgres 127.0.0.1/32 scram-sha-256 из файла /pgdata/05/data/pg_hba.conf или из файла /etc/patroni/postgres.yml для конфигурации с patroni.

  7. (master) Перечитайте обновленный конфигурационный файл БД.

Шаг 2. Подготовительные действия#

  1. (master, replica, arbiter) Запустите скрипт с базовыми проверками, определяющими готовность стенда к обновлению:

    mkdir ~/pangolin/cache/
    echo " <заменить на содержимое из pangolin_checks.sh> " > ~/pangolin/cache/pangolin_checks.sh
    sudo chmod 0700 ~/pangolin/cache/pangolin_checks.sh
    cd ~/ && sudo STAND=<роль ноды> CONFIGURATION=<тип конфигурации> ./pangolin/cache/pangolin_checks.sh
    
    pangolin-check.sh

    pangolin-check.sh:

    function log_form {
        echo -e "\e[32m===============================[0m"
        echo -e "\e[32mКонфигурация: $CONFIGURATION[0m"
        echo -e "\e[32mСтенд: $STAND[0m"
        echo -e "\e[32m===============================[0m"
    }
    
    function error_message {
        echo -e "\e[31mERROR: Проверка не пройдена. $1\e[0m"
    }
    
    function success_message {
        echo -e "\e[32mOK: Проверка пройдена. $1\e[0m"
    }
    
    function warning_message {
        echo -e "\e[33mWARNING: $1\e[0m"
    }
    
    log_form
    
    if [ -z "$STAND" ] || [ -z "$CONFIGURATION" ]; then
        echo -e "\e[31mERROR: Передайте обязательные переменные перед запуском скрипта для корректной проверки. Например: STAND=master CONFIGURATION=standalone ./pangolin_checks.sh.\e[0m"
        exit 1
    fi
    
    # Проверка наличия локали en_us.utf-8 или en_us.utf8
    if locale -a | grep -qE "en_US.utf-8|en_US.utf8"; then
     success_message "Локаль en_US.utf-8 или en_US.utf8 установлена."
    else
     error_message "Необходимо установить локаль en_US.utf-8 или en_US.utf8."
    fi
    
    # Определение списка рабочих файлов в зависимости от конфигурации и стенда
    file_common=("/etc/pgbouncer/pgbouncer.ini" "/etc/systemd/system/pgbouncer.service" "/usr/local/bin/pgbouncer" "/opt/pangolin-common/bin/pg_auth_reencrypt" "/etc/systemd/system/pangolin_reencrypt@.service" "/etc/postgres/enc_util.cfg" "/opt/pangolin-common/bin/pg_certs_rotate_agent" "/etc/systemd/system/pg_certs_rotate_agent.service" "/etc/postgres/pg_certs_rotate_agent.yml")
    if [ "$CONFIGURATION" = "cluster" ]; then
        if [ "$STAND" != "arbiter" ]; then
            additional_files=("/etc/systemd/system/patroni.service" "/etc/patroni/postgres.yml" "/etc/systemd/system/etcd.service" "/etc/etcd/etcd.conf")
        else
            additional_files=("/etc/systemd/system/etcd.service" "/etc/etcd/etcd.conf")
        fi
    else
        if [ "$STAND" != "arbiter" ]; then
            additional_files=("/etc/systemd/system/postgresql.service")
        fi
    fi
    if [ "$STAND" != "arbiter" ]; then
        files_all=("${file_common[@]}" "${additional_files[@]}")
    else
        files_all=("${additional_files[@]}")
    fi
     
    # Проверка наличия рабочих файлов
    for file in "${files_all[@]}"; do
        if [ -f "$file" ]; then
            success_message "Рабочий файл $file найден."
        else
            error_message "Рабочий файл $file не найден. Для конфигурации $CONFIGURATION наличие данного файла необходимо для корректного обновления."
        fi
    done
     
    # Определение списка сервисов в зависимости от конфигурации
    service_common=("pgbouncer" "pg_certs_rotate_agent" "pangolin_reencrypt@postgres.service" "pangolin_reencrypt@kmadmin_pg.service")
    if [ "$CONFIGURATION" = "cluster" ]; then
        if [ "$STAND" != "arbiter" ]; then
            additional_services=("patroni" "etcd")
        else
            additional_services=("etcd")
        fi
    else
        if [ "$STAND" != "arbiter" ]; then
            additional_services=("postgresql")
        fi
    fi
    if [ "$STAND" != "arbiter" ]; then
        service_all=("${service_common[@]}" "${additional_services[@]}")
    else
        service_all=("${additional_services[@]}")
    fi
     
    # Проверка состояния сервисов
    for service in "${service_all[@]}"; do
        if systemctl is-active --quiet "$service"; then
            success_message "Сервис $service активен."
        else
            error_message "Необходимо запустить сервис $service."
        fi
    done
     
    if [ "$STAND" != "arbiter" ]; then
        # Проверка наличия установленного rpm пакета
            PACKAGE_NAME="platform-v-pangolin-dbms"
        if command -v yum &> /dev/null; then
            PACKAGE_MANAGER="yum"
        elif command -v dnf &> /dev/null; then
            PACKAGE_MANAGER="dnf"
        elif command -v apt &> /dev/null; then
            PACKAGE_MANAGER="apt"
        elif command -v apt-get &> /dev/null; then
            PACKAGE_MANAGER="apt-get"
        else
            error_message "Необходимо установить пакетный менеджер (yum/dnf/apt/apt-get)."
            exit 1
        fi
     
        if $PACKAGE_MANAGER list installed | grep -q "$PACKAGE_NAME"; then
            success_message "Пакет $PACKAGE_NAME установлен."
        else
            error_message "Пакет $PACKAGE_NAME не обнаружен на стенде."
        fi
     
        # Получение версии пакета
        PACKAGE_VERSION=$($PACKAGE_MANAGER list installed | grep "$PACKAGE_NAME" | awk '{print $2}')
     
        # Извлечение числовой части версии
        NUMERIC_VERSION=$(echo "$PACKAGE_VERSION" | awk -F'[.-]' '{print $1 $2 $3}' | tr -d '0')
     
        # Проверка версии пакета
        if [[ $NUMERIC_VERSION =~ ^55[0-9]$ ]]; then
            success_message "Версия исходного пакета $PACKAGE_NAME ($NUMERIC_VERSION) соответствует требованиям инструкции по ручному обновлению с переносом данных."
        else
            error_message "Инструкция по ручному обновлению не рассматривает обновление с исходной версии пакета $PACKAGE_NAME ($NUMERIC_VERSION), полученной со стенда. Инструкция рассматривает обновление с версий 5.5.x на 6.5.х."
        fi
    fi
     
    warning_message "Набор проверок не является исчерпывающим. Для обновления рекомендуем использовать автоматизированные скрипты."
    

    Ожидаемый результат:

    Проверка пройдена успешно

    Результат при неготовности стенда к обновлению:

    Проверка не пройдена

    Предупреждение

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

  2. (master, replica, arbiter) Скачайте дистрибутив в рабочий каталог и распакуйте его. Далее по инструкции путь к компонентам дистрибутива будет формироваться с использованием префикса ~/pangolin.

    Действие по скачиванию дистрибутива:

    mkdir -p ~/pangolin
    tar -xzvf pangolin_6.tar.gz  -C ~/pangolin
    
  3. (master) Сохраните исходные значения стенда для последующей инициализации новой БД:

    sudo -iu postgres
    psql -c "SHOW SERVER_ENCODING;" > current_value.txt
    psql -c "SHOW LC_COLLATE;" >> current_value.txt
    psql -c "SHOW LC_CTYPE;" >> current_value.txt
    psql -c "SHOW LC_MESSAGES;" >> current_value.txt
    psql -c "SHOW LC_MONETARY;" >> current_value.txt
    psql -c "SHOW LC_NUMERIC;" >> current_value.txt
    psql -c "SHOW LC_TIME;" >> current_value.txt
    psql -c "SELECT oid, pg_tablespace_location(oid) FROM pg_tablespace WHERE spcname not in ('pg_default', 'pg_global');" >> current_value.txt
    exit
    
  4. (master, replica) Разверните виртуальное окружение и перезапустите сессию пользователей: postgres, kmadmin_pg:

    export PANGOLIN_VER=6.5.x
    sudo dnf install -y ~/pangolin/3rdparty/3rdparty/pangolin-ansible-venv-controlled-$PANGOLIN_VER-sberlinux8.x86_64.rpm
    sudo systemctl restart user@$(id -u postgres)
    sudo systemctl restart user@$(id -u kmadmin_pg)
    
  5. (master) Подготовьте исходную базу для корректной миграции:

    sudo -iu postgres
     
    echo "
    SELECT grant_opts AS grant_opts_start FROM (SELECT unnest(proacl) AS grant_opts FROM pg_proc WHERE proname = 'pg_start_backup' AND proargtypes = array[25,16,16]::oidvector AND pronamespace = 11) AS all_grants, pg_proc WHERE proname = 'pg_start_backup' AND proargtypes = array[25,16,16]::oidvector AND pronamespace = 11 AND NOT (grant_opts = any( acldefault('f', proowner)));
    SELECT revoke_opts AS revoke_opts_start FROM (SELECT unnest(acldefault('f', proowner)) AS revoke_opts FROM pg_proc WHERE proname = 'pg_start_backup' AND proargtypes = array[25,16,16]::oidvector AND pronamespace = 11) AS all_defs, pg_proc WHERE proname = 'pg_start_backup' AND proargtypes = array[25,16,16]::oidvector AND pronamespace = 11 AND NOT (revoke_opts = any(proacl));
    SELECT grant_opts AS grant_opts_stop FROM (SELECT unnest(proacl) AS grant_opts FROM pg_proc WHERE proname = 'pg_stop_backup' AND proargtypes = array[16,16]::oidvector AND pronamespace = 11) AS all_grants, pg_proc WHERE proname = 'pg_stop_backup' AND proargtypes = array[16,16]::oidvector AND pronamespace = 11 AND NOT (grant_opts = any( acldefault('f', proowner)));
    SELECT revoke_opts AS revoke_opts_stop FROM (SELECT unnest(acldefault('f', proowner)) AS revoke_opts FROM pg_proc WHERE proname = 'pg_stop_backup' AND proargtypes = array[16,16]::oidvector AND pronamespace = 11) AS all_defs, pg_proc WHERE proname = 'pg_stop_backup' AND proargtypes = array[16,16]::oidvector AND pronamespace = 11 AND NOT (revoke_opts = any(proacl));
    " > /home/postgres/change_0.sql
     
    echo "
    DELETE FROM pg_depend using (SELECT c.oid AS c_id, p.oid AS p_id, p.proname FROM pg_catalog.pg_class c join pg_catalog.pg_proc p ON c.relname = 'pg_proc' JOIN pg_catalog.pg_namespace ns ON p.pronamespace=ns.oid AND ns.nspname='pg_catalog') flt WHERE pg_depend.refclassid=flt.c_id AND pg_depend.refobjid = flt.p_id AND pg_depend.deptype ='p' AND pg_depend.classid=0 AND pg_depend.objid=0 AND pg_depend.objsubid=0 AND flt.proname IN (SELECT unnest(string_to_array('check_role_params,check_roles_is_on',',')));
    DROP FUNCTION IF EXISTS pg_catalog.check_role_params(role text, settings_to_check text), pg_catalog.check_roles_is_on();
    " > /home/postgres/change_1.sql
     
    echo "
    UPDATE pg_proc SET proacl = NULL WHERE proname = 'pg_start_backup' AND proargtypes = array[25,16,16]::oidvector AND pronamespace = 11;
    UPDATE pg_proc SET proacl = NULL WHERE proname = 'pg_stop_backup' AND proargtypes = array[16,16]::oidvector AND pronamespace = 11;
    UPDATE pg_proc SET proacl = NULL WHERE proname = 'pg_stop_backup' AND cardinality(proargtypes) = 0 AND pronamespace = 11;
    " > /home/postgres/change_2.sql
     
    echo "
     
    databases=(\$(\$PGHOME/bin/psql -t --csv -c \"SELECT datname FROM pg_database WHERE datname not in ('template0', 'template1');\"))
    echo \"databases: \" \$databases
    for ud in \"\${databases[@]}\"; do
    echo \"databases: \" \$ud
    \$PGHOME/bin/psql -d \$ud -f /home/postgres/change_0.sql -1
    done
     
    databases=(\$(\$PGHOME/bin/psql -t --csv -c \"SELECT datname FROM pg_database;\"))
    echo \"databases: \" \$databases
    for ud in \"\${databases[@]}\"; do
    echo \"database: \" \$ud
    \$PGHOME/bin/psql -c \"UPDATE pg_database SET datallowconn = true WHERE datname = 'template0';\"
    \$PGHOME/bin/psql -d \$ud -f /home/postgres/change_1.sql -1
    \$PGHOME/bin/psql -c \"UPDATE pg_database SET datallowconn = false WHERE datname = 'template0';\"
    done
     
    databases=(\$(\$PGHOME/bin/psql -t --csv -c \"SELECT datname FROM pg_database WHERE datname not in ('template0', 'template1');\"))
    echo \"databases: \" \$databases
    for ud in \"\${databases[@]}\"; do
    echo \"databases: \" \$ud
    \$PGHOME/bin/psql -d \$ud -f /home/postgres/change_2.sql -1
    done
    " > /home/postgres/run_precondition.sh
     
    chmod 0700 run_precondition.sh
    ./run_precondition.sh >> current_value.txt
    exit
    
  6. (master, replica) Сформируйте конфигурационные файлы для работы с новой версией:

    sudo mkdir -p ~/pangolin/cache/merge
    sudo cp -r /pgdata/05/data/postgresql.conf ~/pangolin/cache/merge/postgresql.conf
    sudo cp -r /etc/patroni/postgres.yml ~/pangolin/cache/merge/postgres.yml
     
    #точечная актуализация или добавление параметров ~/pangolin/cache/merge/postgresql.conf
    archive_command = '/opt/pangolin-backup-tools/bin/pg_probackup archive-push -B /pgarclogs/06 --instance clustername --wal-file-path=%p --wal-file-name=%f --compress --overwrite -j 4 --batch-size=100' 
    log_directory = '/pgerrorlogs/06'
    pg_plugins_path = /usr/pangolin-6.5/lib
    hba_file = '/pgdata/06/data/pg_hba.conf'
    ident_file = '/pgdata/06/data/pg_ident.conf'
     
    #точечная актуализация или добавление параметров ~/pangolin/cache/merge/postgres.yml Для конфигурации с patroni.
    postgresql:
        bin_dir: '/usr/pangolin-6.5/bin'
        bin_dir_client: /usr/pangolin-dbms-client-6.5/bin
        data_dir: '/pgdata/06/data/'
        callbacks:
            on_role_change: '/opt/pangolin-pooler/bin/pangolin-pooler-restart.sh'
        parameters:
            archive_command: '/opt/pangolin-backup-tools/bin/pg_probackup archive-push -B /pgarclogs/06 --instance clustername --wal-file-path=%p --wal-file-name=%f --compress --overwrite -j 4 --batch-size=100'
            pg_plugins_path = /usr/pangolin-6.5/lib
    
  7. (master, replica) Актуализируйте .bash_profile и sudoers:

    export PANGOLIN_OLD_VER=5.5.x
    sudo sed -i '/LD_LIBRARY_PATH/d'                              /home/postgres/.bash_profile
    sudo sed -i '/PG_PLUGINS_PATH/d'                              /home/postgres/.bash_profile
    sudo sed -i 's/pgerrorlogs\/05/pgerrorlogs\/06/g'             /home/postgres/.bash_profile
    sudo sed -i 's/pgdata\/05/pgdata\/06/g'                       /home/postgres/.bash_profile
    sudo sed -i "s/$PANGOLIN_OLD_VER/6.5/g"                       /home/postgres/.bash_profile
    sudo sed -i "s/$PANGOLIN_OLD_VER/6.5/g"                       /home/postgres/.bash_profile
    sudo sed -i "s/pangolin_reencrypt/pangolin-auth-reencrypt/g"  /etc/sudoers.d/10-kmadmin_pg
    sudo sed -i "s/pangolin_reencrypt/pangolin-auth-reencrypt/g"  /etc/sudoers.d/10-postgres
    sudo sed -i "s/pg_certs_rotate_agent/pangolin-certs-rotate/g" /etc/sudoers.d/10-postgres
    sudo sed -i "s/pgbouncer/pangolin-pooler/g"                   /etc/sudoers.d/10-postgres
     
    #для конфигурации с patroni
    sudo sed -i "s/patronictl/pangolin-manager-ctl/g"                                 /home/postgres/.bash_profile
    sudo sed -i "s/\/usr\/patroni\/patroni_venv\/bin/\/opt\/pangolin-manager\/bin/g"  /home/postgres/.bash_profile
    sudo sed -i "s/patroni/pangolin-manager/g"                                        /home/postgres/.bash_profile
    sudo sed -i "s/patroni/pangolin-manager/g"                                        /etc/sudoers.d/10-postgres
    
  8. (master) Проверьте отсутствие большого количества транзакций с незавершенным статусом. Для этого выполните следующий запрос:

    sudo -iu postgres
    psql
    
    SELECT *
    FROM
    (WITH mysql AS
        (SELECT *
        FROM pg_stat_database) SELECT db.datname,
                                        (mysql.xact_commit::text::bigint - datfrozenxid::text::bigint) / 1048576 AS clog_cnt
    FROM pg_database db,
            mysql
    WHERE db.oid=mysql.datid) mysql2
    WHERE clog_cnt>3;
    

    Результат выполнения данного запроса — таблица с колонками datname (имя БД) и clog_cnt (количество файлов clog). Если результат запроса будет не пустой, то для всех полученных БД необходимо выполнить команду: vacuumdb -v -d db_name, где db_name - имя БД, полученное в результате выполнения запроса выше.

  9. (master) Выполните проверку состояния близости БД к пороговому значению заморозки транзакций autovacuum_freeze_max_age. Для этого выполните SQL-скрипт для каждой базы данных:

    WITH tab_opts_toasts AS
    (
       SELECT c.oid reloid,
           c.reltoastrelid reltoast,
           c.relkind relkind,
           ot.option_value::bigint force_freeze_age,
           c.relnamespace::regnamespace tab_schema,
           c.relname relname,
           age(c.relfrozenxid) tab_frozen_age
       FROM pg_class c LEFT OUTER JOIN pg_options_to_table(c.reloptions) ot ON ot.option_name = 'autovacuum_freeze_max_age'
       WHERE relkind = ANY('{"r","t","m"}')
    )
    
    SELECT 
           current_database() db,
           CASE tot.relkind WHEN 'r' THEN 'table  autovacuum_freeze_max_age'
                           WHEN 't' THEN 'TOAST  autovacuum_freeze_max_age'
                           WHEN 'm' THEN 'mview  autovacuum_freeze_max_age'
           END reason,
           CASE WHEN tot.relkind = 't' THEN parents.tab_schema ELSE tot.tab_schema END tab_schema,       
           CASE WHEN tot.relkind = 't' THEN 'TOAST of '||parents.relname ELSE tot.relname END tabname,
           tot.tab_frozen_age,
           tot.force_freeze_age
       FROM tab_opts_toasts tot LEFT OUTER JOIN tab_opts_toasts parents ON parents.reltoast = tot.reloid
    WHERE tot.force_freeze_age IS NOT NULL and tot.tab_frozen_age >= tot.force_freeze_age::bigint * 0.8
    
    UNION ALL
    
    SELECT
           current_database() db,
           'SYSTEM autovacuum_freeze_max_age' reason,
           CASE WHEN tot.relkind = 't' THEN parents.tab_schema ELSE tot.tab_schema END tab_schema,       
           CASE WHEN tot.relkind = 't' THEN 'TOAST of '||parents.relname ELSE tot.relname END tabname,
           tot.tab_frozen_age,
           current_setting('autovacuum_freeze_max_age')::bigint force_freeze_age
       FROM tab_opts_toasts tot LEFT OUTER JOIN tab_opts_toasts parents ON parents.reltoast = tot.reloid
    WHERE tot.tab_frozen_age >= current_setting('autovacuum_freeze_max_age')::bigint * 0.8
    ;
    
    Результат выполнения запроса

    Результат выполнения данного запроса — таблица со следующими колонками:

    • db - в какой БД найдена таблица;

    • reason - причина попадания таблицы в выборку:

      • table autovacuum_freeze_max_age - превышено 80% порога индивидуального порога таблицы;

      • TOAST autovacuum_freeze_max_age - 80% порога, заданного на этой таблице по ее TOAST (toast.autovacuum_freeze_max_age);

      • mview autovacuum_freeze_max_age - 80% индивидуального порога по mview, необходимо увеличить значение параметра autovacuum_freeze_max_age через команду ALTER MATERIALIZED VIEW;

      • SYSTEM autovacuum_freeze_max_age - превышено 80% системного autovacuum_freeze_max_age;

    • tab_schema - схема таблицы для table/mview, схема родительской таблицы для TOAST;

    • tabname - имя table/mv, имя родительской таблицы у тоста;

    • tab_frozen_age - возраст старейшей замороженной транзакции table/mview/TOAST;

    • force_freeze_age - порог table/mview/TOAST для индивидуальных порогов или current_setting('autovacuum_freeze_max_age') для системного порога.

    Если в результате работы SQL-скрипта, выводится таблица, то рекомендуется перед обновлением выполнить следующие действия на выбор:

    • Выполните команду vacuumdb -a -F -v (заморозка транзакций в кластере баз). В случае если команда отрабатывает некорректно — рекомендуется выполнить следующие действия:

      • Удалите старые подготовленные транзакции;

      • Завершите длительные и бездействующие транзакции;

      • Удалите старые слоты репликации;

      • Разрешите конфликты репликации на репликах или выключите конфликтующие реплики.

      • Затем повторите vacuumdb -a -F -v. За подробностями можно обратиться к документу Server Administration, раздел Routine Database Maintenance Tasks - Routine Vacuuming, глава «Preventing Transaction ID Wraparound Failures»;

    • Увеличьте значение параметра autovacuum_freeze_max_age системное/для таблиц исходя из формулы: autovacuum_freeze_max_age > tab_frozen_age / 80% .

Шаг 3. Остановка компонентов СУБД Pangolin#

  1. (master) В случае конфигурации с patroni переведите patroni в режим паузы:

    sudo -iu postgres
    /usr/patroni/patroni_venv/bin/patronictl -c /etc/patroni/postgres.yml edit-config --set 'pause=true' --force
    exit
    
  2. (master, replica) Перед остановкой необходимо выполнить команду CHECKPOINT на мастере. Остановите все компоненты СУБД Pangolin:

    sudo systemctl stop pgbouncer
    sudo systemctl stop pg_certs_rotate_agent
    sudo systemctl stop pangolin_reencrypt@postgres.service
    sudo systemctl stop pangolin_reencrypt@kmadmin_pg.service
    

    Дополнительно выполните:

    • для конфигурации без patroni:

      sudo systemctl stop postgresql
      
    • Для конфигурации с patroni:

      sudo -iu postgres
      /usr/pangolin/bin/pg_ctl stop -D /pgdata/05/data
      exit
      sudo systemctl stop patroni
      
    • Для конфигурации с etcd:

      sudo systemctl stop etcd
      
  3. (replica, master, arbiter) Остановите сторонние компоненты:

    sudo systemctl stop crond
    

Шаг 4. Обновление компонента pangolin-auth-reencrypt#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_VER=6.5.x
    sudo dnf install -y ~/pangolin/utilities/pangolin-auth-reencrypt-$PANGOLIN_VER-sberlinux8.x86_64.rpm
    
  2. (master, replica) Точечно замените конфигурационный файл, ввиду изменения наименований компонентов, путей к файлам подключения к VAULT и пути к защищенному хранилищу:

    sudo sed -i "s/\/etc\/patroni\/postgres.yml/\/etc\/pangolin-manager\/postgres.yml/g" /etc/pangolin-auth-reencrypt/enc_util.cfg
    sudo sed -i "s/\/etc\/postgres\/enc_utils_auth_settings.cfg/\/etc\/pangolin-auth-encryption\/enc_utils_auth_settings.cfg/g" /etc/pangolin-auth-reencrypt/enc_util.cfg
    sudo sed -i "s/\/etc\/postgres\/enc_connection_settings.cfg/\/etc\/pangolin-security-utilities\/enc_connection_settings.cfg/g" /etc/pangolin-auth-reencrypt/enc_util.cfg
    sudo sed -i "s/\/etc\/postgres\/enc_connection_settings_cert.cfg/\/etc\/pangolin-security-utilities\/enc_connection_settings_cert.cfg/g" /etc/pangolin-auth-reencrypt/enc_util.cfg
    
  3. (master, replica) Создайте каталог для логов компонента:

    export PGLOGS=/pgerrorlogs/06
    sudo mkdir -p $PGLOGS/pangolin-auth-reencrypt/
    sudo chown postgres:pangolin_users $PGLOGS/pangolin-auth-reencrypt/
    sudo chmod 0770 $PGLOGS/pangolin-auth-reencrypt/
    

Шаг 5. Обновление компонента pangolin-certs-rotate#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_VER=6.5.x
    sudo dnf install -y ~/pangolin/utilities/pangolin-certs-rotate-$PANGOLIN_VER-sberlinux8.x86_64.rpm
    
  2. (master, replica) Точечно замените конфигурационный файл, ввиду изменения наименований компонентов:

    sudo sed -i "s/\/pgerrorlogs\/05/\/pgerrorlogs\/06/g" /etc/pangolin-certs-rotate/pangolin-certs-rotate.yml
    sudo sed -i "s/sudo systemctl reload pgbouncer/sudo systemctl reload pangolin-pooler/g" /etc/pangolin-certs-rotate/pangolin-certs-rotate.yml
    sudo sed -i "s/sudo systemctl reload patroni/sudo systemctl reload pangolin-manager/g" /etc/pangolin-certs-rotate/pangolin-certs-rotate.yml
    

Шаг 6. Обновление компонента pangolin-diagnostic-tools#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_VER=6.5.x
    sudo dnf install -y ~/pangolin/utilities/pangolin-diagnostic-tool-$PANGOLIN_VER-sberlinux8.x86_64.rpm
    

Шаг 7. Обновление компонента pangolin-security-utilities#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_VER=6.5.x
    sudo dnf install -y ~/pangolin/utilities/pangolin-security-utilities-$PANGOLIN_VER-sberlinux8.x86_64.rpm
    

Шаг 8. Обновление компонента pangolin-backup-tools#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_BACKUP_TOOLS=1.2.2
    sudo dnf install -y ~/pangolin/pangolin-backup-tools-$PANGOLIN_BACKUP_TOOLS-sberlinux8.x86_64.rpm
    
  2. (master, replica) Актуализируйте конфигурационный файл backup-tools-env согласно шаблону ниже, если установка компонента первичная. Файл backup-tools-env находится в /etc/pangolin-backup-tools/.

    backup-tools-env

    backup-tools-env:

    # PATH, used for access to required executable files, default value: "${PATH}:{PGHOME}/bin/"
    PATH="${PATH}:/usr/pangolin-6.5/bin/"
    # path to PGHOME, default value: "/opt/pangolin-backup-tools/bin"
    PGHOME="/opt/pangolin-backup-tools"
    # path to python libraries, required for manage_backup.bin, default value: "/opt/pangolin-backup-tools/lib/python3/site-packages"
    PYTHONPATH="/opt/pangolin-backup-tools/lib/python3/site-packages"
    # path to libraries, required for executable files, default value: "/opt/pangolin-backup-tools/lib"
    LD_LIBRARY_PATH="/opt/pangolin-backup-tools/lib"
    # path to plugins libraries, default value: "/opt/pangolin-backup-tools/lib"
    PG_PLUGINS_PATH="/opt/pangolin-backup-tools/lib"
     
    # Pangolin DBMS server IP, default value: "127.0.0.1"
    ARG_KEY_DBMS_SERVER_IP="127.0.0.1"
    # Pangolin DBMS port, default value: "5433"
    ARG_KEY_DBMS_SERVER_PORT="5433"
    # user used for access to database, default value: "backup_user"
    ARG_KEY_DBMS_CONNECT_USER="backup_user"
    # database to connect, default value: "postgres"
    ARG_KEY_DBMS_CONNECT_DATA_BASE="postgres"
    # path to backup storage, default value: "/pgarclogs"
    ARG_KEY_DBMS_CONNECT_BACKUP_DIR="/pgarclogs/06"
    # password to connect to Pangolin DBMS, default value: 'sample_password'
    # cluster name, default value: "clustername"
    PGINSTANCE="clustername"
    # WAL archives list
    WALSTATE_FILE="$ARG_KEY_DBMS_CONNECT_BACKUP_DIR/wals_to_delete"
    # Log file
    LOG_FILE="$ARG_KEY_DBMS_CONNECT_BACKUP_DIR/archive.log"
    # path to script, used for creating backup files, default value: "/opt/pangolin-backup-tools/bin/manage_backup.sh"
    MANAGE_BACKUP_SCRIPT="/opt/pangolin-backup-tools/bin/manage_backup.sh"
     
    # setting up of connection string
    PANGOLIN_BACKUP_TOOLS_ARGS="$PANGOLIN_BACKUP_TOOLS_ARGS --host $ARG_KEY_DBMS_SERVER_IP"
    PANGOLIN_BACKUP_TOOLS_ARGS="$PANGOLIN_BACKUP_TOOLS_ARGS -p $ARG_KEY_DBMS_SERVER_PORT"
    PANGOLIN_BACKUP_TOOLS_ARGS="$PANGOLIN_BACKUP_TOOLS_ARGS -U $ARG_KEY_DBMS_CONNECT_USER"
    PANGOLIN_BACKUP_TOOLS_ARGS="$PANGOLIN_BACKUP_TOOLS_ARGS -d $ARG_KEY_DBMS_CONNECT_DATA_BASE"
    PANGOLIN_BACKUP_TOOLS_ARGS="$PANGOLIN_BACKUP_TOOLS_ARGS -B $ARG_KEY_DBMS_CONNECT_BACKUP_DIR"
     
    # environment variables to launch manage backup
    export PATH
    export PGHOME
    export PYTHONPATH
    export LD_LIBRARY_PATH
    export PG_PLUGINS_PATH
    

    Предупреждение

    Значения указаны по умолчанию, если они не соответствуют значениям с обновляемого стенда, актуализируйте.

Шаг 9. Обновление компонента pangolin-pooler#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_POOLER=1.5.0
    sudo dnf install -y ~/pangolin/pangolin-pooler-$PANGOLIN_POOLER-sberlinux8.x86_64.rpm
    sudo sed -i "s/\/pgerrorlogs\/05/\/pgerrorlogs\/06/g" /etc/pangolin-pooler/pangolin-pooler.ini
    
  2. (master, replica) Создайте скрипт pangolin-pooler-restart.sh:

    echo "
    #!/bin/sh \
    sudo systemctl restart pangolin-pooler \
    " > ~/pangolin/pangolin-pooler-restart.sh
    sudo cp -r ~/pangolin/pangolin-pooler-restart.sh /etc/pangolin-pooler/pangolin-pooler-restart.sh
    sudo chown postgres:postgres /etc/pangolin-pooler/pangolin-pooler-restart.sh
    sudo chmod 0500 /etc/pangolin-pooler/pangolin-pooler-restart.sh
    

Шаг 10. Обновление компонента pangolin-manager#

  1. (master, replica) Обновите пакет компонента:

    export PANGOLIN_MANAGER=2.1.6
    sudo dnf install -y ~/pangolin/pangolin-manager-$PANGOLIN_MANAGER-sberlinux8.x86_64.rpm
    

Шаг 11. Обновление pangolin-license#

  1. (master, replica) Подготовьте файл с лицензией:

    sudo mkdir /opt/pangolin_license/
    sudo touch /opt/pangolin_license/license.json
    sudo chown -R postgres:pangolin_users /opt/pangolin_license/
    sudo chmod 0770 /opt/pangolin_license/
    sudo chmod 0440 /opt/pangolin_license/license.json
     
    #заполните файл /opt/pangolin_license/license.json
    

Шаг 12. Обновление компонента pangolin-dbms#

  1. (master, replica) Подготовьте СУБД Pangolin новой версии для миграции.

    • Создание новых рабочих каталогов и файлов БД:

      sudo mkdir -p /pgarclogs/06 /pgerrorlogs/06 /pgdata/06/data
      sudo chown -R postgres:postgres /pgdata/06 /pgarclogs/06 /pgerrorlogs/06  
      sudo chmod -R 0700 /pgdata/06 /pgarclogs/06 /pgerrorlogs/06    
      echo "
      /pgarclogs/06/postgresql-*.log {
          rotate 30
          su postgres postgres
          daily
          compress
          delaycompress
          nocreate
          copytruncate
          sharedscripts
          missingok
          notifempty
      }
       
      postrotate
          SIZE_USED=\$(df /pgarclogs/06| awk '{print $5}' | grep -v Use% | tr -d %)
          if [ \"\$SIZE_USED\" -gt 90 ]; then
              logger \"Диск для логов PostgreSQL заполнен более чем на 90%. Пожалуйста, очистите его для успешной работы.\"
          fi
      endscript
       
      " > ~/pangolin/cache/pangolin-dbms
      sudo cp -r ~/pangolin/cache/pangolin-dbms /etc/logrotate.d/pangolin-dbms
      sudo chown root:root /etc/logrotate.d/pangolin-dbms
      sudo chmod 0644 /etc/logrotate.d/pangolin-dbms
      
    • Обновление пакетов компонентов:

      export PANGOLIN_VER=6.5.x
      export PANGOLIN_TIMESCALEDB=2.14.2
      sudo dnf install -y ~/pangolin/pangolin-dbms-6.5-$PANGOLIN_VER-sberlinux8.x86_64.rpm
      sudo dnf install -y ~/pangolin/pangolin-dbms-6.5-client-$PANGOLIN_VER-sberlinux8.x86_64.rpm
       
      # при необходимости
      sudo dnf install -y ~/pangolin/timescaledb/pangolin-timescaledb-6.5-apache-$PANGOLIN_TIMESCALEDB-sberlinux8-x86_64.rpm
      
    • Копирование вспомогательных файлов:

      sudo mkdir /usr/pangolin/3rdparty/
      sudo tar -xvf  ~/pangolin/3rdparty/3rdparty.tar.gz -C /usr/pangolin/3rdparty/
      sudo chown -R postgres:postgres /usr/pangolin/3rdparty/
      sudo chmod  -R 0700 /usr/pangolin/3rdparty/
      
  2. (master) Инициализируйте новую версию СУБД Pangolin:

    sudo /opt/pangolin-ansible-venv-controlled/bin/python3 ~/pangolin/installer/utilities/psql_get_password_hash -t scram-sha-256 -P '<password_postgres>' > ~/pangolin/cache/.tmp_file
    sudo cp -r ~/pangolin/cache/.tmp_file /home/postgres/
    sudo chown postgres:postgres /home/postgres/.tmp_file
    
    sudo -iu postgres
    /usr/pangolin/bin/initdb -D /pgdata/06/data -k -A scram-sha-256 --pwfile /home/postgres/.tmp_file -E UTF8 --update-authid --lc-collate <данные из файла current_value.txt> --lc-ctype <данные из файла current_value.txt> --lc-messages <данные из файла current_value.txt> --lc-monetary <данные из файла current_value.txt> --lc-numeric <данные из файла current_value.txt> --lc-time <данные из файла current_value.txt>
    exit
    

    Пример зполненной команды:

    /usr/pangolin/bin/initdb -D /pgdata/06/data -k -A scram-sha-256 --pwfile /home/postgres/.tmp_file -E UTF8 --update-authid --lc-collate en_US.utf-8 --lc-ctype en_US.utf-8 --lc-messages en_US.utf8 --lc-monetary en_US.utf8 --lc-numeric en_US.utf8 --lc-time en_US.utf8
    
  3. (master, replica) Скопируйте заранее сформированные конфигурационные файлы каталога в рабочие:

    sudo cp -r ~/pangolin/cache/merge/postgresql.conf /pgdata/06/data/postgresql.conf
    sudo cp -r /pgdata/05/data/pg_hba.conf            /pgdata/06/data/pg_hba.conf
    sudo cp -r /pgdata/05/data/postgresql.base.conf   /pgdata/06/data/postgresql.base.conf
    sudo cp -r /pgdata/05/data/postgresql.auto.conf   /pgdata/06/data/postgresql.auto.conf
    sudo chown postgres:postgres /pgdata/06/data/postgresql.base.conf /pgdata/06/data/postgresql.auto.conf /pgdata/06/data/postgresql.conf /pgdata/06/data/pg_hba.conf /etc/pangolin-manager/postgres.yml /pgdata/06/data/patroni.dynamic.json
    sudo chmod 0600 /pgdata/06/data/postgresql.base.conf /pgdata/06/data/postgresql.auto.conf /pgdata/06/data/postgresql.conf /pgdata/06/data/pg_hba.conf /etc/pangolin-manager/postgres.yml /pgdata/06/data/patroni.dynamic.json
    
    #дополнительно для конфигурации с patroni
    sudo cp -r ~/pangolin/cache/merge/postgres.yml    /etc/pangolin-manager/postgres.yml
    sudo cp -r /pgdata/05/data/patroni.dynamic.json   /pgdata/06/data/patroni.dynamic.json
    
  4. (master, replica) Скорректируйте сервисный файл /etc/systemd/system/postgresql.service для конфигурации без patroni:

    echo "
    [Unit]
    Description=Runners PostgreSQL service
    After=syslog.target network.target pangolin-auth-reencrypt@postgres.service pangolin-auth-reencrypt@kmadmin_pg.service
     
    [Service]
    Type=notify
     
    Environment=\"PG_LICENSE_PATH=/opt/pangolin_license\"
    Environment=\"PG_PLUGINS_PATH=/usr/pangolin-6.5/lib\"
    Environment=\"PGCTLTIMEOUT=120\"
    Environment=\"LD_LIBRARY_PATH=/usr/pangolin-6.5/lib\"
    LimitNOFILE=65536
      
    # Pre-commands to start watchdog device
    User=postgres
    Group=postgres
     
    PermissionsStartOnly=true
    ExecStartPre=/bin/mkdir -p /var/run/postgresql
    ExecStartPre=/bin/chown -R postgres:postgres /var/run/postgresql
    ExecReload=/bin/kill -HUP \$MAINPID
     
    WorkingDirectory=/usr/pangolin-6.5/
    ExecStart=/bin/bash -i -c \"/usr/pangolin-6.5/bin/postgres -D /pgdata/06/data\"
    Restart=on-failure
     
    [Install]
    WantedBy=multi-user.target
    " > ~/pangolin/cache/postgresql.service
    sudo cp -r ~/pangolin/cache/postgresql.service /etc/systemd/system/postgresql.service
    sudo chown -R postgres:postgres /etc/systemd/system/postgresql.service
    sudo chmod -R 0600 /etc/systemd/system/postgresql.service
    sudo systemctl daemon-reload
    
  5. (master, replica) Внесите следующие корректировки для миграции:

    sudo sed -i '1ilocal all postgres scram-sha-256 #tmp_line'     /pgdata/05/data/pg_hba.conf
    sudo sed -i '1ilocal all postgres scram-sha-256 #tmp_line'     /pgdata/06/data/pg_hba.conf    
    sudo sed -i -e "\$aautovacuum = 'off' #tmp_line"               /pgdata/05/data/postgresql.conf
    sudo sed -i -e "\$asynchronous_commit = 'off' #tmp_line"       /pgdata/05/data/postgresql.conf
    sudo sed -i -e "\$acron.database_name = 'template1' #tmp_line" /pgdata/05/data/postgresql.conf
    sudo sed -i -e "\$aautovacuum = 'off' #tmp_line"               /pgdata/06/data/postgresql.conf
    sudo sed -i -e "\$asynchronous_commit = 'off' #tmp_line"       /pgdata/06/data/postgresql.conf
    sudo sed -i -e "\$acron.database_name = 'template1' #tmp_line" /pgdata/06/data/postgresql.conf
    
  6. (master) Мигрируйте данные в новую СУБД с помощью pg_upgrade:

    export PANGOLIN_OLD_VER=5.5.x
    export PGPASSWORD=<password_postgres>
    sudo mkdir -p /pgarclogs/pg_upgrade /var/run/postgresql/pg_upgrade
    sudo chown -R postgres:postgres /pgarclogs/pg_upgrade /var/run/postgresql/pg_upgrade
    sudo chmod -R 0700 /pgarclogs/pg_upgrade /var/run/postgresql/pg_upgrade
    sudo -iu postgres
    PGPASSWORD=$PGPASSWORD PG_LICENSE_PATH=/opt/pangolin_license PGHOST=127.0.0.1 /usr/pangolin-6.5/bin/pg_upgrade -b /usr/pangolin-$PANGOLIN_OLD_VER/bin/ -B /usr/pangolin-6.5/bin/ --old-bindirclient /usr/pangolin-$PANGOLIN_OLD_VER/bin/ --new-bindirclient /usr/pangolin-dbms-client-6.5/bin/ -d /pgdata/05/data -D /pgdata/06/data -p 5433 -P 50433 -j 2 --socketdir=/var/run/postgresql/pg_upgrade -l /pgarclogs/pg_upgrade --link -r
    exit
    

    Внимание!

    При предустановленном в СУБД расширении timescaledb, в строку запуска утилиты pg_upgrade, требуется добавить дополнительный флаг -c timescaledb.restoring='on'.

  7. (master) Актуализируйте файлы табличных пространств (ТП):

    sudo rm -rf /pgdata/05/tablespaces/<название ТП>/PG_13_202306131
    sudo mv /pgdata/05/tablespaces /pgdata/06/tablespaces
    
    #Значения для <path> и <oid> необходимо заменить на значения oid и pg_tablespace_location соответственно из файла current_value.txt
    sudo ln -sfn <path> /pgdata/06/data/pg_tblspc/<oid>
    #например, sudo ln -sfn /pgdata/06/tablespaces/Tbl_t /pgdata/06/data/pg_tblspc/16799
    
  8. (replica) В случае кластерной конфигурации сгенерируйте ключ доступа для переноса данных с мастера на реплику:

    sudo -iu postgres
    mkdir -p /pgarclogs/cache/rsync
    ssh-keygen
     
    Generating public/private rsa key pair.
    # Введите имя файла, в котором будет сохранен ключ: /pgarclogs/cache/rsync/ssh_key_rsync
    Enter file in which to save the key (/home/postgres/.ssh/id_rsa): /pgarclogs/cache/rsync/ssh_key_rsync
    # Введите ключевую фразу (опционально):
    Enter passphrase (empty for no passphrase): <passphrase or enter>
    # Введите ту же ключевую фразу еще раз (опционально):
    Enter same passphrase again: <passphrase or enter>
      
    Your identification has been saved in /pgarclogs/cache/rsync/ssh_key_rsync.
    Your public key has been saved in /pgarclogs/cache/rsync/ssh_key_rsync.pub.
    The key fingerprint is:
    SHA256:5VV.........
    The key's randomart image is:
    +---[RSA 3072]----+
    |              ==+|
    |            .BBo+|
    |          .o.=*=+|
    |         o..+ +++|
    |        S .o = =o|
    |          + o *.+|
    |         o =. .* |
    |        ..oo.+. E|
    |        .oo o... |
    +----[SHA256]-----+ 
    

    Копирование ssh-ключа с replica на master:

    ssh-copy-id -i /pgarclogs/cache/rsync/ssh_key_rsync postgres@<ip-address_master>
    
  9. (replica) В случае кластерной конфигурации запустите rsync для переноса данных:

    sshpass -d4 /bin/rsync --delay-updates -F --checksum --archive --rsync-path=rsync --hard-links --progress --size-only --no-inc-recursive --delete --rsh='ssh -S none -i /pgarclogs/cache/rsync/ssh_key_rsync -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' postgres@<ip-address_master>:/pgdata/06 /pgdata
    #если есть табличные пространства, находящиеся в не /pgdata/05, их необходимо тоже перенсти, напрмер: sshpass -d4 /bin/rsync --delay-updates -F --checksum --archive --rsync-path=rsync --hard-links --size-only --stats --dry-run --delete --no-inc-recursive --rsh='ssh -S none -i /pgarclogs/cache/rsync/ssh_key_rsync -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' <ip-address_master>:/pgdata/11/tablespaces/tsin11 /pgdata/11/tablespaces
    
  10. (master) Проиндексируйте данные в БД, выполните очистку и анализ базы данных:

export PGPASSWORD=<password_postgres>
#для конфигурации без pangolin-manager
sudo systemctl restart postgresql
 
#для конфигурации c pangolin-manager
sudo -iu postgres
/usr/pangolin/bin/pg_ctl start -D /pgdata/06/data/
exit  
 
#для любой конфигурации
sudo -iu postgres
PGPASSWORD=$PGPASSWORD /usr/pangolin-dbms-client-6.5/bin/reindexdb -j 2 --all
PGPASSWORD=$PGPASSWORD /usr/pangolin-dbms-client-6.5/bin/vacuumdb -j 2 --analyze-in-stages --all
exit

#для конфигурации без pangolin-manager
sudo systemctl stop postgresql
 
#для конфигурации c pangolin-manager
sudo -iu postgres
/usr/pangolin/bin/pg_ctl stop -D /pgdata/06/data/
exit

Шаг 13. Завершающие действия#

  1. (master, replica) Удалите временные параметры из рабочих конфигурационных файлов:

    sudo sed -i '/local all postgres scram-sha-256 #tmp_line/d' /pgdata/06/data/pg_hba.conf    
    sudo sed -i "/autovacuum = 'off' #tmp_line/d"               /pgdata/06/data/postgresql.conf
    sudo sed -i "/synchronous_commit = 'off' #tmp_line/d"       /pgdata/06/data/postgresql.conf
    sudo sed -i "/cron.database_name = 'template1' #tmp_line/d" /pgdata/06/data/postgresql.conf
    
  2. (master, replica) Удалите неактуальные рабочие файлы исходной БД:

    sudo dnf remove platform-v-pangolin-dbms -y
    sudo rm -rf /usr/pangolin-5* /usr/pgsql-se-05
    sudo ln -sfvn /pgdata/06 /pgdata/data
    sudo rm -rf /pgdata/05 /pgerrorlogs/05 /pgarclogs/05
    sudo rm -rf /etc/postgres/enc_connection_settings.cfg
    sudo rm -rf /etc/postgres/enc_connection_settings_cert.cfg
    sudo rm -rf /etc/postgres/enc_utils_auth_settings.cfg
    sudo rm -rf /etc/postgres/enc_params.cfg*
    sudo rm -rf /opt/omni/lbin/*manage_backup*
    sudo rm -rf /opt/omni/lbin/*pg_se_archlogs*
    sudo rm -rf /etc/systemd/system/pgbouncer.service
    sudo rm -rf /etc/pgbouncer/
    sudo rm -rf /usr/local/bin/pgbouncer
    sudo rm -rf /usr/local/share/doc/pgbouncer/
    sudo rm -rf /usr/local/share//man/man1/pgbouncer.1
    sudo rm -rf /usr/local/share//man/man5/pgbouncer.5
    sudo rm -rf /usr/patroni/patroni_venv
    sudo rm -rf /opt/pangolin-common
    
  3. (master, replica, arbiter) Актуализируйте dynmotd.sh:

    export PANGOLIN_MANGER=2.1.6
    export PANGOLIN_OLD_MANGER=2.1.1 
    export PANGOLIN_FULL_VER=06.005.XX
    export PANGOLIN_FULL_OLD_VER=05.005.XX
     
    sudo sed -i "s/$PANGOLIN_OLD_MANGER/$PANGOLIN_MANGER/g"         /usr/local/sbin/dynmotd.sh
    sudo sed -i "s/$PANGOLIN_FULL_OLD_VER/$PANGOLIN_FULL_VER/g"     /usr/local/sbin/dynmotd.sh
    

Шаг 14. Запуск компонентов СУБД Pangolin#

  1. (master, replica) Запустите компоненты СУБД Pangolin:

    sudo systemctl daemon-reload
    
    sudo systemctl restart pangolin-pooler
    sudo systemctl restart pangolin-certs-rotate
    sudo systemctl restart pangolin-auth-reencrypt@postgres
    sudo systemctl restart pangolin-auth-reencrypt@kmadmin_pg
    

    Дополнительно выполните:

    • для конфигурации без pangolin-manager:

      sudo systemctl restart postgresql
      
    • Для конфигурации с pangolin-manager:

      sudo systemctl restart pangolin-manager
      
    • Для конфигурации с etcd:

      sudo systemctl restart etcd
      
  2. (master) Запустите сторонние сервисы:

    sudo systemctl restart crond
    
  3. (master) В случае конфигурации с pangolin-manager очистите кластер и выведите pangolin-manager из режима паузы:

    sudo -iu postgres
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml remove clustername  
    exit
    sudo systemctl restart pangolin-manager
    sudo -iu postgres
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml edit-config --set 'pause=false' --force
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml restart clustername
    exit
     
    #дополнительно выполните команду на replica 
    sudo systemctl restart pangolin-manager
    
  4. (master) Подготовьте исходную базу для корректной миграции в «Шаг 2. Подготовительные действия» пункт 5.

    Примечание

    В файле /home/postgres/current_value.txt необходимо выявить, в какой БД были найдены следующие сущности: grant_opts_start/revoke_opts_start/grant_opts_stop/revoke_opts_stop. Значение необходимо подставить в скрипты вместо <БД>.

    Также необходимо проверить, какому пользователю были выданы права. Например, backup_user=X/postgres, значит <пользователь> заменить на backup_user, если значение =X/postgres, значит <пользователь> заменить на PUBLIC.

    sudo -iu postgres
     
    #grant_opts_start
    echo "
    SET SESSION AUTHORIZATION <БД>;
    GRANT EXECUTE ON FUNCTION pg_catalog.pg_backup_start TO <пользователь>;
    RESET SESSION AUTHORIZATION;
    " > /home/postgres/grant_opts_start.sql
     
    #grant_opts_stop
    echo "
    SET SESSION AUTHORIZATION <БД>;
    GRANT EXECUTE ON FUNCTION pg_catalog.pg_backup_stop TO <пользователь>;
    RESET SESSION AUTHORIZATION;
    " > /home/postgres/grant_opts_stop.sql
     
    #revoke_opts_start
    echo "
    REVOKE EXECUTE ON FUNCTION pg_catalog.pg_backup_start FROM <пользователь>;
    " > /home/postgres/revoke_opts_start.sql
     
    #revoke_opts_stop
    echo "
    REVOKE EXECUTE ON FUNCTION pg_catalog.pg_backup_stop FROM <пользователь>;
    " > /home/postgres/revoke_opts_stop.sql
    psql -f /home/postgres/grant_opts_start.sql
    psql -f /home/postgres/grant_opts_stop.sql
    psql -f /home/postgres/revoke_opts_start.sql
    psql -f /home/postgres/revoke_opts_stop.sql
    exit
    

Шаг 15. Обновление каталога безопасности#

  1. (master) Добавьте временный параметр enable_protection_catalogs_upgrade из под пользователя postgres в конец конфигурационного файла в зависимости от конфигурации с помощью обычного текстового редактора:

    # Для конфигурации без pangolin-manager отредактируйте конфигурационный файл postgresql.conf
    enable_protection_catalogs_upgrade = True
    
    # Для конфигурации с pangolin-manager отредактируйте конфигурационный файл postgres.yml
    postgresql:
       parameters:
          enable_protection_catalogs_upgrade: True
    
  2. (master) Произведите reload и restart СУБД в зависимости от конфигурации:

    # Для конфигурации без pangolin-manager
    sudo su - postgres
    /usr/pangolin/bin/pg_ctl reload -D /pgdata/data/data
    /usr/pangolin/bin/pg_ctl restart -D /pgdata/data/data
    exit
    
    # Для конфигурации с pangolin-manager
    sudo su - postgres
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml reload clustername
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml restart clustername
    exit
    
  3. (master) Выполните следующую команду в каждой БД поочередно, кроме БД с включенным флагом datallowconn. <DB> - заменить на название базы данных:

    sudo su - postgres
    psql -c "SELECT NOW()" -d <DB>
    exit
    
  4. (master) Удалите временный параметр enable_protection_catalogs_upgrade из конфигурационного файла в зависимости от конфигурации из под пользователя postgres с помощью обычного текстового редактора. И произведите reload и restart СУБД в зависимости от конфигурации:

    # Для конфигурации без pangolin-manager
    sudo su - postgres
    /usr/pangolin/bin/pg_ctl reload -D /pgdata/data/data
    /usr/pangolin/bin/pg_ctl restart -D /pgdata/data/data
    exit
    
    # Для конфигурации с pangolin-manager
    sudo su - postgres
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml reload clustername
    /opt/pangolin-manager/bin/pangolin-manager-ctl -c /etc/pangolin-manager/postgres.yml restart clustername
    exit