Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Triggers

141 views
Skip to first unread message

Dmitrij Kravtsov

unread,
Apr 11, 2002, 2:39:00 AM4/11/02
to
Коллеги! Возникла странная с моей точки зрения ситуация. Возможно, на
меня просто нашло временное затмение, но объяснерия я ей не вижу.
Происходит следующее: при удалении строк из таблицы строчный триггер на
гнекоторых удаляемых строкахз срабатывал два раза. Не каждый раз. Примерно
один раз из 200-300-400 удалений. Обнаружено это было на рабочей базе. После
этого мне удалось воспроизвести этот эффект на тестовой таблице примерно с
такой же периодичностью. Сейчас этот эффект пропал (никаких действий с БД не
предпринималось). Возможно, кто-то из вас сталкивался с подобным явлением
или может предположить причину его возникновения. Сервер W2000 8.1.7.2.1.
Никаких сообщений об ошибках и тому подобных подорзрительных явлений не
происходит....

Дмитрий Кравцов.

PS Текст тестовой программки прилагаю.
Цикл, приведённый в конце, Выдавал сообщение о "лишнем" срабатывании
триггера на удаление на 200-300 итерации (в разных запусках по разному)

PPS Буду чрезвычайно признателен за комментарии, ибо кое-какая логика
рабочих программ зависит от количеств срабатываний триггеров...

CREATE TABLE tst1 (
id INTEGER,
val INTEGER
);
INSERT INTO tst1 VALUES (1,10);
INSERT INTO tst1 VALUES (1,20);
INSERT INTO tst1 VALUES (1,30);
INSERT INTO tst1 VALUES (1,40);
INSERT INTO tst1 VALUES (1,50);
INSERT INTO tst1 VALUES (1,60);
INSERT INTO tst1 VALUES (1,70);
INSERT INTO tst1 VALUES (1,80);
INSERT INTO tst1 VALUES (1,90);
INSERT INTO tst1 VALUES (1,100);
select count(*) from tst1;

CREATE TABLE tst2 (
id INTEGER,
val INTEGER
);

CREATE OR REPLACE PACKAGE tst2_pk
IS
var_cnt INTEGER;
END tst2_pk;
/

DROP TRIGGER tst2_BIUD_tr;
CREATE OR REPLACE TRIGGER tst2_BIUD_tr
BEFORE INSERT OR UPDATE OR DELETE
ON tst2
BEGIN
tst2_pk.var_cnt := 0;
END;
/

DROP TRIGGER tst2_BIUDR_tr;
CREATE OR REPLACE TRIGGER tst2_BIUDR_tr
BEFORE INSERT OR UPDATE OR DELETE
ON tst2
FOR EACH ROW
BEGIN
tst2_pk.var_cnt := tst2_pk.var_cnt + 1;
END;
/

BEGIN
FOR c IN 1..200000 LOOP
INSERT INTO tst2 SELECT * FROM tst1;
IF tst2_pk.var_cnt <> 10 THEN
Raise_Application_Error(
-20001,
'Вместо 10 раз триггер на вставку сработал : ' ||
TO_CHAR(tst2_pk.var_cnt) || ' раз. На ' || c ||'й итерации'
);
END IF;
UPDATE tst2 SET val = val + 1 WHERE id = 1;
IF tst2_pk.var_cnt <> 10 THEN
Raise_Application_Error(
-20001,
'Вместо 10 раз триггер на обновление сработал : ' ||
TO_CHAR(tst2_pk.var_cnt) || ' раз. На ' || c ||'й итерации'
);
END IF;
DELETE FROM tst2 WHERE id = 1;
IF tst2_pk.var_cnt <> 10 THEN
Raise_Application_Error(
-20001,
'Вместо 10 раз триггер на удаление сработал : ' ||
TO_CHAR(tst2_pk.var_cnt) || ' раз. На ' || c ||'й итерации'
);
END IF;
COMMIT;
END LOOP;
END;
/

Stax

unread,
Apr 11, 2002, 4:50:12 AM4/11/02
to
Добрий день, Дмитрий

Dmitrij Kravtsov <d...@antec.carrier.kiev.ua> пишет:
DK> Коллеги! Возникла странная с моей точки
DK> зрения ситуация. Возможно, на
DK> меня просто нашло временное затмение, но
DK> объяснерия я ей не вижу.
DK> Происходит следующее: при удалении строк из
DK> таблицы строчный триггер на
DK> гнекоторых удаляемых строкахз срабатывал два
DK> раза.

Если с таблицей работает (удаляет изменяет)
еще кто-то (Вы не один) то так и будет (больше срабатываний)
это отражено в документации
(обычно программисты это учитывают (я нет, надо писать лишний код))
Такое возникает при блокировках
На двух сесиях это можно повторить со стопроцентной гарантией
особенно интересно с упдейтом

Если с таблицей работаете Вы один,
мне тяжело ответить
возможно какие-то коллизии
возникают с роллбеками или блоком
(не хватает слотов транзакций или как там их)
тут я неуверен
Может ДБА чего добавят

PS
Вообще очень плохо что в командах
DELETE/UPDATE нет (не было) кляузы ORDER BY
но ничего не поделаеш такой уж оракле

DK> Не каждый раз. Примерно
DK> один раз из 200-300-400 удалений. Обнаружено это
DK> было на рабочей базе. После
DK> этого мне удалось воспроизвести этот эффект на
DK> тестовой таблице примерно с
DK> такой же периодичностью. Сейчас этот эффект
DK> пропал (никаких действий с БД не
DK> предпринималось). Возможно, кто-то из вас
DK> сталкивался с подобным явлением
DK> или может предположить причину его возникновения.
DK> Сервер W2000 8.1.7.2.1.
DK> Никаких сообщений об ошибках и тому подобных
DK> подорзрительных явлений не
DK> происходит....

DK> Дмитрий Кравцов.


--
С уважением, Stax.
... неприятности приходят патчами ...

Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru

Dmitrij Kravtsov

unread,
Apr 11, 2002, 6:05:26 AM4/11/02
to

