模式缓存
PostgREST 需要来自数据库模式的元数据来提供一个抽象 SQL 细节的 REST API。这方面的一个例子是 资源嵌入 的接口。
获取此元数据需要昂贵的查询。为了避免重复此工作,PostgREST 使用模式缓存。
模式缓存重新加载
为了防止模式缓存过时(当您对数据库进行更改时会发生),您需要重新加载它。
您可以使用 UNIX 信号或 PostgreSQL 通知来完成此操作。也可以使用 事件触发器 自动完成此操作。
使用 Unix 信号重新加载架构缓存
要手动重新加载缓存而不重启 PostgREST 服务器,请向服务器进程发送 SIGUSR1 信号。
killall -SIGUSR1 postgrest
对于 docker,您可以执行
docker kill -s SIGUSR1 <container>
# or in docker-compose
docker-compose kill -s SIGUSR1 <service>
使用 NOTIFY 重新加载架构缓存
要从数据库内部重新加载架构缓存,可以使用 NOTIFY
命令。请参阅 监听器。
NOTIFY pgrst, 'reload schema'
自动架构缓存重新加载
您可以进行自动重新加载,并忘记存在架构缓存。为此,请使用 事件触发器 和 NOTIFY
。
-- 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();