Refresh Materialized View Concurrently突然失效,报ogr_system_tables权限错误
问题分析与解决方案
核心问题
使用CONCURRENTLY刷新物化视图时,会创建临时表用于增量更新逻辑,当这些临时表被删除时,触发了ogr_system_tables.event_trigger_function_for_metadata()事件触发器函数,但该函数在处理临时表的DROP操作时出现权限异常——即便使用管理员账号,也因触发器的执行上下文或逻辑问题导致权限不足。而普通刷新(无CONCURRENTLY)不会触发该路径的逻辑,因此能正常执行。
分步解决方案
1. 定位关联的事件触发器
先找出绑定到目标函数的事件触发器:
SELECT evtname, evtevent, evtfuncid::regproc FROM pg_event_trigger WHERE evtfuncid = 'ogr_system_tables.event_trigger_function_for_metadata()'::regproc;
2. 临时应急方案(业务紧急时)
先禁用该事件触发器,完成物化视图刷新后再启用:
-- 禁用触发器 ALTER EVENT TRIGGER <触发器名称> DISABLE; -- 执行CONCURRENTLY刷新 REFRESH MATERIALIZED VIEW CONCURRENTLY <你的物化视图名称>; -- 重新启用触发器 ALTER EVENT TRIGGER <触发器名称> ENABLE;
3. 根本修复:修改触发器函数逻辑
问题出在触发器函数未过滤临时表的处理,导致对临时表的操作触发权限错误。修改函数,跳过临时表的处理:
CREATE OR REPLACE FUNCTION ogr_system_tables.event_trigger_function_for_metadata() RETURNS event_trigger LANGUAGE plpgsql AS $$ DECLARE obj record; BEGIN FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() LOOP -- 跳过所有临时表的处理逻辑 IF obj.schema_name LIKE 'pg_temp%' THEN CONTINUE; END IF; -- 保留原有的非临时表处理逻辑(替换为你函数原有的代码) -- 原第8行的SQL语句放在此处 END LOOP; END; $$;
4. 检查触发器函数的执行权限
如果上述修改后仍有问题,检查函数是否为SECURITY DEFINER模式(执行时使用函数创建者权限而非当前用户权限):
SELECT proname, proowner::regrole, prosecdef FROM pg_proc WHERE proname = 'event_trigger_function_for_metadata' AND pronamespace = 'ogr_system_tables'::regnamespace;
如果prosecdef为true,改为SECURITY INVOKER(使用当前执行用户的权限,即你的管理员账号):
ALTER FUNCTION ogr_system_tables.event_trigger_function_for_metadata() SECURITY INVOKER;
内容的提问来源于stack exchange,提问作者Luffydude
相关产品推荐
相关产品推荐

