Перейти к основному содержимому

Изменение данных локализации при обновлении версии ОС

Актуально для СУБД Pangolin версии 6.x.x.

Данные языкового стандарта предоставляются библиотекой glibc. При обновлении с переносом данных происходит замена библиотеки с версии glibc-2.17 на glibc-2.28. В версии 2.28, выпущенной 2018-08-01, было включено крупное обновление данных локали, которое потенциально может повлиять на данные пользователей СУБД.

Необходимо учесть, что индексы, полученные скриптом, должны быть перестроены по завершении обновления в каждой БД до запуска промышленной нагрузки на СУБД:

SELECT DISTINCT indrelid::regclass::text, indexrelid::regclass::text, collname, pg_get_indexdef(indexrelid)
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s
JOIN pg_collation c ON coll=c.oid
WHERE collprovider IN ('d', 'c') AND collname NOT IN ('C', 'POSIX');

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

#!/bin/bash
read -s -p "Введите пароль: " pass
echo
echo
# Получаем список баз данных
dblist=$(PGPASSWORD=$pass psql -t -c "select string_agg(datname, ' ')
from pg_database where datname not in ('template0','template1');")
for i in $dblist
do
# Получаем список индексов в БД
dbidx=$(PGPASSWORD=$pass psql -d $i -t -c "\
SELECT DISTINCT indexrelid::regclass::text idx_name \
FROM (SELECT indexrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s \
JOIN pg_collation c ON coll=c.oid \
WHERE c.collprovider IN ('d', 'c') AND c.collname NOT IN ('C', 'POSIX') \
AND indexrelid NOT IN (SELECT DISTINCT inhparent FROM pg_inherits);")

echo "Текущая БД : $i"
# Выполняем REINDEX для индексов
for j in $dbidx
do
echo "Текущий обрабатываемый индекс : reindex index $j;"
PGPASSWORD=$pass psql -d $i -c "reindex index $j;"
done
echo "------------------------------"
done

Рекомендуется перестроить потенциально поврежденные индексы в конкурентном режиме:

#!/bin/bash
read -s -p "Введите пароль: " pass
echo
echo
# Получаем список баз данных
dblist=$(PGPASSWORD=$pass psql -t -c "select string_agg(datname, ' ')
from pg_database where datname not in ('template0','template1');")
for i in $dblist
do
# Получаем список индексов в БД
dbidx=$(PGPASSWORD=$pass psql -d $i -t -c "\
SELECT DISTINCT indexrelid::regclass::text idx_name \
FROM (SELECT indexrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s \
JOIN pg_collation c ON coll=c.oid \
WHERE c.collprovider IN ('d', 'c') AND c.collname NOT IN ('C', 'POSIX') \
AND indexrelid not in (SELECT distinct inhparent FROM pg_inherits);")

echo "Текущая БД : $i"
# Выполняем REINDEX для индексов
for j in $dbidx
do
echo "Текущий обрабатываемый индекс : reindex index concurrently $j;"
PGPASSWORD=$pass psql -d $i -c "reindex index concurrently $j;"
done
echo "------------------------------"
done

Для проверки существующих индексов на возможные инварианты, включая расхождения в лексическом порядке с учетом правил сортировки, рекомендуется использовать скрипт на основе расширения amcheck. Для установки расширения amcheck выполните команду от суперпользователя в каждой БД:

CREATE EXTENSION amcheck SCHEMA ext;

Далее в каждой БД запустите скрипт:

do $$
declare stmt record;
declare ret record;
declare verbose_check_indexes boolean:=true; --для большого количества индексов рекомендуется установить в false для сокращения вывода
begin
IF (select installed_version from pg_available_extensions where name='amcheck') is not null then
for stmt in
SELECT DISTINCT indrelid::regclass::text as table_name,
indexrelid::regclass::text as index_name,
'select ext.bt_index_check('''||indexrelid::regclass::text||''');' as check_command
,'reindex index concurrently '||indexrelid::regclass::text||';' as reindex_command
,indexrelid as id
FROM (SELECT indexrelid, indrelid, indcollation[i] coll FROM pg_index, generate_subscripts(indcollation, 1) g(i)) s
JOIN pg_collation c ON coll=c.oid
WHERE collprovider IN ('d', 'c') AND collname NOT IN ('C', 'POSIX') AND
indexrelid NOT IN (SELECT distinct inhparent FROM pg_inherits)
loop
begin
execute stmt.check_command into ret;
IF verbose_check_indexes then
raise notice 'таблица % индекс % проверка прошла успешно',stmt.table_name,stmt.index_name ;
END IF;
exception when others then
raise notice '--------------------------------------%ОШИБКА таблица % индекс %. % Для полного текста ошибки выполните (%). % Для реиндекса выполните (%)% Размер индекса %. % %-----------------------------------------------',chr(10), stmt.table_name,stmt.index_name,chr(10),stmt.check_command,chr(10),stmt.reindex_command,chr(10),pg_size_pretty(pg_total_relation_size(stmt.index_named)),( select case when indisunique then 'Индекс уникален' else 'Индекс не уникален' end from pg_index where indexrelid=stmt.index_named ),chr(10) ;
end;
end loop;
ELSE
raise notice 'установите расширение amcheck';
END IF;
end ; $$;

При отсутствии ошибок будет получено сообщение вида:

NOTICE:  таблица hint_plan.hints индекс hint_plan.hints_norm_and_app проверка прошла успешно

При возникновении ошибок:


NOTICE: --------------------------------------
ОШИБКА таблица tron.products индекс tron.products_pkey.
Для полного текста ошибки выполните (select ext.bt_index_check('tron.products_pkey');).
Для реиндекса выполните (reindex index concurrently tron.products_pkey;)
Размер индекса 0 bytes. Индекс уникален
-----------------------------------------------

Статус индекса можно узнать при помощи запроса:

select ext.bt_index_check('tron.products_pkey');

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

reindex index concurrently tron.products_pkey;

При обнаружении в таблице дубликатов неактуальные повторные записи нужно удалить.

Внимание!

Учитывайте размер индекса и нагрузку на БД.