【问题标题】:Unable to extend postgresql database with timescaledb无法使用 timescaledb 扩展 postgresql 数据库
【发布时间】:2019-10-24 11:36:47
【问题描述】:

我使用 Patroni 创建了一个具有 3 个节点的 PostgreSQL 集群。

我使用的是 Ubuntu 18.04、Postgresql-10 和 Timescaledb 1.4.2。

postgresql.conf 文件中我已包含shared_preload_libraries = 'timescaledb'

当使用命令扩展postresqltimescaledb

CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE; 

它给出了错误

错误:函数 1 的缓存查找失败

【问题讨论】:

  • 这表明某种数据库损坏。你能检查一下你是否已经用select name, installed_version from pg_available_extensions where name = 'timescaledb' 安装了扩展程序吗?
  • iu_timeseries=# select name, installed_version from pg_available_extensions where name ='timescaledb';姓名 | installed_version -------------+----------------- timescaledb | (1 行)
  • 我得到了这样的输出
  • 我得到这样的输出它没有显示安装的版本
  • 是的,我也一样。我在有和没有shared_preload_libraries 的情况下都在本地尝试过,并且在这两种情况下都有效。如果某些列的类型错误,可能会导致此错误,那么您使用的是 PostgreSQL 和 TimescaleDB 的匹配版本吗?

标签: postgresql-10 timescaledb patroni


【解决方案1】:

所以,总结一下我们关于 Slack 的讨论,这就是问题所在。我在这里总结一下,因为它可能对遇到类似问题的其他人有用。

TD;DR. 您在这台机器上的所有 扩展都有问题,不仅是 TimescaleDB,而且问题结果与创建新的 C 函数有关扩展正在做。

定义函数时,PostgreSQL 会在 LANGUAGE(在本例中为 C)之后执行部分,并在 pg_languages 中查找语言验证器。代码在文件functioncmds.c 中的CreateFunction 中。

在您的情况下,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 将使用要定义的函数调用验证器,并允许验证器检查函数是否正确定义。这是在文件pg_proc.c 中的ProcedureCreate 中完成的。

它继续在pg_proc 表中查找函数的 OID,在您的情况下,该表包含:

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

因此,没有找到语言验证器的过程,它在此处生成错误(这是在 fmgr.c 中的 fmgr_info_cxt_security 内):

    /* 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 包含 lanvalidator 列的错误 OID。我们假设它可能是在故障转移期间发生的事情,因为您进行了一些促销活动,但最终,这纯粹是猜测。

【讨论】:

  • psql-general中关于这个问题的讨论比较长
  • 你拯救了我的一天。
猜你喜欢
  • 2021-02-05
  • 2020-06-25
  • 2020-02-11
  • 2018-09-10
  • 2019-12-31
  • 1970-01-01
  • 2017-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多