Изменение данных локализации при обновлении версии ОС
Актуально для СУБД 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;
При обнаружении в таблице дубликатов неактуальные повторные записи нужно удалить.
Учитывайте размер индекса и нагрузку на БД.