Форум: "Базы";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
ВнизКто понимает смысл ошибки "Таблица мутирует" ? Найти похожие ветки
← →
ANB © (2006-09-04 16:06) [0]В общем то смысл самой ошибки понятен. И как ее избегать я знаю. А вот смыл ее генерации ? Неужели нельзя ораклу было без нее обойтись ? Почему я не могу селекать в триггере изменяющуюся таблицу ?
← →
Desdechado © (2006-09-04 16:16) [1]Потому как, логически рассуждая, не известно, какая часть данных уже изменилась, а какая нет. Ведь, например, UPDATE xxx SET yyy=1 затрагивает все записи, но порядок их обновления командой не задается. Поэтому строить логику на неизвестном поведении сервера некорректно (оно может меняться между версиями).
И, также, неизвестно, какие именно данные ты пытаешься селектить в триггере - старые до обновления, новые после обновления или вперемежку.
← →
Val © (2006-09-04 16:29) [2]>ANB © (04.09.06 16:06)
Вас очень задевает данный вопрос, до категоричности, как я посмотрю...Но дело в том, что скл сервера реализованы по-разному и стоит, по-моему, принимать их фичи/баги/реализацию как данность...иначе это принимает глупый вид холивара.
offtop: а понимание того, почему нет второго столбца (в прошлой ветке) уже пришло?
← →
ANB © (2006-09-04 16:35) [3]
> новые после обновления
Меня бы это вполне устроило. Так и знание того, что часть данных уже изменилось. Вот пусть новые и возвращает. Например : вставляю в триггере проверку, что апдейт не приводит к зацикливанию дерева. Есно, при триггере уровня строки у меня селект завалится. Однако, если бы он не завалился, а возвращал мне смесь новых и старых строк - это бы меня вполне устроило. Причем не важно, в каком порядке бы изменялись записи - сервер все равно про это знает.
← →
ANB © (2006-09-04 16:36) [4]
> offtop: а понимание того, почему нет второго столбца (в
> прошлой ветке) уже пришло?
Это в которой ?
← →
ANB © (2006-09-04 16:51) [5]
> > offtop: а понимание того, почему нет второго столбца (в
>
> > прошлой ветке) уже пришло?
>
> Это в которой ?
Какой столбец ?
← →
Desdechado © (2006-09-04 16:53) [6]Ты не забывай, что возможны варианты с автономными транзакциями в триггерах, которые не откатываются при откате главной. Поэтому винегрет будет еще тот при селектах.
Да и
>> новые после обновления
> Меня бы это вполне устроило.
противоречит
> возвращал мне смесь новых и старых строк - это бы меня
> вполне устроило.
Ну, и на закуску.
Это твоя ЧАСТНАЯ задача, для которой удобнее свои подходы. В других задачах - другое видение. На всех не напасешься.
← →
Val © (2006-09-04 16:58) [7]В этой.
http://delphimaster.net/view/3-1157033863/&web=1
Столбец N.
← →
ANB © (2006-09-04 17:10) [8]
> Val © (04.09.06 16:58) [7]
И чего в этой ветке непонятного ? Фактически оракл выполняет DDL в отдельной транзакции как один оператор. Что я и хотел выяснить.
> >> новые после обновления
я имел в виду те, которые уже изменились. Ну как то же тот же FB возвращает данные без ошибок (или нет ?) ?
← →
Виталий Панасенко (2006-09-04 19:06) [9]
>
> > Val © (04.09.06 16:58) [7]
>
> И чего в этой ветке непонятного ? Фактически оракл выполняет
> DDL в отдельной транзакции как один оператор. Что я и хотел
> выяснить.
>
>
> > >> новые после обновления
>
> я имел в виду те, которые уже изменились. Ну как то же тот
> же FB возвращает данные без ошибок (или нет ?) ?
Подтвержденный другой транзакцией и если читающая транзакция - ReadCommited. Можно сделать "снимок", тогда пофигу все остальные тарнзакции - данные будут только те, которые были на момент старта читающей транзакции.Я о ЖарПтице
← →
ANB © (2006-09-04 19:17) [10]
> Я о ЖарПтице
Во. Тогда вопрос - можно ли в FB в триггере уровня строки селекать из изменяемой таблицы (ну, например, тупая проверка на дубли, хотя это лучше уникальным индексом сделать) ?
← →
atruhin © (2006-09-04 20:36) [11]> Тогда вопрос - можно ли в FB в триггере уровня строки селекать
> из изменяемой таблицы
Можно. FB чистый версионник, и он спокойно читает данные не учитывая текущие изменения.
← →
kaif © (2006-09-05 01:17) [12]А кто-то утверждал, что ORACLE - версионник...
В версионнике как может таблица мутировать?
Вот в IB она никогда не мутирует в режиме ReadCommitted.
Только ногами не бейте...
← →
ANB © (2006-09-05 09:57) [13]
> А кто-то утверждал, что ORACLE - версионник...
оракл - не версионник. Он иммитация версионника. А вот FB/IB действительно версионники.
Кстати, я понимаю принцип работы транзакций оракла в нормальном режиме. А что происходит в случае сбоя ? Неужто при старте оракл лезет первым делом в RBS и начинает откат слетевших транзакций ?
← →
Sergey13 © (2006-09-05 10:20) [14]> [13] ANB © (05.09.06 09:57)
Только не в RBS а в Redo. Легко убедиться посмотрев alert файл.
← →
ANB © (2006-09-05 12:39) [15]
> Только не в RBS а в Redo
Хрен редьки не слаще. Все равно, по идее, не сильно шустро. Таки так и происходит ?
← →
Sergey13 © (2006-09-05 13:01) [16]> [15] ANB © (05.09.06 12:39)
Может подняться после сбоя можно было бы и быстрее, но зато существует практически 100% гарантия (при грамотном администрировании разумеется) поднимаемости и сохранности данных в БД на "за мгновение до сбоя". Тот же механизм работает при порче носителя и восстановления из бекапа.
← →
Petr V. Abramov © (2006-09-05 13:07) [17]> Неужто при старте оракл лезет первым делом в RBS и начинает откат слетевших транзакций ?
лезет в redo, накатывает его на rbs, и "естественным образом" откатывает. Если под "случаем сбоя" понимать падение пусть по уважительным причинам. А что в этом такого "неужто"?
> Вот в IB она никогда не мутирует в режиме ReadCommitted.
точно так же мутирует, только ошибку не выдает.
> Вот пусть новые и возвращает. Например : вставляю в триггере проверку, что апдейт не приводит к зацикливанию дерева.
в гораздо более большом количестве задач этот винигрет будет источником трудноуловимых ошибок.
← →
ANB © (2006-09-05 14:03) [18]
> винигрет будет источником трудноуловимых ошибок.
каких ? Ну давайте представим, что оракл ошибку убрал и вместо этого начал возвращать винегрет. В какой ситуации может что то сломаться ?
← →
kaif © (2006-09-05 14:19) [19]2 Petr V. Abramov © (05.09.06 13:07) [17]
точно так же мутирует, только ошибку не выдает.
Я не сталкивался с подобным явлением.
← →
ANB © (2006-09-05 14:20) [20]
> kaif © (05.09.06 14:19) [19]
Кстати, а что FB возращает в такой ситуации ?
← →
Petr V. Abramov © (2006-09-05 14:47) [21]> Я не сталкивался с подобным явлением.
ну так FB ошибку не выдает, а выдает муть.
> каких ? Ну давайте представим, что оракл ошибку убрал и вместо этого
> начал возвращать винегрет. В какой ситуации может что то сломаться ?
да сломаться-то ничего не сломается. но бред будет.
например в триггере на table1 пишем
select count(*) from t1 where field1=1
потом говорим update t1 set fied1 = 1
что должен возвращать select count(*) на каждой стороке?
зайдем по-другому: а покажите пример задачи, которая решается красиво, если ошибка "убрана", инекрасиво, если ошибка "не убрана".
← →
evvcom © (2006-09-05 14:52) [22]> [13] ANB © (05.09.06 09:57)
> оракл - не версионник. Он иммитация версионника.
Ну вот, опять двадцать пять! Что ты понимаешь под термином "версионник"?
> [12] kaif © (05.09.06 01:17)
> В версионнике как может таблица мутировать?
А какая разница в версионнике это или нет? Вот так и мутирует. При апдейте нескольких записей, после апдейта первой таблица УЖЕ изменяется и в триггере уровня строки на селекте и получим вышеуказанную ошибку. Зато в триггере после апдейта уровня оператора таблица уже НЕ изменяется и подобной ошибки не будет.
> [18] ANB © (05.09.06 14:03)
Так тебе ж селект выдал бы СЛУЧАЙНЫЕ данные, разве ж это не винегрет? Если тебе все равно, что выдаст селект, сделай его из dual хотя бы тогда :)
← →
ANB © (2006-09-05 15:02) [23]
> выдал бы СЛУЧАЙНЫЕ данные
Ни фига они были бы не случайные. Они были бы непредсказуемыми, что не есть одно и тоже. Однако, для проверки, например, зацикливания дерева мне бы любые подошли. Кстати, ошибка при некоторых условиях валится даже если меняется всего одна строка (но не всегда). Например, если вставляется одна строка и производится проверка на дубль ID, то триггер отрабатывает. Если же в эту таблицу делаешь вставку хотя бы 2-х строк одним инсертом, то триггер падает.
← →
ANB © (2006-09-05 15:03) [24]
> Если же в эту таблицу делаешь вставку хотя бы 2-х строк
> одним инсертом, то триггер падает.
И при этом триггер уровня оператора мне уже не поможет, если мне нужно было в триггере присвоить значение ID.
← →
Sergey13 © (2006-09-05 15:13) [25]> [23] ANB © (05.09.06 15:02)
Что-то мне помнится Оракл сам отлавливает зацикливания дерева. Плюс непонятно зачем искать дубль ID? Руками что-ли вводишь?
← →
ANB © (2006-09-05 15:23) [26]
> Что-то мне помнится Оракл сам отлавливает зацикливания дерева.
Только при селекте. А мне надо не допустить этой ситуации при изменении данных. Этим же селектом с генерацией ошибки очень удобно ловить.
> Плюс непонятно зачем искать дубль ID
Значится в первой моей оракловой конторе была сделана иммитация автоинкрементальных полей. В триггере дергался сиквенс. А т.к. исторически сиквенсы были зацикленными, то в триггере же производилась проверка на дубль и если она срабатывала, то сиквенс дергался пока не надоест. Одна запись завсегда нормально вставлялась, 2 - вылетала ошибка мутации. И тут обход через пакет и еще 2 триггера никак не поможет, приходилось вставлять записи по одной в курсоре.
← →
evvcom © (2006-09-05 15:29) [27]> [23] ANB © (05.09.06 15:02)
> Ни фига они были бы не случайные. Они были бы непредсказуемыми
Согласен.
> Например, если вставляется одна строка и производится проверка
> на дубль ID, то триггер отрабатывает
Заметь, триггер before on each row
> Если же в эту таблицу делаешь вставку хотя бы 2-х строк
> одним инсертом, то триггер падает.
Естественно, на второй записи.
Если тебе пофиг, что вернет селект, то напиши этот селект в отдельной ХП с прагмой автономной транзакции и вызывай ее из своего триггера. Тогда будет все ок.
← →
Sergey13 © (2006-09-05 15:31) [28]> [26] ANB © (05.09.06 15:23)
> Только при селекте.
Разве? Помнится (хоть и давно это было) я вроде получал ошибку и при апдейте.
> А т.к. исторически сиквенсы были зацикленными
И что? Не хватило размерности?
← →
ANB © (2006-09-05 15:39) [29]
> в отдельной ХП с прагмой автономной транзакции
А если проблема в уже добавленных/измененных записях ?
> Разве? Помнится (хоть и давно это было) я вроде получал
> ошибку и при апдейте.
Ну откуда ж оракл знает, что ты дерево в таблице нарисовал. Он только при connect by об этом и узнает.
> И что? Не хватило размерности?
За историю фирмы грили, раза три триггера на 0 скидывались.
Неправильно организовали разделение ID между филиалами, а потом уже "исторически сложилось".
← →
evvcom © (2006-09-05 15:45) [30]> [29] ANB © (05.09.06 15:39)
> А если проблема в уже добавленных/измененных записях ?
И что? Я так понимаю, тебе надо узнать используется такой id или нет? ХП проверит, видит ли она такой id и вернет результат триггеру. Триггер дальше решает, что с этим делать. Хочешь raise сделай, хочешь сиквенс еще дерни и опять в ХП.
← →
Sergey13 © (2006-09-05 15:48) [31]> Ну откуда ж оракл знает, что ты дерево в таблице нарисовал.
> Он только при connect by об этом и узнает.
Наверное ты прав, а мне пригрезилось. Попробовал - получил как ты говоришь.
← →
Petr V. Abramov © (2006-09-05 15:49) [32]> Однако, для проверки, например, зацикливания дерева мне бы любые подошли
че-то Вы перемудрили, возможно. Как насчет четкого описания, что Вы хотите сделать и почему именно в триггере?
← →
ANB © (2006-09-05 15:56) [33]
> Petr V. Abramov © (05.09.06 15:49) [32]
ОК.
1)
Имеем парентовое дерево. ID, ID_Parent.
При добавлении/изменении данных пользователь может умудриться дерево зациклить. Чтобы не дать ему этого сделать, нужно выполнить проверку по своей же таблице. В триггере уровня строки этого сделать нельзя. Этот случай можно разрулить либо триггером уровня оператора (сохранив массив строк) либо вообще изменять данные только через хранимку (там такой проблемы не вылезет).
2) Имеем триггер, который присваивает ID первичному ключу. Т.к. сиквенс зациклен, то в триггере производится обращение к своей таблице для проверки дублирования. При вставке более одной строки за раз триггер падает. Обойти вообще никак, только если вставлять всегда по одной строке.
3) И на закузку. Ошибка мутации может вылезти и без триггеров.
← →
evvcom © (2006-09-05 15:57) [34]> [29] ANB © (05.09.06 15:39)
> Неправильно организовали разделение ID между филиалами,
> а потом уже "исторически сложилось".
Если они писали в одну базу, то ID нафиг не надо было разделять.
Если базы разные, а потом репликация в главную, мое имхо, лучше сделать составной ПК из id филиала и сиквенса.
← →
evvcom © (2006-09-05 16:01) [35]> [33] ANB © (05.09.06 15:56)
> В триггере уровня строки этого сделать нельзя.
> Обойти вообще никак, только если вставлять всегда по одной
> строке.
Том Кайт думает по-другому. См. [27] последнее предложение и [30].
> 3) И на закузку. Ошибка мутации может вылезти и без триггеров.
Поподробнее можно?
← →
kaif © (2006-09-05 16:04) [36]Petr V. Abramov © (05.09.06 14:47) [21]
ну так FB ошибку не выдает, а выдает муть.
Приведи пример кода, который выдаст такую муть.
Я готов попробовать.
Зачем зря спорить?
Может я неправ, а прав - ты.
Только учти, что в FB существует большое разнообразие типов транзакций: и wait и nowait и Snapshot и ReadCommitted и RepeatebleRead. И всевозможные лок-конфликты, которые FB успешно отлавливает.
Не знаю, как в ORACLE.
По крайней мере, работая из JAVA, я не смог от ORACLE получить ничего
кроме READ COMMITTED в том смысле, который, как известно периодически "мутирует". Возможно плохо старался.
:)
← →
Petr V. Abramov © (2006-09-05 16:12) [37]> 3) И на закузку. Ошибка мутации может вылезти и без триггеров.
это как Вам удалось??! Научи! :)
> либо вообще изменять данные только через хранимку (там такой проблемы не вылезет).
вот самое лучшее решение.
> то в триггере производится обращение к своей таблице для проверки дублирования.
а не эффективнее ли вставки тоже делать хранимкой и действия предпринимать по факту ошибки
P.S. не люблю триггеры, запутывают они систему, а во-вторых, если в случае крайней необходимости надо руками данные подправить, может нехорошо получиться
← →
ANB © (2006-09-05 16:13) [38]Пример (правда бессмысленный) получения ошибки мутации на функции :
create table table2 (ID integer, Parent_ID integer, Status integer)
insert into table2 (ID, Parent_ID, Status)
select rownum, rownum - 1, decode(mod(rownum,2),0,4,5) from dual
connect by level <= 10000
commit;
CREATE OR REPLACE FUNCTION t2_prev_status (p_prev_id INTEGER)
RETURN INTEGER
AS
v_status INTEGER;
BEGIN
SELECT NVL (MIN (status), 0)
INTO v_status
FROM table2
WHERE ID = p_prev_id;
RETURN v_status;
END;
select t2.*, t2_prev_status(t2.PARENT_ID) from table2 T2
update table2 T2
set Status = t2_prev_status(t2.PARENT_ID)
where ID = 1
я нарывался на эту ошибку и в реальном проекте. Ох и матов было . . .
> работая из JAVA
Ограничения JDBC/Net. Оракл позволяет управлять уровнем изоляции, но этим мало кто пользуется.
← →
evvcom © (2006-09-05 16:17) [39]> [36] kaif © (05.09.06 16:04)
Пример кода:
Создаешь TestTable с полями (Id, Value) и такую же LogTable. Вставляешь в TestTable 2 записи (1,1) и (2,1). Далее триггер on TestTable after update on each row:
insert into LogTable
select * from TestTable;
Далее выполняешь
update TestTable
set
value = value + 1;
и смотришь LogTable. По идее должен получить 4 записи:
(1,2), (2,1), (1,2), (2,2)
или
(1,1), (2,2), (1,2), (2,2)
в зависимости от того, какую запись первой обновит update. Вот из-за этой зависимости результата от очередности изменения записей Oracle и выдает ошибку про "мутации" :)
← →
ANB © (2006-09-05 16:18) [40]
> См. [27] последнее предложение и [30].
Согласен. Но к каждому триггеру придется тогда добавить еще и хранимку.
> Если базы разные, а потом репликация в главную, мое имхо,
> лучше сделать составной ПК из id филиала и сиквенса.
1) Базы, есно, разные.
2) Составной PK не сильно кузяво (в связке из 30-40 таблиц да с извратами это сильно неудобно будет)
3) Исторически сложилось, млин. Достаточно было запихать номер филилала в млдашие ращряды ID, а не в старшие (ограничив собственно ID 20000000) и сиквенса бы хватило весьма надолго. Но - см. начало фразы.
← →
ANB © (2006-09-05 16:20) [41]
> Вот из-за этой зависимости результата от очередности изменения
> записей Oracle и выдает ошибку про "мутации" :)
Вместо этого могли бы описать эту проблему в доке и не резать возможность селекать в своей таблице, когда порядок изменения строк не важен.
← →
evvcom © (2006-09-05 16:26) [42]> [38] ANB © (05.09.06 16:13)
Ну да. Здесь функция вызывается для каждой строки при апдейте. Естественно таблица уже меняется.
> [37] Petr V. Abramov © (05.09.06 16:12)
> P.S. не люблю триггеры, запутывают они систему, а во-вторых,
> если в случае крайней необходимости надо руками данные
> подправить, может нехорошо получиться
Чтобы обеспечить целостность системы, когда возможностей констрейнтов уже недостаточно, предпочитаю писать триггеры. С триггерами можно и руками подправить, если они корректно написаны. А вот с ХП можно нарваться и на поломку целостности, если кто-то из любителей поправить руками (ну я, например) вдруг не знает, что делать это с данной таблицей категорически запрещается.
← →
Val © (2006-09-05 16:30) [43]>[41] ANB © (05.09.06 16:20)
это описанов доке, в разделе о триггерах, описано и решение.
← →
evvcom © (2006-09-05 16:32) [44]> [40] ANB © (05.09.06 16:18)
> Но к каждому триггеру придется тогда добавить еще и хранимку.
Можно и одну написать, если очень лень, в которой SQL формировать динамически. Кстати, а попробуй динамический SQL прямо в триггере. Есть подозрение, что он будет выполняться также в отдельной транзакции. Не утверждаю, но вдруг? На Оракле я такое еще не проверял.
← →
evvcom © (2006-09-05 16:35) [45]> [41] ANB © (05.09.06 16:20)
> Вместо этого могли бы описать эту проблему в доке и не резать
> возможность селекать в своей таблице, когда порядок изменения
> строк не важен
А прикинь, я когда с этим впервые столкнулся, доков на эту тему не читал. Вот умолчал бы Оракл об этом, и я бы долго бы еще тогда пытался понять, почему получаю в селектах не то, что ожидаю. А так полез разбираться и согласился с ними.
← →
ANB © (2006-09-05 16:52) [46]
> что он будет выполняться также в отдельной транзакции
не в отдельной.
> это описанов доке, в разделе о триггерах, описано и решение.
Ну ктоб спорил. "Мы сделали криво, вот вам руководство, как наши кривые руки обойти на 15 листах".
> evvcom © (05.09.06 16:26) [42]
+1.
← →
Val © (2006-09-05 16:58) [47]>[46] ANB © (05.09.06 16:52)
> "Мы сделали криво...
Это ВЫ так думаете, а кто-то думает иначе. Посоветуете подкрутить сервер под желания каждого разработчика? Да ну его нафиг, такое чудовище.
← →
evvcom © (2006-09-05 17:06) [48]> [46] ANB © (05.09.06 16:52)
> "Мы сделали криво,
Я тоже с этим не согласен. Нормально сделали.
← →
ANB © (2006-09-05 17:14) [49]
> Val © (05.09.06 16:58) [47]
> evvcom © (05.09.06 17:06) [48]
Так чего же тут нормального ?
Как мы выяснили на примере FB, логического противоречия никакого нет.
Да, если убрать ошибку, то в НЕКОТОРЫХ случаях возможна неоднозначность операции из-за непредсказуемости последовательности обработки строк таблицы при апдейтах и удалениях. Но :
1) далеко не всегда эта последовательность важна
2) коллизия возможна только при групповом обновлении/удалении записей и легко могла бы быть при надобности ликвидирована использованием курсора (групповой инсерт легко регулируется order by в запросе - никакой неоднозначности).
У меня такое впечатление, что оракл просто по техническим причинам (из-за существующего механизма транзакций) не готов работать с измененными/удаленными записями в рамках одного оператора. Посему, чтобы не мучится, сделали генерацию ошибки и свалили все проблемы на прикладных программистов.
Некузяво как то.
← →
evvcom © (2006-09-05 17:29) [50]> [49] ANB © (05.09.06 17:14)
> логического противоречия никакого нет.
Есть. Вникни в пример [39]. Если FB такое позволяет, поэкспериментируй на нем. Возможность получить разные результаты выполнения - это уже баги. Оракл эту возможность пресёк.
> 1) далеко не всегда эта последовательность важна
Если не важна, обходи эту ситуацию известными способами.
> 2) коллизия возможна только
ну ведь возможна же! :)
> групповой инсерт легко регулируется order by в запросе -
> никакой неоднозначности
AFAIR, order by в инсерте недопустим.
> из-за существующего механизма транзакций
А транзакция тут при чем? Речь идет о групповой замене за один присест, в одном операторе.
> и свалили все проблемы на прикладных программистов.
В твоем случае, ты сам вроде как признался, виноваты сами прикладные программисты. Ошибка проектирования базы. Отсюда и проблемы, которые отпали бы, построив базу "правильно".
← →
ANB © (2006-09-05 17:44) [51]
> AFAIR, order by в инсерте недопустим.
хм. напиши групповой инсерт без селекта.
> построив базу "правильно".
Имхо - правильно, это использовать триггера. А от этого сплошь и рядом приходится отказываться или городить кучу объектов для обхода
> Если FB такое позволяет, поэкспериментируй на нем. Возможность
> получить разные результаты выполнения - это уже баги. Оракл
> эту возможность пресёк.
Мне подход FB больше нравится. А такое пресекание "отберем у всех в Москве спички, чтобы ничего не спалили в деревне Гадюкино" режет фукциональность.
> А транзакция тут при чем? Речь идет о групповой замене за
> один присест, в одном операторе
ПОСЛЕ оператора до коммита в таблице лежат новые данные, в RBS - старые.
А вот где что лежит во время выполнения оператора - х.з. (знаний маловато).
← →
ANB © (2006-09-05 18:56) [52]Кстати, по поводу неоднозначности.
Вот такой оператор :
update Table2 set Status = rownum
будет выполнен без проблем, хотя его результат тоже неоднозначен и зависит от настроения сервера.
Однако этот случай задокументирован, ошибка не генерится.
← →
Desdechado © (2006-09-05 19:15) [53]ANB ©
Ты скажи, ты завел этот топик, чтобы высказать свое возмущение или послушать объяснения?
Возмущения понятны, но, имхо, от них все равно ничего не изменится. Прими механизм как данность. Просто теперь им не выгодно менять логику поведения сервера, слишком много у всех заточек на старый механизм, а обратной совместимости никто не отменял.
Выгоднее делать новые фичи, чем Ларри успешно занимается.
← →
ANB © (2006-09-05 19:23) [54]
> Выгоднее делать новые фичи, чем Ларри успешно занимается.
Ну так прагму бы добавили для тех, кому неохота возится с этой ошибкой. Автономная транзакция же исправляет ситуацию.
> Ты скажи, ты завел этот топик, чтобы высказать свое возмущение
> или послушать объяснения?
Высказать возмущения, послушав объяснения (может я чего не догонял или в FB таже картина). Я то считал, что кроме оракла сия ошибка больше нигде не встречается.
← →
Desdechado © (2006-09-05 19:31) [55]> Автономная транзакция же исправляет ситуацию.
Это заблуждение.
← →
ANB © (2006-09-05 19:40) [56]
> > Автономная транзакция же исправляет ситуацию.
> Это заблуждение.
Функция перестала падать.
Ща доработает - на триггере потренируюсь. Но эта прагма автоматически включает чтение старых данных.
← →
Val © (2006-09-05 19:44) [57]>включает чтение старых данных
может, отключает чтение новых?
← →
Desdechado © (2006-09-05 19:46) [58]> Функция перестала падать.
А теперь подумай, что будет, если надо будет откатить всю транзакцию, а не отдельные ее автономности?
И ты поймешь, что заблуждался относительно "решения пролемы". Ты ее только замаскировал и углубил.
← →
ANB © (2006-09-05 19:51) [59]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;
Вот этот триггер работает. Убираем прагму - валится.
> если надо будет откатить всю транзакцию, а не отдельные
> ее автономности?
Что откатывать после селекта ?
Кстати, таки доп. неудобство. Мало того, что я не могу производить проверки с учетом уже измененных записей (хотя всего одна то меняется, здесь то зачем мутация ?), так еще изменять данный в общем контексте транзакции не смогу.
> может, отключает чтение новых?
да какая разница. пусть будет "отключает".
← →
ANB © (2006-09-05 19:54) [60]Завели бы прагму типа "грязное чтение чего попало". кто хочет иметь такой результат и работать без генерации ошибки - самостоятельно включает. Хочешь по старому - без прагмы все по старому и работает.
Зажрался просто оракл.
← →
Petr V. Abramov © (2006-09-05 23:40) [61]> С триггерами можно и руками подправить, если они корректно написаны. А
> вот с ХП можно нарваться и на поломку целостности, если кто-то из
> любителей поправить руками (ну я, например) вдруг не знает, что делать
> это с данной таблицей категорически запрещается.
это уже оргметодами решается. т.е любители подправить руками, которые не знают, не должны иметь возможность это сделать. А необходимость сия на моей памяти возникала только в случае, когда облажались с кодом и надо быстро привести базу в состояние, когда она в целости и непротиворечивости.
Проблема чуть глубже. вотя как кодер, когда говорю update, знаю, что поменяются записи в соответствии с set и where, и больше ничего. А так прежде чем писать update, теоретически должен предугадать фантазию триггерописателей на срок службы системы. Проблема ессно вылезает, когда таблица стоИт на грани полномочий двух разработчиков.
> что оракл просто по техническим причинам (из-за существующего
> механизма транзакций) не готов работать с измененными/удаленными
> записями в рамках одного оператора.
на мое ИМХО технических проблем нет. Такой же Plssql-ный объект, как и ХП и пакет. А от plssql до мехпнизма управления транзакциями - 2 лаптя по карте. Работает-то он все равно в терминах блоков. Может, конечно просто поленились к релизу глючок какой исправить, и оказалось, что оно на надо, пусть так живет, приложения надежней будут
← →
tesseract © (2006-09-06 00:08) [62]> Выгоднее делать новые фичи, чем Ларри успешно занимается.
да нет в моде упрощёнка, а на кой он MySQL к рукам прибрал?
> я не могу селекать в триггере изменяющуюся таблицу ?
Потому что происходит перестройка файловой структуры базы, что после этого выйдет, и какого цвета, никто не знает, это только dbf сильно предсказуем.
> Есно, при триггере уровня строки у меня селект завалится.
> Однако, если бы он не завалился, а возвращал мне смесь новых
> и старых строк - это бы меня вполне устроило.
А зря, менеджеров, не устраивает, в 99% случаев.
> Вот в IB она никогда не мутирует в режиме ReadCommitted.
ReadCommited для того и создан, максимум производительности при минимуме проблем. Фактически неявная неблокирующая транзакция, пока не подтвердишь данные можно считать старые.
> > что оракл просто по техническим причинам (из-за существующего
>
> > механизма транзакций) не готов работать с измененными/удаленными
>
> > записями в рамках одного оператора.
> на мое ИМХО технических проблем нет. Такой же Plssql-ный
> объект, как и ХП и пакет. А от plssql до мехпнизма управления
> транзакциями - 2 лаптя по карте. Работает-то он все равно
> в терминах блоков. Может, конечно просто поленились к релизу
> глючок какой исправить, и оказалось, что оно на надо, пусть
> так живет, приложения надежней будут
Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде только DB2 в состояниии справиться.
← →
Petr V. Abramov © (2006-09-06 00:47) [63]> Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде
> только DB2 в состояниии справиться.
тот же FB пожеланиям некотрых трудящихся удовлетворяет. А в чем, на Ваш взгляд, технические проблемы-то? Давайте погадаем :)
> пока не подтвердишь данные можно считать старые.
только это небесплатно в плане ресурсов-то
← →
Petr V. Abramov © (2006-09-06 01:44) [64]да ладно. много много в Oracle несовершенства, но у него есть такое же гадкое св-во, как у Windows - люди матерятся на глюки (сабж - не глюк :), но на другие продукты не переходят :)
← →
ANB © (2006-09-06 09:21) [65]
> 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-ке инсерт нескольких записей не работал. Так что есть надежда, что таки потихоньку доведут до ума.
Таки не понятно - почему проходит массовый инсерт и не работает апдейт одной записи ? Триггер уровня строки до. Т.е. ораклу должно быть все понятно, никакой неоднозначности - какая мутация то ?
← →
evvcom © (2006-09-06 10:27) [66]> [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 10:31) [67]
> А зря, менеджеров, не устраивает, в 99% случаев.
Менеджерам важны данные в отчетах и гриде. Триггер их никак волновать не должен. А если по логике триггера мне все равно, в каком порядке изменяются данные, главное - чтобы давали читать уже измененные ?
← →
evvcom © (2006-09-06 10:35) [68]> [67] ANB © (06.09.06 10:31)
Ну сделай табличку в пакете, в нее пиши изменения, а в автономной внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
← →
ANB © (2006-09-06 10:43) [69]
> evvcom © (06.09.06 10:35) [68]
> > [67] ANB © (06.09.06 10:31)
>
> Ну сделай табличку в пакете, в нее пиши изменения, а в автономной
> внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
>
Способов изгала то много. Для проверки на целостность дерева можно и стандартным обходом обойтись. Можно и вообще триггера не использовать.
И запретить использовать функции в DML.
← →
Petr V. Abramov © (2006-09-06 13:37) [70]> ПОСЛЕ оператора до коммита в таблице лежат новые данные, в RBS -
> старые. А вот где что лежит во время выполнения оператора - х.з. (знаний маловато).
в RBS лежат change vectors, изменения данных. А "во время измения" - в тех блоках, которые уже поменялись - новые данные, в которых еще не поменялись - старые :) Второй свежести данных не бывает :) То есть триггер в процеесе выполнения запроса относительно легко может получить старые данные (обычным consistent read, небесплатной процедурой), а новые - никак, потому что не все блоки еще обновились. Может, еще именно из-за consistent read не стали они связываться и сделали выдачу ошибки, тем более, что про винигрет уже много тут говорилось
← →
Petr V. Abramov © (2006-09-06 14:05) [71]> ANB ©
если интересует, что там происходит "во время выполнения оператора", то
1. сделай триггер, который после изменения двух-трех записей повесит сессию (dbms_lock.sleep)
2. поизучай заголовки блоков (v$bh). вечерком могу поискать, как скинуть дамп блока в trace, сейчас просто убегаю.
Счастливых анатомических исследований :)))
← →
Андрей Пазик (2006-09-06 14:43) [72]IB/FB вообще нарушает базовые принципы SQL. Например. Есть у вас поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
И получаем детскими граблями! Потому что ограничения целостности проверяются тут на onrowChange, а не на onStatementFinish.
← →
evvcom © (2006-09-06 15:01) [73]> [72] Андрей Пазик (06.09.06 14:43)
Не знаю как этот случай описан в базовых принципах, а Оракл без специального аттрибута в ключе тоже по рукам даст за такое.
← →
Desdechado © (2006-09-06 15:39) [74]> поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
Смысл этого запроса?
← →
Petr V. Abramov © (2006-09-06 22:05) [75]> Не знаю как этот случай описан в базовых принципах, а Оракл без
> специального аттрибута в ключе тоже по рукам даст за такое.
и по умолчанию бьет. dererrable initially defrerred появилось только в 8-ке (и, что странно, в той же версии оно уже работало :)
← →
Sergey13 © (2006-09-07 08:19) [76]> [75] Petr V. Abramov © (06.09.06 22:05)
Хм. А у меня 8.1.7 съел и не подавился.
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
Память: 0.7 MB
Время: 0.041 c