2014-02-11 41 views
0

我想创建DB2 10.1.2当字段更新为一定值时,在该表中的行数与该值,看看是否计数(在Linux上运行LUW)触发它与另一个表中的计数相匹配,然后更新该表(例如,将任务状态汇总为工作状态)。表达它似乎很简单:DB2触发行锁定

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 

我试图用“与UR”的内部计数,但是当我创建触发器(“SQL20159W将被明确地忽略由于语句上下文,隔离子句被忽略。SQLSTATE = 01652“)。

我也尝试过使用BEFORE和INSTEAD OF,但遇到了问题。

这看起来好像是一件常见的事情。它通常如何处理?

+0

你有没有尝试'为每个陈述'? – AngocA

+0

我刚刚尝试过“对于每条语句”,它仍然僵持不下。 (我不确定如果更新更新多行并且我为“每个语句”而不是“针对每一行”执行操作,但它无法正常工作会发生什么情况。) – kjpires

+1

触发器无法在就像你说的那样,一个单独的UOW,因为触发体实际上被编译到引起触发器运行的'UPDATE'语句的计划中。你如何确定存在僵局? – mustaccio

回答

0

没有什么错与上面的触发器。我不知道,我的JOB_TABLE上的一个公开交易非常出色。我追查下来,做了回滚并完成了触发更新。

我会用count(0)代替count(*)作为建议的优化。

0

我不认为这是僵局。首先,DB2有一个死锁检测器,如果有两个连接在不同的资源上等待另一个资源的锁,那么DB2将会杀死其中的一个。我没有看到两个连接。

其次,你要更新另一个表(JOB_TABLE)的基础上,从表所在的触发器定义的值(COUNT)(TASK_TABLE)

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 = (  -- Total tasks before or after the update? 
    select count(*) 
    from TASK_TABLE 
    where TASK_TABLE.JOB_ID = N.JOB_ID 
    and TASK_TABLE.TASK_STATUS = 'Completed' 
    ) 

你有没有运行更新的外触发。它工作,不是吗?

我认为该交易修改是不是犯了行(更新task_table),当你发出选择在触发,等待对同一个表提交。事实上,事务并不知道被更新的行是否处于“已完成”状态,并且您有一个谓词来查找哪一个更新:JOB_TABLE.TOTAL_TASKS = x,但当前行可能是此集的一部分。

你打算更新哪一个?当前更新之前或当前更新之后的JOB_TABLE.TOTAL_TASKS?最后,我不确定为什么你有这个谓词。

BTW,不要使用count(*),但数(0)

+0

_when在触发器中发出select时 - - 不,它不。 – mustaccio

+0

另外,为什么_do不使用count(*)而是count(0)_? – mustaccio

+0

如果较低的优化级别,所有行都会被提取。 – AngocA