Таблица сугубо тестовая, поэтому работаю я с ней один... Но даже если и
не один, я что-то не припомню никаких оговорок по поводу неоднократного
срабатывания триггеров уровня записи на одну и ту же запись ( а ситуация
именно такова)... Окажите любезность: ткните носом в конкретный пункт
документации!!!! Стыдно, конечно, но не помню... :-((

Дмитрий.

Valery Yourinsky

unread,
Apr 11, 2002, 6:46:50 AM4/11/02
to Dmitrij Kravtsov
Dmitrij Kravtsov wrote:
>
> Таблица сугубо тестовая, поэтому работаю я с ней один... Но даже если и
> не один, я что-то не припомню никаких оговорок по поводу неоднократного
> срабатывания триггеров уровня записи на одну и ту же запись ( а ситуация
> именно такова)... Окажите любезность: ткните носом в конкретный пункт
> документации!!!! Стыдно, конечно, но не помню... :-((

Oracle8i. Application Developer▓s Guide - Fundamentals
Release 2 (8.1.6). December 1999. Part No. A76939-01
12. Using Triggers
Creating Triggers
Restrictions on Creating Triggers

References to Package Variables
===============================
If an UPDATE or DELETE statement detects a conflict
with a concurrent UPDATE, then Oracle performs a transparent ROLLBACK to
SAVEPOINT and restarts the update. This can occur many times before the
statement completes successfully. Each time the statement is restarted,
the BEFORE
statement trigger is fired again. The rollback to savepoint does not
undo changes to
any package variables referenced in the trigger. The package should
include a
counter variable to detect this situation.


Ключевые слова:
The rollback to savepoint does not undo changes to
any package variables referenced in the trigger.

Валерий Юринский
--
Oracle8 Certified DBA
Moscow, Russia

Stax

unread,
Apr 11, 2002, 7:05:50 AM4/11/02
to
Dmitrij Kravtsov <d...@antec.carrier.kiev.ua> пишет:

DK> Таблица сугубо тестовая, поэтому работаю я с
DK> ней один... Но даже если и
DK> не один, я что-то не припомню никаких оговорок по
DK> поводу неоднократного
DK> срабатывания триггеров уровня записи на одну и ту
DK> же запись ( а ситуация
DK> именно такова)... Окажите любезность: ткните
DK> носом в конкретный пункт
DK> документации!!!!

Мне нужно время, у меня плохо с английским
Точно не припомню там или фраза (предложение) или даже абзац
Возможно при описании обхода мутации
Ведь если это не учитывать то можно
два раза заполнить PL/SQL таблицу для триггера уровня оператора

На "две сессии" примерчик могу сразу состряпать,
с гарантией "лишнего" повтора триггера
На одну сессию не пробовал, тут нужен ДБА,
и может это еще и зависит от параметров базы


Повторюсь
C делитом проще, более интересно ведет себя update
это обсуждалось, возможно в fido-шной

DK> Стыдно, конечно, но не помню...
А чего стыдно,
я кстати Ваш ученик (двоешник)
Вы мне лекции по 8 ораклу читали,
многому именно Вы меня научили
Если я не обознался

DK> :-((

DK> Дмитрий.

DK>>
DK>> Если с таблицей работает (удаляет изменяет)
DK>> еще кто-то (Вы не один) то так и будет (больше
DK> срабатываний)
DK>> это отражено в документации
DK>> (обычно программисты это учитывают (я нет, надо
DK> писать лишний код))
DK>> Такое возникает при блокировках
DK>> На двух сесиях это можно повторить со
DK> стопроцентной гарантией
DK>> особенно интересно с упдейтом
DK>>
DK>> Если с таблицей работаете Вы один,
DK>> мне тяжело ответить
DK>> возможно какие-то коллизии
DK>> возникают с роллбеками или блоком
DK>> (не хватает слотов транзакций или как там их)
DK>> тут я неуверен
DK>> Может ДБА чего добавят
DK>>
DK>> PS
DK>> Вообще очень плохо что в командах
DK>> DELETE/UPDATE нет (не было) кляузы ORDER BY
DK>> но ничего не поделаеш такой уж оракле

Dmitry Kravtsov

unread,
Apr 11, 2002, 11:23:04 AM4/11/02
to

Спасибо за ссылку, но это не тот случай.
Ключевые слова:

Each time the statement is restarted, the BEFORE statement trigger is fired
again.


А именно в BEFORE STATEMENT триггере происходит очистка пакетных переменных.
Т.е. такого повторения приведённый пример (да и рабочая программа) не
замечает. Дело в чём-то другом. Да и нет у меня никакого CONCARENTа... Но
всё равно - спасибо...

Дмитрий Кравцов.

"Valery Yourinsky" <v...@bill.mts.ru> wrote in message
news:3CB5699A...@bill.mts.ru...

Dmitry Kravtsov

unread,
Apr 11, 2002, 11:27:25 AM4/11/02
to

Возможно и не обознались... Курсы я действительно читал многим людям.
Рад, что они принесли пользу...
Если можно, пример на две сессии? Бог с ней - с одной. Может он мне
подскажет что-то... Ибо пока ситуация малопонятна. И перестала почему-то
воспроизводиться...

Дмитрий Кравцов.

"Stax" <st...@lviv.eximb.com> wrote in message
news:a93qn4$od1$1...@host.talk.ru...
> Dmitrij Kravtsov <d...@antec.carrier.kiev.ua> пишет:

Dmitry Kravtsov

unread,
Apr 11, 2002, 11:47:37 AM4/11/02
to

В качестве иллюстрации того, что это мне не приснилось, копирую экран
"плюса"... И так повтогрялось (на разном номере итерации) не один десяток
раз...

SQL> BEGIN
2 FOR c IN 1..1000 LOOP
3 INSERT INTO tst2 SELECT * FROM tst1;
4 IF tst2_pk.var_cnt <> 10 THEN
5 Raise_Application_Error(
6 -20001,
7 'Вместо 10 раз триггер на вставку сработал : ' ||


TO_CHAR(tst2_pk.var_cnt) || ' раз. На ' || c ||'й итерации'

8 );
9 END IF;
10 DELETE FROM tst2 WHERE id = 1;
11 IF tst2_pk.var_cnt <> 10 THEN
12 Raise_Application_Error(
13 -20001,
14 'Вместо 10 раз триггер на удаление сработал : ' ||


TO_CHAR(tst2_pk.var_cnt) || ' раз. На ' || c ||'й итерации'

15 );
16 END IF;
17 END LOOP;
18 END;
19 /
BEGIN
*
ERROR at line 1:
ORA-20001: Вместо 10 раз триггер на удаление сработал : 11 раз. На 296й
итерации
ORA-06512: at line 12

Elapsed: 00:00:55.80

Дмитрий Кравцов.

"Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message
news:a94a6h$28v8$2...@gateway.naverex.net...

Vitaliy Lyanchevskiy

unread,
Apr 11, 2002, 2:11:47 PM4/11/02
to
Hello, Dmitry!
11.04.2002 15:23, Dmitry Kravtsov -> Valery Yourinsky:

>> Oracle8i. Application Developer's Guide - Fundamentals
>>

>> References to Package Variables
>> ===============================
>> If an UPDATE or DELETE statement detects a conflict
>> with a concurrent UPDATE, then Oracle performs a transparent ROLLBACK to
>> SAVEPOINT and restarts the update. This can occur many times before the
>> statement completes successfully. Each time the statement is restarted,
>> the BEFORE statement trigger is fired again.
>> The rollback to savepoint does not undo changes to
>> any package variables referenced in the trigger. The package should
>> include a counter variable to detect this situation.
>>
>> Ключевые слова:
>> The rollback to savepoint does not undo changes to
>> any package variables referenced in the trigger.

DK> Спасибо за ссылку, но это не тот случай.
DK> Ключевые слова:

DK> Each time the statement is restarted, the BEFORE statement trigger is
fired
DK> again.

DK> А именно в BEFORE STATEMENT триггере происходит очистка пакетных
переменных.
DK> Т.е. такого повторения приведённый пример (да и рабочая программа) не
DK> замечает. Дело в чём-то другом. Да и нет у меня никакого CONCARENTа...
Но
DK> всё равно - спасибо...

Мне тоже кажется, что не в этом дело.

У меня этот глюк(?) стопроцентно воспроизводится на:
- Personal Oracle 7.3.3.6 на Win2000Prof
- Oracle Server 7.3.3.6.0 на SCO OpenServer 5

Не воспроизвёлся (400000 итераций) на
- Oracle8i Enterprise Edition Release 8.1.6.0.0 на Win2000Prof

Срабатывает на 1000..100000-ой итерации на Upd или Del.
Чаще срабатывает на Del.
Срабатывает, почему-то, только на 1-ой или 8-ой строке.
Никакой конкуренции за тестовые таблицы нет.


Ниже привожу пример протокола срабатываний триггеров
на сбойной итерации. Для большей наглядности
созданы ещё и AFTER-триггера, не изменяющие счётчика.

===== begin dump =======
i) Level/StatementType/Counter: (OldValues) -> (NewValues)
===
1) BeforeStatement/Insert/0: (,) -> (,)
2) BeforeRow/Insert/1: (,) -> (1,10)
3) AfterRow/Insert/1: (,) -> (1,10)
4) BeforeRow/Insert/2: (,) -> (1,20)
5) AfterRow/Insert/2: (,) -> (1,20)
6) BeforeRow/Insert/3: (,) -> (1,30)
7) AfterRow/Insert/3: (,) -> (1,30)
8) BeforeRow/Insert/4: (,) -> (1,40)
9) AfterRow/Insert/4: (,) -> (1,40)
10) BeforeRow/Insert/5: (,) -> (1,50)
11) AfterRow/Insert/5: (,) -> (1,50)
12) BeforeRow/Insert/6: (,) -> (1,60)
13) AfterRow/Insert/6: (,) -> (1,60)
14) BeforeRow/Insert/7: (,) -> (1,70)
15) AfterRow/Insert/7: (,) -> (1,70)
16) BeforeRow/Insert/8: (,) -> (1,80)
17) AfterRow/Insert/8: (,) -> (1,80)
18) BeforeRow/Insert/9: (,) -> (1,90)
19) AfterRow/Insert/9: (,) -> (1,90)
20) BeforeRow/Insert/10: (,) -> (1,100)
21) AfterRow/Insert/10: (,) -> (1,100)
22) AfterStmnt/Insert/10: (,) -> (,)
23) BeforeStatement/Update/0: (,) -> (,)
24) BeforeRow/Update/1: (1,20) -> (1,21)
25) AfterRow/Update/1: (1,20) -> (1,21)
26) BeforeRow/Update/2: (1,30) -> (1,31)
27) AfterRow/Update/2: (1,30) -> (1,31)
28) BeforeRow/Update/3: (1,40) -> (1,41)
29) AfterRow/Update/3: (1,40) -> (1,41)
30) BeforeRow/Update/4: (1,50) -> (1,51)
31) AfterRow/Update/4: (1,50) -> (1,51)
32) BeforeRow/Update/5: (1,60) -> (1,61)
33) AfterRow/Update/5: (1,60) -> (1,61)
34) BeforeRow/Update/6: (1,70) -> (1,71)
35) AfterRow/Update/6: (1,70) -> (1,71)
36) BeforeRow/Update/7: (1,80) -> (1,81) <===== !!!!!
37) BeforeRow/Update/8: (1,80) -> (1,81)
38) AfterRow/Update/8: (1,80) -> (1,81)
39) BeforeRow/Update/9: (1,90) -> (1,91)
40) AfterRow/Update/9: (1,90) -> (1,91)
41) BeforeRow/Update/10: (1,100) -> (1,101)
42) AfterRow/Update/10: (1,100) -> (1,101)
43) BeforeRow/Update/11: (1,10) -> (1,11)
44) AfterRow/Update/11: (1,10) -> (1,11)
45) AfterStmnt/Update/11: (,) -> (,)
===== end dump =======


