Ручное обновление с переносом данных СУБД 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.sqlSELECT 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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.sqlWITH 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. Резервное копирование рабочих файлов компонентов#
(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/
(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/(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.(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(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(master) Удалите строку
host replication postgres 127.0.0.1/32 scram-sha-256из файла/pgdata/05/data/pg_hba.confили из файла/etc/patroni/postgres.ymlдля конфигурации сpatroni.(master) Перечитайте обновленный конфигурационный файл БД.
Шаг 2. Подготовительные действия#
(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.shpangolin-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 "Набор проверок не является исчерпывающим. Для обновления рекомендуем использовать автоматизированные скрипты."Ожидаемый результат:

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

Предупреждение
Набор проверок не является исчерпывающим. Для обновления рекомендуется использовать автоматизированные скрипты.
(master, replica, arbiter) Скачайте дистрибутив в рабочий каталог и распакуйте его. Далее по инструкции путь к компонентам дистрибутива будет формироваться с использованием префикса
~/pangolin.Действие по скачиванию дистрибутива:
mkdir -p ~/pangolin tar -xzvf pangolin_6.tar.gz -C ~/pangolin(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(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)(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(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(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(master) Проверьте отсутствие большого количества транзакций с незавершенным статусом. Для этого выполните следующий запрос:
sudo -iu postgres psqlSELECT * 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- имя БД, полученное в результате выполнения запроса выше.(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#
(master) В случае конфигурации с
patroniпереведитеpatroniв режим паузы:sudo -iu postgres /usr/patroni/patroni_venv/bin/patronictl -c /etc/patroni/postgres.yml edit-config --set 'pause=true' --force exit(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
(replica, master, arbiter) Остановите сторонние компоненты:
sudo systemctl stop crond
Шаг 4. Обновление компонента pangolin-auth-reencrypt#
(master, replica) Обновите пакет компонента:
export PANGOLIN_VER=6.5.x sudo dnf install -y ~/pangolin/utilities/pangolin-auth-reencrypt-$PANGOLIN_VER-sberlinux8.x86_64.rpm(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(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#
(master, replica) Обновите пакет компонента:
export PANGOLIN_VER=6.5.x sudo dnf install -y ~/pangolin/utilities/pangolin-certs-rotate-$PANGOLIN_VER-sberlinux8.x86_64.rpm(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#
(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#
(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#
(master, replica) Обновите пакет компонента:
export PANGOLIN_BACKUP_TOOLS=1.2.2 sudo dnf install -y ~/pangolin/pangolin-backup-tools-$PANGOLIN_BACKUP_TOOLS-sberlinux8.x86_64.rpm(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#
(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(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#
(master, replica) Обновите пакет компонента:
export PANGOLIN_MANAGER=2.1.6 sudo dnf install -y ~/pangolin/pangolin-manager-$PANGOLIN_MANAGER-sberlinux8.x86_64.rpm
Шаг 11. Обновление pangolin-license#
(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#
(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/
(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(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(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(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(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'.(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(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>(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(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. Завершающие действия#
(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(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(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#
(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
(master) Запустите сторонние сервисы:
sudo systemctl restart crond(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(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. Обновление каталога безопасности#
(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(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(master) Выполните следующую команду в каждой БД поочередно, кроме БД с включенным флагом
datallowconn. <DB> - заменить на название базы данных:sudo su - postgres psql -c "SELECT NOW()" -d <DB> exit(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