【问题标题】:Fine-tuning when a constraint trigger should fire约束触发器应该触发时的微调
【发布时间】:2013-02-14 15:03:33
【问题描述】:

在我们的应用程序中(使用 PostgreSQL 引擎盖(目前是 9.1,移动到 9.2),我们在处理某些请求时再次插入(或更新)和更新特定行。 所以它看起来像:

BEGIN
INSERT(pg), UPDATE(java)
XOR
UPDATE(pg), UPDATE(java)
COMMIT

(进程在 postgres 和 java 之间划分,postgres 获取并插入/更新它可以的内容(其他列 NULL),将控制权返回给 java 应用程序,并更新其余列)。

遗憾的是,我们在应用程序中发现了一个设计缺陷,该缺陷可能会在特定行中提交后导致数据不一致(在极其罕见的情况下,多年来只发生过一次)。 更具体地说,如果 columnA = 'someConstant',则在 COMMIT 之后 columnB 不能为 NULL(但它可以在第一次插入/更新之后和第二次更新之前!)。

在重新设计应用程序时,我们必须提供一些短期解决方法来防止这种情况发生。

我目前正在使用所谓的约束触发器。它们可以在 COMMIT 之前被 DEFERRED,它们可以进行任意检查和 RAISE EXCEPTION(这很好,因为事务将正常回滚)。 问题是我有 (INSERT,UPDATE) 或 (UPDATE,UPDATE) 语句。正如我所说,提到的不一致列在中间有效,但在事务结束时有效。所以这就是诀窍:触发器应该只为第二条语句触发。我正在挖掘文档,发现 FOR EACH ROW 和 FOR EACH STATEMENT。这无济于事,因为它们都会触发两次,但我必须只触发第二个 UPDATE 语句。

有什么想法吗?

【问题讨论】:

    标签: postgresql stored-procedures triggers


    【解决方案1】:

    更新时的延迟约束触发器可以解决您的问题,只是它不应该检查NEW.column is NULL,因为NEW.column 将是更新时的值,而不是提交时的值,即使触发器在提交时触发。

    您可以做的是像这样的行级延迟约束触发器(假设table 有一个名为pk 的主键)来测试事务结束时的当前值:

    DECLARE
     v column_type; -- to fetch the value at the end of the transaction
    BEGIN
     SELECT column INTO v FROM table WHERE pk=NEW.pk;
     IF FOUND AND v IS NULL THEN
       RAISE ERROR 'Null not allowed in column';
     END IF
     RETURN new;
    END;
    

    如果表没有主键,那么应该找到一些不同的方法来获取最新的列值(不是ctid,因为它在多次更新的情况下不起作用)。

    【讨论】:

      【解决方案2】:

      谢谢丹尼尔。我目前正在测试这个:

      CREATE OR REPLACE FUNCTION noFalseData() RETURNS trigger LANGUAGE plpgsql AS $$
      DECLARE
       v text;
      BEGIN
       SELECT column INTO v FROM active.table WHERE othercolumn = 'SOME_CONSTANT' AND pk=NEW.pk;
       IF FOUND AND v IS NULL THEN
         RAISE EXCEPTION 'Null not allowed in column';
       END IF;
       RETURN NULL;
      END;
      $$;
      
      CREATE CONSTRAINT TRIGGER watchActCampUpd AFTER UPDATE
      ON active.table DEFERRABLE INITIALLY DEFERRED
      FOR EACH ROW
      EXECUTE PROCEDURE noFalseData();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多