BEGIN
*
ERROR at line 1:

ORA-20001: Вместо 10 раз триггер на обновление сработал : 11 раз. На 21855й
итерации
ORA-06512: at line 51

real: 118911

Как видно при "сбое" не срабатывает AfterRowTrigger
и происходит повторный вход в BeforeRowTrigger.
Может в доке ошибка и в "References to Package Variables"
речь должна была бы идти о BEFORE _ROW_ триггере ?

Хотя я всё равно не понимаю отчего это вообще происходит.

--
WBR, Vitaliy Lyanchevskiy (E-Mail: el...@ecard.ru)

Vladimir Begun

unread,
Apr 11, 2002, 3:19:19 PM4/11/02
to
Дмитрий

Dmitrij Kravtsov wrote:
>
> Коллеги! Возникла странная с моей точки зрения ситуация. Возможно, на
> меня просто нашло временное затмение, но объяснерия я ей не вижу.
> Происходит следующее: при удалении строк из таблицы строчный триггер на
> гнекоторых удаляемых строкахз срабатывал два раза. Не каждый раз. Примерно
> один раз из 200-300-400 удалений. Обнаружено это было на рабочей базе. После

ИМХО, Rollback segment увеличивался -- временный затык, не было куда
сложить данные, триггер отрабатывал 2-й раз после появления места в
rollback segmente.

