【问题标题】:DB2 trigger timing outDB2 触发器超时
【发布时间】:2013-10-07 14:52:05
【问题描述】:

我有以下触发器,可确保只有一条记录具有字段 DEFAULTCARD=1

create trigger TRG_U_XSTRDCRD
     after update on XSTOREDCARD referencing new as N old as O
     for each row mode db2sql
     begin atomic
        if N.DEFAULTCARD = 1 then
            update XSTOREDCARD
                set DEFAULTCARD = 0
                where USERS_ID = N.USERS_ID and ID <> N.ID;
        end if;
     end@

我还想确保只有一条记录的 EBACTIVE 字段值为 1,所以我尝试了这个。

create trigger TRG_U_XSTRDCRD
     after update on XSTOREDCARD referencing new as N old as O
     for each row mode db2sql
     begin atomic
        if N.DEFAULTCARD = 1 then
            update XSTOREDCARD
                set DEFAULTCARD = 0
                where USERS_ID = N.USERS_ID and ID <> N.ID;
        end if;
        if N.EBACTIVE = 1 then
            update XSTOREDCARD
                set EBACTIVE = 0
                where USERS_ID = N.USERS_ID and ID <> N.ID;
        end if;
     end@

但它不起作用,导致更新几分钟后超时:

Caused by: com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -101, SQLSTATE: 54001, SQLERRMC: null
at com.ibm.db2.jcc.b.zc.e(zc.java:1606)
at com.ibm.db2.jcc.b.zc.a(zc.java:1206)
at com.ibm.db2.jcc.a.db.h(db.java:149)
at com.ibm.db2.jcc.a.db.a(db.java:43)
at com.ibm.db2.jcc.a.r.a(r.java:30)
at com.ibm.db2.jcc.a.sb.g(sb.java:152)
at com.ibm.db2.jcc.b.zc.n(zc.java:1186)
at com.ibm.db2.jcc.b.ad.db(ad.java:1761)
at com.ibm.db2.jcc.b.ad.d(ad.java:2203)
at com.ibm.db2.jcc.b.ad.V(ad.java:521)
at com.ibm.db2.jcc.b.ad.executeUpdate(ad.java:504)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2595)
... 19 more

有什么错误或如何做的建议吗?

干杯! NFV

【问题讨论】:

  • 请显示准确的错误代码和完整的信息。
  • SQLCODE -101 不是超时;这意味着您正在达到内存限制或其他一些资源限制。由于您没有提到您的 DB2 版本和平台,因此我无法提供更多详细信息。与您的 DBA 交谈。
  • 以下页面可能会给您一些提示。 dbforums.com/db2/…

标签: sql triggers db2


【解决方案1】:

阅读this nice post 后,我可能意识到您对许多人做了一些更新。您定义了一个更新后触发器,它更新同一个表。您实际上更新了该用户的所有行。所以假设每个用户有 10 行,其中一行更改了 DEFAULTCARD 标志。这意味着您更新 9 行,无论它们是否需要更新。这听起来没什么大不了,但是,如果您有 5,000,000 条记录,那么即使您只需要更新一条记录(即旧的 DEFAULTCARD 记录),您也会更新 4,999,999 条记录。

        update XSTOREDCARD
            set DEFAULTCARD = 0
            where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;

此声明应仅影响 1 条记录或不影响记录。因此,您不必运行 4,999,999 次更新和触发调用,而是只有一次更新。

EBACTIVE 也是如此。更好的是,如果 EBACTIVE 和 DEFAULTCARD 对于不同的记录是 1,它会变得非常混乱,因为对 EBACTIVE 的更新将触发对 DEFAULTCARD 的更新,这将再次触发对 EBACTIVE 的更新。所以如果我没记错的话,你是在一个无限循环中。

 begin atomic
    if N.DEFAULTCARD = 1 then
        update XSTOREDCARD
            set DEFAULTCARD = 0
            where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;
    end if;
    if N.EBACTIVE = 1 then
        update XSTOREDCARD
            set EBACTIVE = 0
            where USERS_ID = N.USERS_ID and EBACTIVE = 1 and ID <> N.ID;
    end if;
 end@

这应该表现得更好。

编辑:第二次尝试

如果值实际发生变化,我们应该只更新数据集。

 begin atomic
    if N.DEFAULTCARD = 1 and O.DEFAULTCARD != 1 then
        update XSTOREDCARD
            set DEFAULTCARD = 0
            where USERS_ID = N.USERS_ID and DEFAULTCARD = 1 and ID <> N.ID;
    end if;
    if N.EBACTIVE = 1 and O.EBACTIVE !=1 then
        update XSTOREDCARD
            set EBACTIVE = 0
            where USERS_ID = N.USERS_ID and EBACTIVE = 1 and ID <> N.ID;
    end if;
 end@

【讨论】:

  • 感谢您的建议,它看起来不错,但我仍然遇到同样的错误...
  • 你的桌子有多大?
  • 然后试试我的编辑,你的触发器很可能有一个无限循环
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多