2014-02-11 7 views
0

Я хочу создать триггер в DB2 10.1.2 (LUW, работающий в Linux), который, когда поле обновляется до определенного значения, подсчитывает количество строк в этой таблице с этим значением, чтобы увидеть, он сопоставляет счет в другой таблице, а затем обновляется эта таблица (например, свертывание статуса задачи в статус задания). Выражая это казалось довольно легко:Блокировка триггерной строки 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 The условие изоляции игнорируется из-за контекста оператора. SQLSTATE = 01652 ").

Я также пытался использовать ПЕРЕД и ВМЕСТО, но возникли проблемы.

Кажется, что это было бы что-то общее. Как обычно это обрабатывается?

+0

Вы пробовали «для каждого заявления»? – AngocA

+0

Я просто попробовал «для каждого утверждения», и он все еще зашел в тупик. (Я не уверен, что произойдет, если обновление обновит несколько строк, и я делаю «для каждого оператора» вместо «для каждой строки», но это все равно не работает.) – kjpires

+1

Невозможно выполнить запуск триггера в отдельный UOW, как вы говорите, потому что тело триггера фактически скомпилировано в план оператора 'UPDATE', который вызывает запуск триггера. Как вы определяете, что существует тупик? – mustaccio

ответ

0

Там нет ничего плохого с выше спускового крючка. Неизвестно, что открытая транзакция на моем JOB_TABLE была невыполнима. Я отследил его, выполнил откат и завершил обновление.

Я буду использовать count(0) вместо count(*) в качестве предлагаемой оптимизации.

0

Я не думаю, что он зашел в тупик. Во-первых, DB2 имеет детектор Deadlock, и если есть два соединения с блокировками на разных ресурсах, ожидающих другого, 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' 
    ) 

Вы запустить обновление вне вызывать. Это работает, не так ли?

Я думаю, что транзакция модифицирует строку, которая не была зафиксирована (update task_table), и когда вы выдаете выбор в триггере, он ожидает фиксации в той же таблице. Фактически, транзакция не знает, находится ли обновление строки в состоянии «завершено», и у вас есть предикат для поиска одного обновления: и JOB_TABLE.TOTAL_TASKS = x, но текущая строка может быть частью этого набора.

Какой номер вы собираетесь обновить? JOB_TABLE.TOTAL_TASKS перед текущим обновлением или после текущего обновления? Наконец, я не уверен, почему у вас есть предикат.

BTW, не используйте COUNT (*), но подсчитывать (0)

+0

_ когда вы выберете выбор в триггере_ - нет, это не так. – mustaccio

+0

Кроме того, почему _do не использовать count (*), но count (0) _? – mustaccio

+0

Если нижний уровень оптимизации, все строки будут извлечены. – AngocA

Смежные вопросы