如何跟踪PostgreSQL中任何函数的更改
我希望跟踪PostgreSQL中任何函数的更改 示例-假设我在postgesql数据库中有函数如何跟踪PostgreSQL中任何函数的更改,sql,postgresql,triggers,postgresql-9.4,Sql,Postgresql,Triggers,Postgresql 9.4,我希望跟踪PostgreSQL中任何函数的更改 示例-假设我在postgesql数据库中有函数fun\u name(),并且我正在对函数进行修改 现在,我想跟踪记录,比如 DateTime,Schema_name,Function_name,old_func_text,new_func_text 请建议在postgresql中实现这一点的最佳方法 我正在研究事件触发器 谢谢。在Postgres 9.5中,有一个函数可用于事件触发器中,以获取插入/更改对象的oid 日志表: create tab
fun\u name()
,并且我正在对函数进行修改
现在,我想跟踪记录,比如
DateTime,Schema_name,Function_name,old_func_text,new_func_text
请建议在postgresql中实现这一点的最佳方法
我正在研究事件触发器
谢谢。在Postgres 9.5中,有一个函数可用于事件触发器中,以获取插入/更改对象的oid 日志表:
create table function_log (
datetime timestamp,
schema_name text,
function_name text,
tag text,
function_body text);
事件函数和触发器:
create or replace function public.on_function_event()
returns event_trigger
language plpgsql
as $function$
begin
insert into function_log
select now(), nspname, proname, command_tag, prosrc
from pg_event_trigger_ddl_commands() e
join pg_proc p on p.oid = e.objid
join pg_namespace n on n.oid = pronamespace;
end
$function$;
create event trigger on_function_event
on ddl_command_end
when tag in ('CREATE FUNCTION', 'ALTER FUNCTION')
execute procedure on_function_event();
例如:
create or replace function test()
returns int as $$ select 1; $$ language sql;
create or replace function test()
returns int as $$ select 2; $$ language sql;
alter function test() immutable;
select *
from function_log;
datetime | schema_name | function_name | tag | function_body
----------------------------+-------------+---------------+-----------------+---------------
2017-02-26 13:05:15.353879 | public | test | CREATE FUNCTION | select 1;
2017-02-26 13:05:15.353879 | public | test | CREATE FUNCTION | select 2;
2017-02-26 13:05:15.353879 | public | test | ALTER FUNCTION | select 2;
(3 rows)
您可以向触发器添加DROP FUNCTION
command标记,然后使用pg\u event\u trigger\u DROP\u objects()
函数,类似于pg\u event\u trigger\u ddl\u commands()
不幸的是,在Postgres 9.4中没有
pg\u事件\u触发器\u ddl\u命令()。您可以尝试使用current\u query()
获取插入/更改的对象,或者在C
中编写触发器函数。我认为更简单的方法是将Postgres升级到9.5+。关于限制的一些注意事项
您不能在PostgreSQL中的系统表上放置触发器,因此无法在这方面创建审计跟踪
您可能需要使用PostgreSQL外部的东西来管理版本控制。所以我推荐像sqitch这样的东西
pgdump的一个主要问题是不能保证事物的顺序是唯一的,所以简单的dump和version会给你一个非常糟糕的信噪比
现在您可以做的一件事是使用ddl捕获事件,然后记录和处理。这仍然需要您在设计方面付出大量努力,但这是完全可能的。如果您使用事件触发器,请首先在登台系统上进行彻底测试
我会说,当我需要这样做时,我通常会使用事件触发器和系统表的副本,因此我会从旧目录更新表并记录更改。完整版本,带有拖放和触发器跟踪功能
create schema hist;
create table hist.functions (
datetime timestamp,
schema_name text,
function_name text,
oper char(1),
function_body text,
ip text);
create or replace function hist.on_function_event_hist()
returns event_trigger
language plpgsql
as $function$
begin
insert into hist.functions
select now(),
coalesce(nspname, t.trigger_schema),
coalesce(proname, t.trigger_name),
command_tag::char(1),
coalesce(pg_get_functiondef(p.oid),
'create trigger ' || trigger_name || ' ' || action_timing || ' ' || event_manipulation ||
E'\non\n' || quote_ident(event_object_schema) || '.' || quote_ident(event_object_table) || ' for ' || action_orientation || coalesce(E'\rwhen (' || action_condition || E')\r', E'\r') || action_statement || ';'),
coalesce(inet_client_addr()::text, '::1')
from pg_event_trigger_ddl_commands() e
left join pg_proc p on p.oid = e.objid
left join pg_namespace n on n.oid = pronamespace
left join information_schema.triggers t on object_identity like t.trigger_name || '%';
end
$function$;
create event trigger on_function_event
on ddl_command_end
when tag in ('CREATE FUNCTION', 'ALTER FUNCTION', 'ALTER TRIGGER', 'CREATE TRIGGER')
execute procedure hist.on_function_event_hist();
create or replace function hist.on_function_drop_func()
returns event_trigger
language plpgsql
as $function$
begin
insert into hist.functions
SELECT now(),
schema_name,
object_identity,
'D',
null,
coalesce(inet_client_addr()::text, '::1')
FROM pg_event_trigger_dropped_objects();
end
$function$;
CREATE EVENT TRIGGER on_function_drop
ON sql_drop
EXECUTE PROCEDURE hist.on_function_drop_func();
谢谢你的解决方案。您能否建议我是否可以将日志存储在数据库表中。由于pg_dump不能保证函数之类的排序,您希望信噪比是多少?我对pg_dump
的第一个回答可能过于笼统,因此我完全修改了答案。@klin感谢您的努力。非常类似于我试图找到的解决方案。