postgresql-10 - 无法使用 timescaledb 扩展 postgresql 数据库
问题描述
我使用 Patroni 创建了一个具有 3 个节点的 PostgreSQL 集群。
我正在使用 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 的缓存查找失败
解决方案
所以,总结一下我们关于 Slack 的讨论,这就是问题所在。我在这里总结一下,因为它对遇到类似问题的其他人很有用。
TD;博士。您在这台机器上的所有扩展都遇到了问题,不仅是 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
,在您的情况下,该 OID 包含:
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
包含错误的 OIDlanvalidator
列。我们假设它可能发生在故障转移期间,因为您发生了一些促销活动,但最终,这只是纯粹的猜测。
推荐阅读
- javascript - 以数组为参数的 for 循环中的 setTimeout 行为不端
- python - 程序完全跳过函数中的代码
- swift - 从 Firebase 实时数据库解码 JSON
- c++ - C ++:声明对象时“不允许不完整的类型”-原因是什么?
- c# - GetComponentInChildren 如何统一
- php - PHP访问数组中的SimpleXML数据
- php - Wordpress - 回声内爆
- f# - 对用户定义的数据类型中的元素求和
- vidyo - 连接失败VIDYO_CONNECTORFAILREASON_ConnectionFailed onFailure
- c - Visual Studio 2017 中的 C 文件处理