BEFORE Triggers Fired Multiple Times

If an UPDATE or DELETE statement detects a conflict with a concurrent
UPDATE, then Oracle performs a transparent ROLLBACK to SAVEPOINT and
restarts the update. This can occur many times before the statement
completes successfully. Each time the statement is restarted, the
BEFORE statement trigger is fired again. The rollback to savepoint
does not undo changes to any package variables referenced in the
trigger.
The package should include a counter variable to detect this situation.

Я думаю здесь не совсем корректная информация, вернее она говорит
немного о другом, и в принципе неполно.

BEFORE row trigger отработал 2-жды, и это правильно потому что при
расширении rollback segmentа нет смысла повторять целый statement
заново, согласись это было бы полным бредом.

> этого мне удалось воспроизвести этот эффект на тестовой таблице примерно с
> такой же периодичностью. Сейчас этот эффект пропал (никаких действий с БД не
> предпринималось). Возможно, кто-то из вас сталкивался с подобным явлением

Это понятно почему не повторяется. Можно сделать маленький rollback
segment (скажем INITIAL 16K, NEXT 16K OPTIMAL 64K MAXEXTENTS 5) и
заставить его расти... Да, наверное COMMIT из сценария нужно убрать,
так быстрее можно будет увидеть проблему.

> или может предположить причину его возникновения. Сервер W2000 8.1.7.2.1.
> Никаких сообщений об ошибках и тому подобных подорзрительных явлений не
> происходит....
>
> Дмитрий Кравцов.
>
> PS Текст тестовой программки прилагаю.
> Цикл, приведённый в конце, Выдавал сообщение о "лишнем" срабатывании
> триггера на удаление на 200-300 итерации (в разных запусках по разному)
>
> PPS Буду чрезвычайно признателен за комментарии, ибо кое-какая логика
> рабочих программ зависит от количеств срабатываний триггеров...

Мне кажется не стоит на это "затачивать" логику... Если уж она заточена
ловите ошибки, не выполняйте PL/SQL кода дважды, т.е. заведите счётчик
выполнения операции.

Может в будущем что-то и поменяеется, но видимо пока это сделано
так как сделано.

Удачи!
--
Vladimir Begun | The statements and opinions expressed
http://vbegun.net/ | here are my own and do not necessarily
http://vbegun.net/wap/ | represent those of Oracle Corporation.
m...@vbegun.net |
ICQ#19259480/30% reachability|

Stanislav Shydlovskyy

unread,
Apr 12, 2002, 2:54:34 AM4/12/02
to
Добрий день, Дмитрий

"Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message news:<a94a6h$28v8$2...@gateway.naverex.net>...

> Если можно, пример на две сессии? Бог с ней - с одной. Может он мне
> подскажет что-то... Ибо пока ситуация малопонятна. И перестала почему-то
> воспроизводиться...
>

На две сессии
В триггере просто задержка,
через функцию потому что не имею прав
напрямую на dbms_lock

Примеры (привел три) не на все варианты,
так как мне кажется найболее яркие
Может получилось несколько сумбурно
или при копировании из плюса не туда вставил,
так уж звиняите

Все это несколько странно,
но как говорит Владимир, имеем что имеем

такой он оракле

SQL> set sqlp "ses1 > "
ses1 > desc t
Name Null? Type
------------------------------- -------- ----
C NUMBER
V NUMBER
N NUMBER

create or replace trigger t$upd_stax before update
on t
for each row
declare
n number;
begin
n:=grand2.stax_lock(10);
dbms_output.put_line('Updated'
||to_char(sysdate,'hh24:mi:ss')
||' old c='||to_char(:old.c)
||' old v='||to_char(:old.v)
||' old n='||to_char(:old.n)
||' new c='||to_char(:new.c)
||' new v='||to_char(:new.v)
||' new n='||to_char(:new.n)
);
end;

create or replace trigger t$del_stax before delete
on t
for each row
declare
n number;
begin
n:=grand2.stax_lock(10);
dbms_output.put_line('Deleted'
||to_char(sysdate,'hh24:mi:ss')
||' old c='||to_char(:old.c)
||' old v='||to_char(:old.v)
||' old n='||to_char(:old.n)
);
end;

ПРИМЕР 1
ses1 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4
1 1 1
1 1 5
на начало транзакции нужно удалить 5 записей
ses1 > delete t where c=1;

