Дмитрий Кравцов.
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;
/
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
Дмитрий.
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
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>> но ничего не поделаеш такой уж оракле
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...
Дмитрий Кравцов.
"Stax" <st...@lviv.eximb.com> wrote in message
news:a93qn4$od1$1...@host.talk.ru...
> Dmitrij Kravtsov <d...@antec.carrier.kiev.ua> пишет:
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...
>> 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)
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|
"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
Но я дописал триггер на 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
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
Это понятно.
В исходном примере это как раз учитывается
благодяря триггеру 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
Дмитрий Кравцов.
"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>...
> > Если можно, пример на две сессии? Бог с ней - с одной. Может он мне
> > подскажет что-то... Ибо пока ситуация малопонятна. И перестала почему-то
> > воспроизводиться...
> >
>
> На две сессии
>
"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 никак руки не доходят разобраться)
> Но всё это не объясняет моего примера... Кое-какие намёки содержатся в
> письме В.Бегуна, но что-то у меня сегодня нет сил его нормально осмысливать.
> Отложу на понедельник...
Я согласен, что у Вас другие причины
первое что приходит на ум
-с роллбеками
-конкуренция за блоки индекса
-за блоки данных
-сами даные могут быть экзотическими (напр таблица в кластере)
-активно работаете с ОПС (на кластерном железе, коллизии между узлами)
-триггер хитрый не простой (он вызывает какие то коллизии)
-
Ой распоясался,
Вы это и сами знаете
Осталось локализовать еще ОДНУ фичу оракля
..... 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
Дмитрий Кравцов.
"Vladimir Begun" <Vladimi...@oracle.com> wrote in message
news:3CB5E1CF...@oracle.com...
> Дмитрий
Дмитрий Кравцов.
"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, согласованность чтения
> > соблюдается.
> Тут как посмотреть, а если три сессии,
> на это закладываться нельзя
>
Dmitry Kravtsov wrote:
>
> Спасибо, Владимир, Ваша версия, видимо, достаточно близка к
> реальности... Придётся таки ставить проверку повторных срабатываний... Если
Я использовал пример, который был представлен + своё собственное
понимание этого процесса + проверку что это действительно так
как оно происходит...
Скажу честно, долго не копал, можно рыться и найти многое, но на это
нет времени.
> бы ещё поиметь некоторые гарантии... Например, что срабатывания по одной
> строке будут происходить подряд... Или быть уверенным, что для
> AFTER-триггеров подобная ситуация никогда не возникнет... :-))
;) Это зависит от того как это всё написать. Знаю одно triggers --
это не самое лучшее средство, но порою единственное :( для реализации
какой-то сложной логики...
С уважением, Д.Кравцов.
"Vladimir Begun" <Vladimi...@oracle.com> wrote in message
news:3CBB0571...@oracle.com...
Dmitry Kravtsov wrote:
> Я так и понял, Владимир... А нельзя ли пару слов о проверке "...что это
> действительно так..."? Я вполне готов поверить и "на слово", особенно
> учитывая, что это согласуется и с моими личными представлениями, но пример
> для "общего развития" не помешал бы... :-))
Я не думаю что это развививает, тем более в "общем плане",
так что ни о каком "общем развитии" речь идти не может. :)
Спасибо за готовность поверить на слово.
Я просто проверил что был rollback, но при этом не отработал
before statement trigger, а отработал row. Можно "рыть", но
как я уже сказал на это нет времени, да и интересно ли это?
>
> Спасибо за готовность поверить на слово.
>
Пожалуйста! :-))
> Я просто проверил что был rollback, но при этом не отработал
> before statement trigger, а отработал row. Можно "рыть", но
> как я уже сказал на это нет времени, да и интересно ли это?
>
Понял. Спасибо. Дальнейшее рытьё, пожалуй, особого смысла не имеет, ибо
всё равно всё в любой момент может измениться...
Ещё раз спасибо. Дмитрий.