所以,总结一下我们关于 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
列。我们假设它可能发生在故障转移期间,因为您发生了一些促销活动,但最终,这只是纯粹的猜测。