Сразу во второй сессии
ses2 > update t set c=2 where n=4;
Updated09:06:44 old c=1 old v=1 old n=4 new c=2 new v=1 new n=4
1 row updated.
ses2 > commit;
Commit complete.
ses2 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
2 1 4
1 1 1
1 1 5
ses2 >
Теперь смотрим в первой
Deleted09:06:40 old c=1 old v=1 old n=2
Вот сдесь во вторй был update
Deleted09:06:50 old c=1 old v=1 old n=3
Deleted09:07:00 old c=1 old v=1 old n=4
ждет коммит
Deleted09:08:30 old c=1 old v=1 old n=2
Deleted09:08:40 old c=1 old v=1 old n=3
Deleted09:08:50 old c=1 old v=1 old n=1
Deleted09:09:00 old c=1 old v=1 old n=5

4 rows deleted.

ВНИМАНИЕ УДАЛИЛОСЬ 4 ЗАПИСИ
ses1 > select * from t;
C V N
--------- --------- ---------

2 1 4

ses1 > rollback;
Rollback complete.

ЕЩЕ ПРИМЕР С UPDATE
ПРИМЕР 2
ses2 > update t set c=1 where n=4;
Updated09:15:49 old c=2 old v=1 old n=4 new c=1 new v=1 new n=4
1 row updated.
ses2 > commit;
Commit complete.
ses2 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4
1 1 1
1 1 5

В первой
ses1 > delete t where c=1;

После этого в 2
ses2 > update t set c=n,v=1000 where n in (1,5);
Updated09:21:01 old c=1 old v=1 old n=1 new c=1 new v=1000 new n=1
Updated09:21:11 old c=1 old v=1 old n=5 new c=5 new v=1000 new n=5
2 rows updated.
ses2 > commit;
Commit complete.
ses2 > select * from t;

C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4
1 1000 1
5 1000 5

В это время в первой

Deleted09:20:58 old c=1 old v=1 old n=2
Вот сдесь Updated09:21:01
Deleted09:21:08 old c=1 old v=1 old n=3
Deleted09:21:19 old c=1 old v=1 old n=4
Deleted09:21:29 old c=1 old v=1 old n=1
ждет коммита
Deleted09:23:38 old c=1 old v=1 old n=2
Deleted09:23:49 old c=1 old v=1 old n=3
Deleted09:23:59 old c=1 old v=1 old n=4
Deleted09:24:09 old c=1 old v=1000 old n=1
4 rows deleted.

ses1 > select * from t;
C V N
--------- --------- ---------
5 1000 5
ses1 >

Обратите внимание УДАЛИЛОСЬ ИЗМЕНЕННАЯ закомиченная ЗАПИСЬ n=1
в тоже время осталась с n=5
хотя на начало транзакции удаления она попадала под условие с=1

ПРИМЕР 3
ses1 > rollback
Rollback complete.
ses1 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4
1 1000 1
5 1000 5
ses1 > delete t where c=1;
Во второй
ses2 > update t set c=1,v=222222 where n in (1,5);
Updated09:35:36 old c=1 old v=1000 old n=1 new c=1 new v=222222 new n=1
Updated09:35:47 old c=5 old v=1000 old n=5 new c=1 new v=222222 new n=5
2 rows updated.
ses2 > commit;
Commit complete.
ses2 >
ses2 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4
1 222222 1
1 222222 5
ses2 >
А в это время
ses1 > delete t where c=1;
Deleted09:35:33 old c=1 old v=1 old n=2
---Updated09:35:36
Deleted09:35:43 old c=1 old v=1 old n=3
Deleted09:35:54 old c=1 old v=1 old n=4
Deleted09:36:04 old c=1 old v=1000 old n=1
ждем коммита
Deleted09:38:38 old c=1 old v=1 old n=2
Deleted09:38:49 old c=1 old v=1 old n=3
Deleted09:38:59 old c=1 old v=1 old n=4
Deleted09:39:09 old c=1 old v=222222 old n=1
Deleted09:39:19 old c=1 old v=222222 old n=5
5 rows deleted.

ses1 > select * from t;
no rows selected

Внимание УДАЛИЛАСЬ запись с номером т=5,
но на начоло транзакции удаления она не входила
в условие WHERE

--
С уважением,
Stax

Yaroslav Ribak

unread,
Apr 12, 2002, 3:46:25 AM4/12/02
to

"Stanislav Shydlovskyy" <st...@lviv.eximb.com> wrote in message
news:c422712f.0204...@posting.google.com...

> Добрий день, Дмитрий
>
> "Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message
news:<a94a6h$28v8$2...@gateway.naverex.net>...
> > Если можно, пример на две сессии? Бог с ней - с одной. Может он мне
> > подскажет что-то... Ибо пока ситуация малопонятна. И перестала почему-то
> > воспроизводиться...
> >
>
> На две сессии
> В триггере просто задержка,
> через функцию потому что не имею прав
> напрямую на dbms_lock
>
> ..... skipped

Но я дописал триггер на before statement и
он сработал как и написано в документации.

> ses2 >
> Теперь смотрим в первой

Здесь сработал.

> Deleted09:06:40 old c=1 old v=1 old n=2
> Вот сдесь во вторй был update
> Deleted09:06:50 old c=1 old v=1 old n=3
> Deleted09:07:00 old c=1 old v=1 old n=4
> ждет коммит

И здесь сработал.

> Deleted09:08:30 old c=1 old v=1 old n=2
> Deleted09:08:40 old c=1 old v=1 old n=3
> Deleted09:08:50 old c=1 old v=1 old n=1
> Deleted09:09:00 old c=1 old v=1 old n=5
>
> 4 rows deleted.
>

> ..... skipped


Stax

unread,
Apr 12, 2002, 8:43:35 AM4/12/02
to
Добрий день, Ярослав

Yaroslav Ribak <yaro...@softline.kiev.ua> пишет:

YR> "Stanislav Shydlovskyy" <st...@lviv.eximb.com>
YR> wrote in message
YR>> Добрий день, Дмитрий
YR>>
YR>> На две сессии
YR>> В триггере просто задержка,
YR>> через функцию потому что не имею прав
YR>> напрямую на dbms_lock
YR>>
YR>> ..... skipped

