Невозможно расширить базу данных postgresql с помощью шкалы времениb

Я создал кластер PostgreSQL с 3 узлами, используя Patroni.

Я использую Ubuntu 18.04, Postgresql-10 и Timescaledb 1.4.2.

В postgresql.conf файл я включил shared_preload_libraries = 'timescaledb'

При расширении postresql на timescaledb с помощью команды

CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE; 

это дает ошибку

ОШИБКА: не удалось выполнить поиск в кеше для функции 1


person Pravin Kumbhar    schedule 24.10.2019    source источник
comment
Это говорит о некотором повреждении базы данных. Можете ли вы проверить, установлено ли у вас расширение уже с select name, installed_version from pg_available_extensions where name = 'timescaledb'?   -  person Mats Kindahl    schedule 30.10.2019
comment
iu_timeseries = # выберите имя, установленную_версию из pg_available_extensions, где name = 'timescaledb'; имя | установленная_версия ------------- + ------------------- шкала времениb | (1 ряд)   -  person Pravin Kumbhar    schedule 30.10.2019
comment
я получил такой результат   -  person Pravin Kumbhar    schedule 30.10.2019
comment
я получил такой вывод, он не показывает установленную версию   -  person Pravin Kumbhar    schedule 30.10.2019
comment
Да, у меня тоже самое. Я пробовал это локально как с shared_preload_libraries, так и без него, и это сработало в обоих случаях. Если у некоторых столбцов был неправильный тип, это могло вызвать эту ошибку, поэтому вы используете совпадающие версии PostgreSQL и TimescaleDB?   -  person Mats Kindahl    schedule 30.10.2019


Ответы (1)


Итак, подведем итоги нашего обсуждения Slack, вот в чем была проблема. Я резюмирую его здесь, поскольку он может быть полезен другим, сталкивающимся с аналогичной проблемой.

TD; DR. У вас были проблемы со всеми расширениями на этом компьютере, не только с TimescaleDB, и проблема оказалась связана с созданием новых функций C, которые выполняло расширение. .

Когда функции определены, PostgreSQL принимает часть после LANGUAGE (в данном случае C) и ищет валидатор языка в pg_languages. Код для этого находится в CreateFunction в файле functioncmds.c.

В вашем случае pg_languages содержал:

SELECT * FROM pg_languages;
lanname  | lanowner | lanispl | lanpltrusted | lanplcallfoid | laninline | lanvalidator | lanacl
----------+----------+---------+--------------+---------------+-----------+--------------+--------
internal |       10 | f       | f            |             0 |         0 |         2246 |
sql      |       10 | f       | t            |             0 |         0 |         2248 |
plpgsql  |       10 | t       | t            |         13005 |     13006 |        13007 |
c        |       10 | f       | f            |             0 |         0 |            1 |
(4 rows)

Из приведенной выше таблицы OID для валидатора языка (который является нашим виновником) равен 1.

Как только это будет сделано, PostgreSQL вызовет валидатор с функцией, которую нужно определить, и позволит валидатору проверить правильность определения функции. Это делается в ProcedureCreate в файле pg_proc.c.

Он продолжает поиск OID функции в таблице pg_proc, которая в вашем случае содержала:

SELECT oid, proname FROM pg_proc WHERE oid = 1;
oid | proname
-----+---------
(0 rows)

Итак, процедура для валидатора языка не найдена, и он генерирует ошибку здесь (это внутри fmgr_info_cxt_security в fmgr.c):

    /* Otherwise we need the pg_proc entry */
    procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
    if (!HeapTupleIsValid(procedureTuple))
        elog(ERROR, "cache lookup failed for function %u", functionId);
    procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);

Это можно исправить, посмотрев правильный языковой валидатор для использования. Все встроенные валидаторы названы fmgr_<lang>_validator, поэтому мы можем найти их, используя:

SELECT oid, proname FROM pg_proc WHERE proname LIKE '%fmgr%validator%';
 oid  |         proname         
------+-------------------------
 2246 | fmgr_internal_validator
 2247 | fmgr_c_validator
 2248 | fmgr_sql_validator
(3 rows)

Таким образом, этот запрос обновит столбец lanvalidator, чтобы использовать правильный валидатор.

UPDATE pg_languages
   SET lanvalidator = (SELECT oid FROM pg_proc WHERE proname = 'fmgr_c_validator')
 WHERE lanname = 'c'

Обратите внимание, что это объясняет, почему вы получаете ошибку, но не объясняет, почему pg_languages содержит неправильный OID для столбца lanvalidator. Мы предположили, что это могло произойти во время аварийного переключения, поскольку у вас было несколько рекламных акций, но в конечном итоге это чистая догадка.

person Mats Kindahl    schedule 31.10.2019
comment
Этот вопрос более подробно обсуждается в psql-general - person Mats Kindahl; 31.10.2019
comment
Ты спас мне день. - person Isuru Pathirana; 29.01.2020