【问题标题】:How to use PostgreSql trigger and procedure to audit/restore parent-child tables如何使用 PostgreSql 触发器和过程来审计/恢复父子表
【发布时间】:2014-04-27 23:31:46
【问题描述】:

我们希望保留某些表格的编辑历史,并在必要时恢复它们。例如,我们有以下表格。我们希望在执行插入/删除操作时审核 emp 表。除此之外,当版本字段发生更新时,我们还需要将相关 emp_addr 记录的副本保存到 emp_addr_audit。当用户想要回滚到某个emp的特定版本时,我们需要从emp_audit和emp_addr_audit中恢复记录。

我正在考虑使用触发器来进行审计工作和使用程序来进行恢复工作。我知道关键部分是如何在审计和恢复工作中保持父子表的完整性。我需要一些建议。谢谢。

 create table emp (
 emp_id integer primary key,
 version varchar(50)
);

/* Address table */    
create table emp_addr (
 addr_id integer primary key,
 emp_id integer, -- references table emp
 line1 varchar(30),

);

/* Audit table for emp table */    
create table emp_audit (
 operation   character(1),
 updatetime timestamp,
 emp_id integer,
 version varchar(50)

);

/* Audit table for emp_addr table */    
create table emp_addr_audit (
 operation   character(1),
 addr_id integer,
 emp_id integer,
 line1 varchar(30),
);

【问题讨论】:

  • 您必须要求任何回滚都回滚从现在到该记录及其子记录的目标时间之间的 all 更改,而不是直接恢复目标记录。或者,您可以编写审核记录,在每次任何父项或子项更改时复制父项及其所有子项(例如,json 表示法)。这样您就可以删除父项及其所有子项,然后从目标审计记录中恢复它们。

标签: sql postgresql parent-child audit


【解决方案1】:

我建议将 id 字段作为 主键 添加到审计表,因为您需要在回滚到 emp 表时引用它,而您还需要emp 引用对应版本的emp_addr。 所以审计表 DDL 应该如下所示:

/* Audit table for emp table */    
create table emp_audit (
    id bigserial,
    operation   character(1),
    updatetime timestamp,
    emp_id integer,
    version varchar(50),
    CONSTRAINT audit_emp_id PRIMARY KEY (id)
);

/* Audit table for emp_addr table */    
create table emp_addr_audit (
    id bigserial,
    operation   character(1),
    addr_id integer,
    emp_id integer,
    line1 varchar(30),
    CONSTRAINT fk_  audit_emp_id FOREIGN KEY emp_audit_id
       REFERENCES emp_audit (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;
);

接下来,您需要创建一个触发器来存储更改。请注意,您必须监控两个表中的更改并创建对相应存储记录的引用。

CREATE TRIGGER t_audit_emp_IUD
    AFTER INSERT OR UPDATE OR DELETE -- probably u want only update. Not sure
    ON emp
    FOR EACH ROW
    EXECUTE PROCEDURE emp_modified();

CREATE TRIGGER t_audit_emp_addr_IUD
    AFTER INSERT OR UPDATE OR DELETE 
    ON emp_addr
    FOR EACH ROW
    EXECUTE PROCEDURE emp_addr_modified();

最后定义函数。注意,函数应该在触发器之前存储在数据库中,因为触发器引用了函数。

回滚函数应以emp_audit.id为输入,根据审计表恢复状态。最好在回滚之前保存状态以防止可能的数据丢失。

如果这不能回答您的问题,请说明您真正需要帮助的部分。

【讨论】:

  • 如何在每次DML操作后以编程方式生成回滚sql语句?例如,如果我执行 INSERT INTO table (id, column1, column2) VALUES (1,'value1', 'value2')。那么可以在审计表中使用触发器自动生成undo sql语句为:DELETE FROM table WHERE id=1, column1='value1', column2='value2'
猜你喜欢
  • 1970-01-01
  • 2010-11-10
  • 2014-04-19
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
相关资源
最近更新 更多