YR> Но я дописал триггер на before statement и
YR> он сработал как и написано в документации.

Я не говорил что триггер не отработает
просто это надо учитвать,
лишний напряг в кодировании

Примеры
1 По пайпу данные уже ушли
2 Отработали автономные транзакции
3 Поверте, я видел код когда pl/sql таблица очищалась в after triggere
4 Иногда тяжело (лень) отслеживать повторные срабатывания
(в общем случае их больше двух)
5 А при каскадных удалениях еще интереснее
6 Следующие проходы наново перечитывают первоначальный набор
(как бы нарушая целостность по чтению на начало выполнения,
решение на удаление принято на основании совершенно других данных,
и это тоже надо "дополнительно" кодировать)
и т.д.

Еще раз, я не говорю что это не работает,
просто надо ДОПОЛНИТЕЛЬНО учитывать при проектировании
хотя лично мне,
эти повторные срабатывания не очень нравятся

У Дмитрия Кравцова возможно
и другие причины повторных срабатываниий.
тем более в одной сессии
Смотрите ответ Владимира
Правда насчет "нет смысла повторять целый statement


заново, согласись это было бы полным бредом"

В моих примерах и есть этот ...

И если целый оператор не отрабатывает,
то у меня нет уверенности что отработает
триггер на before statement, и повторное срабатывания
еще тяжелее отследить

Просто мне более тяжело повторить,
пример на одной сессии

YR>> ses2 >
YR>> Теперь смотрим в первой

YR> Здесь сработал.

YR>> Deleted09:06:40 old c=1 old v=1 old n=2
YR>> Вот сдесь во вторй был update
YR>> Deleted09:06:50 old c=1 old v=1 old n=3
YR>> Deleted09:07:00 old c=1 old v=1 old n=4
YR>> ждет коммит

YR> И здесь сработал.

YR>> Deleted09:08:30 old c=1 old v=1 old n=2
YR>> Deleted09:08:40 old c=1 old v=1 old n=3
YR>> Deleted09:08:50 old c=1 old v=1 old n=1
YR>> Deleted09:09:00 old c=1 old v=1 old n=5
YR>>
YR>> 4 rows deleted.
YR>>
YR>> ..... skipped

YR> news:c422712f.0204...@posting.google.co
YR> m...

--
С уважением, Stax.


... неприятности приходят патчами ...

Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru

Yaroslav Ribak

unread,
Apr 12, 2002, 11:06:58 AM4/12/02
to

"Stax" <st...@lviv.eximb.com> wrote in message
news:a96kqd$gks$1...@host.talk.ru...

> Добрий день, Ярослав
>
> Yaroslav Ribak <yaro...@softline.kiev.ua> пишет:
>
> YR> "Stanislav Shydlovskyy" <st...@lviv.eximb.com>
> YR> wrote in message
> YR>> Добрий день, Дмитрий
> YR>>
> YR>> На две сессии
> YR>> В триггере просто задержка,
> YR>> через функцию потому что не имею прав
> YR>> напрямую на dbms_lock
> YR>>
> YR>> ..... skipped
>
> YR> Но я дописал триггер на before statement и
> YR> он сработал как и написано в документации.
>
> Я не говорил что триггер не отработает
> просто это надо учитвать,
> лишний напряг в кодировании

Это понятно.
В исходном примере это как раз учитывается
благодяря триггеру before statement.
Но, судя по письму Владимира и по исходному вопросу,
триггер before statement может и не срабатывать,
что уже совсем неприятно.

> Примеры
> 1 По пайпу данные уже ушли
> 2 Отработали автономные транзакции
> 3 Поверте, я видел код когда pl/sql таблица очищалась в after triggere
> 4 Иногда тяжело (лень) отслеживать повторные срабатывания
> (в общем случае их больше двух)
> 5 А при каскадных удалениях еще интереснее
> 6 Следующие проходы наново перечитывают первоначальный набор
> (как бы нарушая целостность по чтению на начало выполнения,
> решение на удаление принято на основании совершенно других данных,
> и это тоже надо "дополнительно" кодировать)

Ну, для read comitted это вроде как и нормально.

В случае isolation_level=serializable первая сессия
после отработки второй отваливается с ошибкой
ORA-08177: can't serialize access for this transaction.

> и т.д.
>
> Еще раз, я не говорю что это не работает,
> просто надо ДОПОЛНИТЕЛЬНО учитывать при проектировании
> хотя лично мне,
> эти повторные срабатывания не очень нравятся

Мне тоже очень не нравится это.

>
> У Дмитрия Кравцова возможно
> и другие причины повторных срабатываниий.
> тем более в одной сессии
> Смотрите ответ Владимира

Ну так я потому и написал, что прочитал.

> Правда насчет "нет смысла повторять целый statement
> заново, согласись это было бы полным бредом"
>
> В моих примерах и есть этот ...

Так вот и я как раз об этом.
Получается, при обновлении большой таблицы,
с которой к тому же еще и работают интенсивно другие
пользователи , процес обновления будет много раз
перестартовывать аж пока не залочит все данные.
Владимир прав, это явно нелогично, но почти факт :(

Если таки триггер before statement может не перестартовать,
то вся логика внутри строчных триггеров должна быть только
транзакционная.

> И если целый оператор не отрабатывает,

Тут я потерял мысль.
Не понял, что ты хотел сказать.

> то у меня нет уверенности что отработает
> триггер на before statement, и повторное срабатывания
> еще тяжелее отследить
>
> Просто мне более тяжело повторить,
> пример на одной сессии
>

> ... skipped


Dmitry Kravtsov

unread,
Apr 12, 2002, 12:39:21 PM4/12/02
to

Спасибо. Примеры посмотрел. Весьма интересно. В принципе, если отвлечься
от некоторых утверждений документации (!!! :-) ), ситуация понятна и
объяснима, хотя и не совсем хороша... И естественно, противоречит
утверждению "Read consistency, as supported by Oracle, does the following: *
Guarantees that the set of data seen by a statement is consistent with
respect to a single point in time and does not change during statement
execution (statement-level read consistency)..." Если, конечно, не
интерпретировать термин "statement-level ", как SELECT-level... Кстати, если
заменить UPDATE во второй сесси на INSERT, согласованность чтения
соблюдается.
В общем, не даром Оракл настоятельно рекомендует перед выполнением
изменения данных выполнять SELECT ... FOR UPDATE...
Но всё это не объясняет моего примера... Кое-какие намёки содержатся в
письме В.Бегуна, но что-то у меня сегодня нет сил его нормально осмысливать.
Отложу на понедельник...

