架构缓存#

PostgREST需要数据库模式中的元数据来提供抽象SQL详细信息的REST API。这方面的一个例子是 资源嵌入

获取此元数据需要代价高昂的查询。为避免重复此工作,PostgREST使用模式缓存。

架构缓存重新加载#

为了不让模式缓存变得陈旧(在您更改数据库时发生),您需要重新加载它。

您可以使用Unix Signals或PostgreSQL通知来执行此操作。也可以使用以下命令自动执行此操作 event triggers

备注

  • 请求将等待,直到架构缓存重新加载完成。这是为了防止由于过时的架构缓存而导致的客户端错误。

  • 如果您正在使用 数据库内配置 ,则架构缓存重新加载将 reload the configuration 也是。

使用Unix信号重新加载架构缓存#

要在不重新启动PostgREST服务器的情况下手动重新加载缓存,请向服务器进程发送SIGUSR1信号。

killall -SIGUSR1 postgrest

对于码头,您可以执行以下操作:

docker kill -s SIGUSR1 <container>

# or in docker-compose
docker-compose kill -s SIGUSR1 <service>

使用NOTIFY重新加载架构缓存#

PostgREST还允许您通过PostgreSQL重新加载其方案缓存 NOTIFY

NOTIFY pgrst, 'reload schema'

这在无法发送SIGUSR1 Unix信号的环境中非常有用。就像在云托管容器或Windows系统上一样。

这个 pgrst 默认情况下启用通知通道。有关配置通道的信息,请参见 DB-通道数据库通道已启用

自动重新加载架构缓存#

您可以执行自动重载,然后忽略模式缓存。为此,请使用 event triggerNOTIFY

-- Create an event trigger function
CREATE OR REPLACE FUNCTION pgrst_watch() RETURNS event_trigger
  LANGUAGE plpgsql
  AS $$
BEGIN
  NOTIFY pgrst, 'reload schema';
END;
$$;

-- This event trigger will fire after every ddl_command_end event
CREATE EVENT TRIGGER pgrst_watch
  ON ddl_command_end
  EXECUTE PROCEDURE pgrst_watch();

现在,每当 pgrst_watch 触发器触发时,PostgREST将自动重新加载架构缓存。

要禁用自动重新加载,请放下触发器。

DROP EVENT TRIGGER pgrst_watch

更细粒度的事件触发器#

您可以细化前一个事件触发器,使其仅对与架构缓存相关的事件作出反应。这还可以防止在函数内创建临时表时不必要的重载。

-- watch CREATE and ALTER
CREATE OR REPLACE FUNCTION pgrst_ddl_watch() RETURNS event_trigger AS $$
DECLARE
  cmd record;
BEGIN
  FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
  LOOP
    IF cmd.command_tag IN (
      'CREATE SCHEMA', 'ALTER SCHEMA'
    , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE'
    , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE'
    , 'CREATE VIEW', 'ALTER VIEW'
    , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW'
    , 'CREATE FUNCTION', 'ALTER FUNCTION'
    , 'CREATE TRIGGER'
    , 'CREATE TYPE', 'ALTER TYPE'
    , 'CREATE RULE'
    , 'COMMENT'
    )
    -- don't notify in case of CREATE TEMP table or other objects created on pg_temp
    AND cmd.schema_name is distinct from 'pg_temp'
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$ LANGUAGE plpgsql;

-- watch DROP
CREATE OR REPLACE FUNCTION pgrst_drop_watch() RETURNS event_trigger AS $$
DECLARE
  obj record;
BEGIN
  FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
  LOOP
    IF obj.object_type IN (
      'schema'
    , 'table'
    , 'foreign table'
    , 'view'
    , 'materialized view'
    , 'function'
    , 'trigger'
    , 'type'
    , 'rule'
    )
    AND obj.is_temporary IS false -- no pg_temp objects
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER pgrst_ddl_watch
  ON ddl_command_end
  EXECUTE PROCEDURE pgrst_ddl_watch();

CREATE EVENT TRIGGER pgrst_drop_watch
  ON sql_drop
  EXECUTE PROCEDURE pgrst_drop_watch();