【发布时间】:2014-02-11 21:57:01
【问题描述】:
我想在 DB2 10.1.2(在 Linux 上运行的 LUW)中创建一个触发器,当一个字段更新为某个值时,该表中的行数会使用该值进行计数,以查看它是否与计数匹配在另一个表中,然后更新该表(例如,将任务状态汇总为作业状态)。表达起来似乎很容易:
CREATE TRIGGER AUTHORED
AFTER UPDATE OF TASK_STATUS ON TASK_TABLE
REFERENCING NEW AS N FOR EACH ROW WHEN (TASK_STATUS = 'Completed')
update JOB_TABLE set JOB_STATUS='Completed'
where JOB_TABLE.ID = N.JOB_ID
and JOB_TABLE.TOTAL_TASKS = (select count(*) from TASK_TABLE
where TASK_TABLE.JOB_ID = N.JOB_ID
and TASK_TABLE.TASK_STATUS = 'Completed')
不幸的是,触发器的上下文和触发器的主体似乎不在同一个工作单元中,当您从触发的更新本身计算锁定的行时,就会发生死锁。这是我执行触发更新后“db2pd -wlocks”的输出:
Locks being waited on :
AppHandl [nod-index] TranHdl Lockname Type Mode Conv Sts CoorEDU AppName AuthID AppID
44248 [000-44248] 111 0200040E070000000000000052 RowLock ..X G 1385 perl KJPIRES 10.0.15.139.38727.140201011731
14937 [000-14937] 15 0200040E070000000000000052 RowLock .NS W 1238 perl KJPIRES 10.0.15.139.55287.140211231609
我尝试使用“with UR”作为内部计数,但在创建触发器时显式忽略了这一点(“SQL20159W 由于语句上下文而忽略了隔离子句。SQLSTATE=01652”)。
我也尝试使用 BEFORE 和 INSTEAD OF,但遇到了问题。
这似乎很常见。平时是怎么处理的?
【问题讨论】:
-
你试过'for each statement'吗?
-
我刚刚尝试了“for each statement”,但它仍然陷入僵局。 (我不确定如果更新更新多行并且我执行“for each statement”而不是“for each row”会发生什么,但它无论如何都不起作用。)
-
如您所说,触发器不可能在单独的 UOW 中执行,因为触发器主体实际上已编译到导致该触发器运行的
UPDATE语句的计划中。如何判断是否存在死锁? -
这是 DB2 for LUW、i 还是 z/OS?
-
我们在这里查看的行数是多少?在表格中,我的意思是,不是工作单元。
JOB_STATUS可以在常规读取时即时派生(例如,通过定义视图)吗?在最坏的情况下,您可以定义一个计划调用来检查所有作业。也许是一个首先提交任务状态的存储过程?指定SKIP LOCKED DATA在这里可以工作吗?