2017-02-25 238 views

回答

4

Postgres 9.5有一个函数pg_event_trigger_ddl_commands()可以在事件触发器中使用以获取插入/更改对象的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命令标签添加到扳机,然后使用功能pg_event_trigger_dropped_objects()以类似于pg_event_trigger_ddl_commands()的方式。

遗憾的是,在Postgres 9.4中没有pg_event_trigger_ddl_commands()。您可以尝试使用current_query()获取插入/更改的对象,或在C中写入触发器函数。我认为更简单的方法是将Postgres升级到9.5+。

+0

感谢您的解决方案。你可以请建议,如果我可以在数据库表中存储日志。 – Tajinder

+0

既然pg_dump不能保证像函数这样的东西排序,那么你认为信噪比会是多少? –

+1

我的第一个回答是'pg_dump',可能太笼统了,所以我完全修改了答案。 – klin

1

的约束的几个注意事项。

  1. 您不能在PostgreSQL的系统表上放置触发器,因此在这方面无法创建审计跟踪。
  2. 你可能需要使用一些外部的PostgreSQL的管理版本。所以我会推荐像sqitch这样的东西。

pgdump的一个主要问题是事物的排序不能保证是唯一的,所以简单的转储和版本会给你一个很糟糕的信噪比。

现在有一件事你可能做的是在ddl上使用event triggers来捕获事件然后记录和处理。这仍然需要您在设计方面付出很多努力,但完全有可能。如果您使用事件触发器,请先在分级系统上进行彻底测试!

时候我已经需要做这样的事情,我平时已经使用事件触发器和系统表的副本,所以我更新从旧目录表和日志的变化,我会说。