Дмитрий Кравцов.

"Stanislav Shydlovskyy" <st...@lviv.eximb.com> wrote in message
news:c422712f.0204...@posting.google.com...


> Добрий день, Дмитрий
>
> "Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message
news:<a94a6h$28v8$2...@gateway.naverex.net>...
> > Если можно, пример на две сессии? Бог с ней - с одной. Может он мне
> > подскажет что-то... Ибо пока ситуация малопонятна. И перестала почему-то
> > воспроизводиться...
> >
>
> На две сессии
>

Stanislav Shydlovskyy

unread,
Apr 15, 2002, 4:11:41 AM4/15/02
to
Добрий день, Дмитрий

"Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message news:<a972na$ld1$1...@gateway.naverex.net>...


> Спасибо. Примеры посмотрел. Весьма интересно. В принципе, если отвлечься
> от некоторых утверждений документации (!!! :-) ), ситуация понятна и
> объяснима, хотя и не совсем хороша... И естественно, противоречит
> утверждению "Read consistency, as supported by Oracle, does the following: *
> Guarantees that the set of data seen by a statement is consistent with
> respect to a single point in time and does not change during statement
> execution (statement-level read consistency)..." Если, конечно, не
> интерпретировать термин "statement-level ", как SELECT-level...

Вот я часто отмечаю, что с переводом
предложений с нюансами часто бывают несуразницы

> Кстати, если
> заменить UPDATE во второй сесси на INSERT, согласованность чтения
> соблюдается.

Тут как посмотреть, а если три сессии,
на это закладываться нельзя
Например

ses1 > select * from t;
C V N
--------- --------- ---------
1 1 2
1 1 3
1 1 4

1 222222 1
1 222222 5

ses1 > delete t where c=1;
В третьей сессии
ses3 > insert into t values (1,666666,6);
1 row created.

Во второй
ses2 > update t set v=333333 where n=5;
Updated09:33:19 old c=1 old v=222222 old n=5 new c=1 new v=333333 new n=5
1 row updated.
ses3 > commit;
Commit complete.


ses2 > commit;
Commit complete.
ses2 >

А в это время в первой
Deleted09:33:13 old c=1 old v=1 old n=2

insert+Updated09:33:19

Deleted09:33:23 old c=1 old v=1 old n=3

Deleted09:33:33 old c=1 old v=1 old n=4
Deleted09:33:43 old c=1 old v=222222 old n=1
Deleted09:33:54 old c=1 old v=222222 old n=5
Ждем
Deleted09:36:55 old c=1 old v=1 old n=2
Deleted09:37:05 old c=1 old v=1 old n=3


Deleted09:37:16 old c=1 old v=1 old n=4

Deleted09:37:26 old c=1 old v=222222 old n=1
Deleted09:37:36 old c=1 old v=333333 old n=5
Deleted09:37:46 old c=1 old v=666666 old n=6

6 rows deleted.

Удалил все записи,
в том числе измененную и вновь добавленную

Видно в 8и сильно доделали ISOLATION LEVEL SERIALIZABLE;
Во времена 7 версии у меня там не все получалось
с целостность по чтению
и я забросил этот режим,
возмжно зря

> В общем, не даром Оракл настоятельно рекомендует перед выполнением
> изменения данных выполнять SELECT ... FOR UPDATE...

"Настоятельно", тут тоже не так все гладко
(нельзя делать коммит, а это не всегда удобно)
(да и с автономной транзакцией и FOR UPDATE никак руки не доходят разобраться)

> Но всё это не объясняет моего примера... Кое-какие намёки содержатся в
> письме В.Бегуна, но что-то у меня сегодня нет сил его нормально осмысливать.
> Отложу на понедельник...

Я согласен, что у Вас другие причины
первое что приходит на ум
-с роллбеками
-конкуренция за блоки индекса
-за блоки данных
-сами даные могут быть экзотическими (напр таблица в кластере)
-активно работаете с ОПС (на кластерном железе, коллизии между узлами)
-триггер хитрый не простой (он вызывает какие то коллизии)
-
Ой распоясался,
Вы это и сами знаете
Осталось локализовать еще ОДНУ фичу оракля

Stanislav Shydlovskyy

unread,
Apr 15, 2002, 4:46:41 AM4/15/02
to
Добрий день, Ярослав

..... skipped


> >
> > 6 Следующие проходы наново перечитывают первоначальный набор
> > (как бы нарушая целостность по чтению на начало выполнения,
> > решение на удаление принято на основании совершенно других данных,
> > и это тоже надо "дополнительно" кодировать)
>
> Ну, для read comitted это вроде как и нормально.
>
> В случае isolation_level=serializable первая сессия
> после отработки второй отваливается с ошибкой
> ORA-08177: can't serialize access for this transaction.
>

Видать в 8и сильно дописали этот режим,
раньше я его рассматривал как только
для прогона "транзакционных тестов"
В семерке что-то не все у меня там получалось,
особенно с согласованностью по чтению
и я забросил, посчитав что этот режим
ну уж СОВСЕМ не основной в субд оракле

В свободное от работы время надо будет присмотрется,
Возможно пересмотреть и базовые понятия

Но всеравно переводить промышленную базу
точно не будем (без указания сверху)

..... skipped

