![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Кто понимает смысл ошибки "Таблица мутирует" ? [Оракл]
ANB © (2006-09-04 16:06:00)В общем то смысл самой ошибки понятен. И как ее избегать я знаю. А вот смыл ее генерации ? Неужели нельзя ораклу было без нее обойтись ? Почему я не могу селекать в триггере изменяющуюся таблицу ?
Sergey13 (2006-09-07 08:19:00) [1]> [75] Petr V. Abramov © (06.09.06 22:05)
Хм. А у меня 8.1.7 съел и не подавился.
Petr V. Abramov (2006-09-06 22:05:00) [2]> Не знаю как этот случай описан в базовых принципах, а Оракл без
> специального аттрибута в ключе тоже по рукам даст за такое.
и по умолчанию бьет. dererrable initially defrerred появилось только в 8-ке (и, что странно, в той же версии оно уже работало :)
Desdechado (2006-09-06 15:39:00) [3]> поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
Смысл этого запроса?
evvcom (2006-09-06 15:01:00) [4]> [72] Андрей Пазик (06.09.06 14:43)
Не знаю как этот случай описан в базовых принципах, а Оракл без специального аттрибута в ключе тоже по рукам даст за такое.
Андрей Пазик (2006-09-06 14:43:00) [5]IB/FB вообще нарушает базовые принципы SQL. Например. Есть у вас поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
И получаем детскими граблями! Потому что ограничения целостности проверяются тут на onrowChange, а не на onStatementFinish.
Petr V. Abramov (2006-09-06 14:05:00) [6]> ANB ©
если интересует, что там происходит "во время выполнения оператора", то
1. сделай триггер, который после изменения двух-трех записей повесит сессию (dbms_lock.sleep)
2. поизучай заголовки блоков (v$bh). вечерком могу поискать, как скинуть дамп блока в trace, сейчас просто убегаю.
Счастливых анатомических исследований :)))
Petr V. Abramov (2006-09-06 13:37:00) [7]> ПОСЛЕ оператора до коммита в таблице лежат новые данные, в RBS -
> старые. А вот где что лежит во время выполнения оператора - х.з. (знаний маловато).
в RBS лежат change vectors, изменения данных. А "во время измения" - в тех блоках, которые уже поменялись - новые данные, в которых еще не поменялись - старые :) Второй свежести данных не бывает :) То есть триггер в процеесе выполнения запроса относительно легко может получить старые данные (обычным consistent read, небесплатной процедурой), а новые - никак, потому что не все блоки еще обновились. Может, еще именно из-за consistent read не стали они связываться и сделали выдачу ошибки, тем более, что про винигрет уже много тут говорилось
ANB (2006-09-06 10:43:00) [8]
> evvcom © (06.09.06 10:35) [68]
> > [67] ANB © (06.09.06 10:31)
>
> Ну сделай табличку в пакете, в нее пиши изменения, а в автономной
> внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
>
Способов изгала то много. Для проверки на целостность дерева можно и стандартным обходом обойтись. Можно и вообще триггера не использовать.
И запретить использовать функции в DML.
evvcom (2006-09-06 10:35:00) [9]> [67] ANB © (06.09.06 10:31)
Ну сделай табличку в пакете, в нее пиши изменения, а в автономной внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
ANB (2006-09-06 10:31:00) [10]
> А зря, менеджеров, не устраивает, в 99% случаев.
Менеджерам важны данные в отчетах и гриде. Триггер их никак волновать не должен. А если по логике триггера мне все равно, в каком порядке изменяются данные, главное - чтобы давали читать уже измененные ?
evvcom (2006-09-06 10:27:00) [11]> [51] ANB © (05.09.06 17:44)
> А вот где что лежит во время выполнения оператора - х.з.
> (знаний маловато).
Я думаю, все там же. Только часть данных уже изменилась, а части еще предстоит. Кроме того выставляется внутренний флаг, что таблица уже изменяется, он-то и анализируется.
> [53] Desdechado © (05.09.06 19:15)
Поддерживаю.
> [56] ANB © (05.09.06 19:40)
> Но эта прагма автоматически включает чтение старых данных.
Она не включает. Просто автономной транзакции не доступны изменения, сделанные в первичной транзакции, а потому для нее
таблица неизменяется.
ANB (2006-09-06 09:21:00) [12]
> tesseract © (06.09.06 00:08) [62]
Во. Наконец то опытный спец пришел. Как чувствовал, что просто забили на баг, оформили исключением и сделали его фичей.
> (сабж - не глюк :),
- конечно, не глюк - глюк, это непойманный баг. А пойманный, заткнутый и документированный - это уже фича.
Продолжил эксперименты :
При наличии указанных выше таблиц и триггера (без прагмы) вот это работатет :
insert into table2 (ID, Parent_ID, Status)
values (10001, 1, 2)
insert into table2 (ID, Parent_ID, Status)
select 10002, 1, 3 from dual
insert into table2 (ID, Parent_ID, Status)
select rownum + 10010, rownum + 10010 - 1, decode(mod(rownum,2),0,4,5) from dual
connect by level <= 1000
А вот это - уже нет :
update table2 T2
set Status = t2_prev_status(t2.PARENT_ID)
where ID = 1
Кстати, в похожей ситуации на 8-ке инсерт нескольких записей не работал. Так что есть надежда, что таки потихоньку доведут до ума.
Таки не понятно - почему проходит массовый инсерт и не работает апдейт одной записи ? Триггер уровня строки до. Т.е. ораклу должно быть все понятно, никакой неоднозначности - какая мутация то ?
Petr V. Abramov (2006-09-06 01:44:00) [13]да ладно. много много в Oracle несовершенства, но у него есть такое же гадкое св-во, как у Windows - люди матерятся на глюки (сабж - не глюк :), но на другие продукты не переходят :)
Petr V. Abramov (2006-09-06 00:47:00) [14]> Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде
> только DB2 в состояниии справиться.
тот же FB пожеланиям некотрых трудящихся удовлетворяет. А в чем, на Ваш взгляд, технические проблемы-то? Давайте погадаем :)
> пока не подтвердишь данные можно считать старые.
только это небесплатно в плане ресурсов-то
tesseract (2006-09-06 00:08:00) [15]> Выгоднее делать новые фичи, чем Ларри успешно занимается.
да нет в моде упрощёнка, а на кой он MySQL к рукам прибрал?
> я не могу селекать в триггере изменяющуюся таблицу ?
Потому что происходит перестройка файловой структуры базы, что после этого выйдет, и какого цвета, никто не знает, это только dbf сильно предсказуем.
> Есно, при триггере уровня строки у меня селект завалится.
> Однако, если бы он не завалился, а возвращал мне смесь новых
> и старых строк - это бы меня вполне устроило.
А зря, менеджеров, не устраивает, в 99% случаев.
> Вот в IB она никогда не мутирует в режиме ReadCommitted.
ReadCommited для того и создан, максимум производительности при минимуме проблем. Фактически неявная неблокирующая транзакция, пока не подтвердишь данные можно считать старые.
> > что оракл просто по техническим причинам (из-за существующего
>
> > механизма транзакций) не готов работать с измененными/удаленными
>
> > записями в рамках одного оператора.
> на мое ИМХО технических проблем нет. Такой же Plssql-ный
> объект, как и ХП и пакет. А от plssql до мехпнизма управления
> транзакциями - 2 лаптя по карте. Работает-то он все равно
> в терминах блоков. Может, конечно просто поленились к релизу
> глючок какой исправить, и оказалось, что оно на надо, пусть
> так живет, приложения надежней будут
Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде только DB2 в состояниии справиться.
Petr V. Abramov (2006-09-05 23:40:00) [16]> С триггерами можно и руками подправить, если они корректно написаны. А
> вот с ХП можно нарваться и на поломку целостности, если кто-то из
> любителей поправить руками (ну я, например) вдруг не знает, что делать
> это с данной таблицей категорически запрещается.
это уже оргметодами решается. т.е любители подправить руками, которые не знают, не должны иметь возможность это сделать. А необходимость сия на моей памяти возникала только в случае, когда облажались с кодом и надо быстро привести базу в состояние, когда она в целости и непротиворечивости.
Проблема чуть глубже. вотя как кодер, когда говорю update, знаю, что поменяются записи в соответствии с set и where, и больше ничего. А так прежде чем писать update, теоретически должен предугадать фантазию триггерописателей на срок службы системы. Проблема ессно вылезает, когда таблица стоИт на грани полномочий двух разработчиков.
> что оракл просто по техническим причинам (из-за существующего
> механизма транзакций) не готов работать с измененными/удаленными
> записями в рамках одного оператора.
на мое ИМХО технических проблем нет. Такой же Plssql-ный объект, как и ХП и пакет. А от plssql до мехпнизма управления транзакциями - 2 лаптя по карте. Работает-то он все равно в терминах блоков. Может, конечно просто поленились к релизу глючок какой исправить, и оказалось, что оно на надо, пусть так живет, приложения надежней будут
ANB (2006-09-05 19:54:00) [17]Завели бы прагму типа "грязное чтение чего попало". кто хочет иметь такой результат и работать без генерации ошибки - самостоятельно включает. Хочешь по старому - без прагмы все по старому и работает.
Зажрался просто оракл.
ANB (2006-09-05 19:51:00) [18]CREATE OR REPLACE TRIGGER tr_table2
BEFORE UPDATE
ON table2
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_cnt INTEGER;
BEGIN
SELECT COUNT (*)
INTO v_cnt
FROM table2 t2
WHERE t2.parent_id = :NEW.parent_id;
END;
Вот этот триггер работает. Убираем прагму - валится.
> если надо будет откатить всю транзакцию, а не отдельные
> ее автономности?
Что откатывать после селекта ?
Кстати, таки доп. неудобство. Мало того, что я не могу производить проверки с учетом уже измененных записей (хотя всего одна то меняется, здесь то зачем мутация ?), так еще изменять данный в общем контексте транзакции не смогу.
> может, отключает чтение новых?
да какая разница. пусть будет "отключает".
Desdechado (2006-09-05 19:46:00) [19]> Функция перестала падать.
А теперь подумай, что будет, если надо будет откатить всю транзакцию, а не отдельные ее автономности?
И ты поймешь, что заблуждался относительно "решения пролемы". Ты ее только замаскировал и углубил.
Val (2006-09-05 19:44:00) [20]>включает чтение старых данных
может, отключает чтение новых?