PostgreSQL初始化时创建扩展

原创
2020/08/05 10:40
阅读数 477

本篇讲如何在初始化时创建扩展,大体步骤与创建表相同,主要问题是如何处理需要预加载的扩展。

 

1、扩展的加载

扩展的库加载发生在第一次访问扩展时,如果我们一直没有使用它,那么在数据库运行期间是不会发生加载动作的。以下几种方式都会触发:(1)、设置为preload;(2)、调用引用它的外部函数;(3)、LOAD命令;(4)、访问它的外部表(fdw扩展);(5)、CREATE EXTENSION创建时,等等。

 

2、共享预加载

有一些扩展必须定义在 shared_preload_libraries 中,在接收客户端连接之前加载。这类扩展往往会有一个检查,防止用户忘记。

if (!process_shared_preload_libraries_in_progress)
  return;

摘自 pg_stat_statements,这里它没有报错,而是直接返回。如果在session中LOAD,是没有任何作用的,因为它所需要的hook都没有设置,见代码。

但有些扩展在编写时,会直接报错:

  if (!process_shared_preload_libraries_in_progress)
    ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
          errmsg("xxx must be loaded via shared_preload_libraries")));

 

3、初始化时预加载

在initdb中,已经有创建扩展的动作,就是PL/pgSQL,见函数 load_plpgsql(历史版本,曾经叫做“CREATE LANGUAGE”)。增加自己的扩展,类似于在初始化时建表,增加自己的脚本即可。但如果是上述非初始化加载会直接报错的编码,initdb会因为错误被中断:

performing post-bootstrap initialization ... 2020-08-03 09:57:26.734 CST [11438] FATAL:  XXX must be loaded via shared_preload_libraries
2020-08-03 09:57:26.734 CST [11438] STATEMENT:  CREATE EXTENSION XXX;

因为StandAlone模式下不加载 shared library,代码见 PostgressMain()。

 

4、代码修改

因为我们只是想在初始化时加载,修改办法很简单,在检查process_shared_preload_libraries_in_progress之前:

if (!IsPostmasterEnvironment)
  return;

这个修改不会影响初始化之后的插件使用,摘自PG注释:

IsPostmasterEnvironment is true in a postmaster process and any postmaster child process; it is false in a standalone process (bootstrap or standalone backend).

 

我亦无他,惟手熟尔。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部