> Ну так я потому и написал, что прочитал.
>
> > Правда насчет "нет смысла повторять целый statement
> > заново, согласись это было бы полным бредом"
> >
> > В моих примерах и есть этот ...
>
> Так вот и я как раз об этом.
> Получается, при обновлении большой таблицы,
> с которой к тому же еще и работают интенсивно другие
> пользователи , процес обновления будет много раз
> перестартовывать аж пока не залочит все данные.
> Владимир прав, это явно нелогично, но почти факт :(
>
> Если таки триггер before statement может не перестартовать,
> то вся логика внутри строчных триггеров должна быть только
> транзакционная.
>
> > И если целый оператор не отрабатывает,
>
> Тут я потерял мысль.

Вы выше написали об этом
Надо было взять в кавычки _оператор_не_отрабатывает
это я из цытаты Владимира выкусил
надо было:
И если "целый statement" не отрабатывает,

> Не понял, что ты хотел сказать.

Теперь надеюсь, будет более понятно

> > то у меня нет уверенности что отработает
> > триггер на before statement, и повторное срабатывания
> > еще тяжелее отследить

Даже не знаю, ровиды запоминать что-ли

> >
> > Просто мне более тяжело повторить,
> > пример на одной сессии
> >

Я писал тут нужен дба (нужны нехилые права)

> > ... skipped

PS
И еще при таких (удалениях, вставках) мозможны (и они есть)
взаимоблокировки (dead lock)
это тоже очень неприятно
так он (оракл) хоть с нюансами но повторяет оператор
а при dead lock одна из сессий (оператор в сессии)
слетает причем для меня это головная боль
Правда в трасу честно пишет (писал)

В идеале нужно изменять и удалять по одной записи

--
С уважением,
Stax

Dmitry Kravtsov

unread,
Apr 15, 2002, 6:05:27 AM4/15/02
to

Спасибо, Владимир, Ваша версия, видимо, достаточно близка к
реальности... Придётся таки ставить проверку повторных срабатываний... Если
бы ещё поиметь некоторые гарантии... Например, что срабатывания по одной
строке будут происходить подряд... Или быть уверенным, что для
AFTER-триггеров подобная ситуация никогда не возникнет... :-))

Дмитрий Кравцов.

"Vladimir Begun" <Vladimi...@oracle.com> wrote in message
news:3CB5E1CF...@oracle.com...
> Дмитрий

Dmitry Kravtsov

unread,
Apr 15, 2002, 6:21:10 AM4/15/02
to

Конечно, нельзя... Это я уже так - в порядке "флейма"... :-)))
Понятно, что эту ситуацию (при "угрозе" её возникновения) нужно
отслеживать внешними по отношению к исполнительным механизмам Оракла
средствами... И постараться не забыть об этом эффекте при разработке
алгоритмов приложения...

Дмитрий Кравцов.

"Stanislav Shydlovskyy" <st...@lviv.eximb.com> wrote in message

news:c422712f.02041...@posting.google.com...


> Добрий день, Дмитрий
>
> "Dmitry Kravtsov" <d...@antec.carrier.kiev.ua> wrote in message
news:<a972na$ld1$1...@gateway.naverex.net>...


>


> > Кстати, если
> > заменить UPDATE во второй сесси на INSERT, согласованность чтения
> > соблюдается.
> Тут как посмотреть, а если три сессии,
> на это закладываться нельзя
>

Vladimir Begun

unread,
Apr 15, 2002, 12:52:48 PM4/15/02
to
Дмитрий

Dmitry Kravtsov wrote:
>
> Спасибо, Владимир, Ваша версия, видимо, достаточно близка к
> реальности... Придётся таки ставить проверку повторных срабатываний... Если

Я использовал пример, который был представлен + своё собственное
понимание этого процесса + проверку что это действительно так
как оно происходит...

Скажу честно, долго не копал, можно рыться и найти многое, но на это
нет времени.

> бы ещё поиметь некоторые гарантии... Например, что срабатывания по одной
> строке будут происходить подряд... Или быть уверенным, что для
> AFTER-триггеров подобная ситуация никогда не возникнет... :-))

;) Это зависит от того как это всё написать. Знаю одно triggers --
это не самое лучшее средство, но порою единственное :( для реализации
какой-то сложной логики...

Dmitry Kravtsov

unread,
Apr 16, 2002, 3:24:04 AM4/16/02
to

Я так и понял, Владимир... А нельзя ли пару слов о проверке "...что это
действительно так..."? Я вполне готов поверить и "на слово", особенно
учитывая, что это согласуется и с моими личными представлениями, но пример
для "общего развития" не помешал бы... :-))

С уважением, Д.Кравцов.

"Vladimir Begun" <Vladimi...@oracle.com> wrote in message

news:3CBB0571...@oracle.com...

Vladimir Begun

unread,
Apr 17, 2002, 4:14:51 PM4/17/02
to
Дмитрий

Dmitry Kravtsov wrote:
> Я так и понял, Владимир... А нельзя ли пару слов о проверке "...что это
> действительно так..."? Я вполне готов поверить и "на слово", особенно
> учитывая, что это согласуется и с моими личными представлениями, но пример
> для "общего развития" не помешал бы... :-))

Я не думаю что это развививает, тем более в "общем плане",
так что ни о каком "общем развитии" речь идти не может. :)

Спасибо за готовность поверить на слово.

Я просто проверил что был rollback, но при этом не отработал
before statement trigger, а отработал row. Можно "рыть", но
как я уже сказал на это нет времени, да и интересно ли это?

Dmitry Kravtsov

unread,
Apr 18, 2002, 3:14:06 AM4/18/02
to

"Vladimir Begun" <Vladimi...@oracle.com> wrote in message
news:3CBDD7D2...@oracle.com...

>
> Спасибо за готовность поверить на слово.
>

Пожалуйста! :-))

> Я просто проверил что был rollback, но при этом не отработал
> before statement trigger, а отработал row. Можно "рыть", но
> как я уже сказал на это нет времени, да и интересно ли это?
>

Понял. Спасибо. Дальнейшее рытьё, пожалуй, особого смысла не имеет, ибо
всё равно всё в любой момент может измениться...

Ещё раз спасибо. Дмитрий.


0 new messages