Форум: "Начинающим";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];
ВнизОткат транзакции в InterBase. Найти похожие ветки
← →
Drowsy (2009-09-15 17:45) [0]Должен ли происходить откат на внесённые в таблицу А изменения и если да, то почему може не происходить?
TransactionAll - на базе
TransactionA - на выборке из таблицы А.
TransactionВ - на выборке из таблицы В.
TransactionAll.StartTransaction;
try
TransactionA.StartTransaction;
// изменения на А
TransactionA.Commit;
TransactionB.StartTransaction;
// изменения на B
=> появление Exception.
TransactionB.Commit;
TransactionAll.Commit;
except
TransactionAll.RollBack;
end;
← →
DrPass © (2009-09-15 17:56) [1]
> Должен ли происходить откат на внесённые в таблицу А изменения
> и если да, то почему може не происходить?
Неизвестно. Т.к. из данного кода неясно, в рамках какой транзакции ты делал изменения в таблице А. Если это была TransactionA, то откат, конечно же, происходить не должен. Если TransactionAll, то должен
← →
Drowsy (2009-09-15 18:03) [2]
> неясно, в рамках какой транзакции ты делал изменения в таблице
> А.
TransactionA связана с TIBQury - выборке из таблицы А.
И ей делается коммит.
Мне нужно сделать пакетно изменения в таблицах и откатить все, если при
изменении хоть одной возникло исключение...
← →
Drowsy (2009-09-15 18:13) [3]Я запутался в Commit, RollBack, CommitRetaining, RollBackRetaining, параметрах транзакций...
Что в каких случаях применяется когда и как......
Руководства врубаются сразу в тонкости и детали, а для начинающих, с нуля и "на пальцах" никому не интересно
писать...
← →
DrPass © (2009-09-15 18:36) [4]
> Мне нужно сделать пакетно изменения в таблицах и откатить
> все, если при
> изменении хоть одной возникло исключение...
Тогда тебе нужно делать не три транзакции, а только одну. И связать ее со всеми компонентами, участвующими в этих самых пакетных изменениях.
> Руководства врубаются сразу в тонкости и детали, а для начинающих,
> с нуля и "на пальцах" никому не интересно
> писать...
А что там объяснять для начинающих, по крайней мере, в отношении Interbase? Транзакция объединяет группу операций с базой данных. Все, что выполняется в рамках одной и той же транзакции, можно разом применить через commit, или разом отменить через rollback. Каких-либо там глобальных транзакций, или вложенных друг в друга в Interbase нет.
← →
Drowsy (2009-09-15 18:49) [5]А в моём примере TransactionA и TransactionВ не являются вложенными по отношению к TransactionAll?
Я сейчас сделал так :
try
TransactionAll.StartTransaction;
TransactionA.StartTransaction;
// изменения на А
TransactionB.StartTransaction;
// изменения на B
=> появление Exception.
TransactionA.Commit;
TransactionB.Commit;
TransactionAll.Commit;
except
TransactionA.RollBack;
TransactionB.RollBack;
TransactionAll.RollBack;
end;
Работает, но дико долго стало работать. Когда после изменений делал коммит на каждом наборе, то хотя отката при ексепшене не происходило (как, по пояснениям DRPASS - спасибо!, и должно было случиться), но работало несравнимо быстрее.
← →
Inovet © (2009-09-15 18:54) [6]> [5] Drowsy (15.09.09 18:49)
Одну пока оставь.
← →
Юрий Зотов © (2009-09-16 00:30) [7]> Drowsy (15.09.09 18:49) [5]
Зачем так усложнять и путать? Если откатывать нужно ВСЕ изменения - значит, и транзакция должна быть только ОДНА. Причем стартовать ее надо ПЕРЕД try, а не внутри (иначе, если при старте транзакции возникнет исключение, то код попытается ее откатить - а раз она не стартовала, то и откатывать нечего).
Transaction.StartTransaction;
try
... // все изменения
Transaction.Commit
except
Transaction.RollBack
end;
← →
Германн © (2009-09-16 00:38) [8]
> Drowsy (15.09.09 18:49) [5]
>
>
Лучше бы всё же почитать книжку. А то явная путаница с "вложенностью". Плюс благодарность DrPass © за то, что сам и не понял.
← →
Юрий Зотов © (2009-09-16 01:50) [9]> Drowsy
Кстати, в секции except после отката транзакции надо бы как-то обработать исключение (хотя бы выдать юзеру сообщение). В простейшем случае - просто raise.
← →
Германн © (2009-09-16 02:33) [10]
> Кстати, в секции except после отката транзакции надо бы
> как-то обработать исключение (хотя бы выдать юзеру сообщение).
> В простейшем случае - просто raise.
>
Ну да. Хотя бы затычку!
← →
Drowsy (2009-09-16 06:20) [11]А - главная таблица с автоинкрементным ключом
В - связанная таблица
Сделал всё в одной транзакции.
Теперь такое:
После инсерта записи в А, при попытке ввести связанную запись в В, генерируется ошибка dead lock, с указанием на Foreign Key таблицы В.
← →
Sergey13 © (2009-09-16 08:49) [12]> [11] Drowsy (16.09.09 06:20)
Может все таки код напишешь вместо своих
> Сделал всё в одной транзакции
> генерируется ошибка dead lock, с указанием на Foreign Key таблицы В
Что-то сомнительно про dead lock. Ключ не находит - понятно. В данном случае ключ для главной таблицы надо не генерить в тригере, а получать заранее, перед началом транзакции, для всех вставляемых записей.
← →
Юрий Зотов © (2009-09-16 10:21) [13]> Drowsy (16.09.09 06:20) [11]
Псевдокод:
Transaction.StartTransaction;
try
// 1. Получаем ID новой записи в таблице A и лочим ее
"select Max(ID) + 1 into NewID from A for update";
// 2. Вставляем запись в таблицу A, явно указывая ID = NewID
"insert into A...";
// 3. Вставляем запись в таблицу B, явно указывая ForeignKey = NewID
"insert into B...";
Transaction.Commit
except
Transaction.RollBack;
raise
end;
← →
Юрий Зотов © (2009-09-16 10:29) [14]Кстати, вопрос к знатокам: достаточно ли для блокировки таблицы A на время транзакции указать "for update", или нужны другие телодвижения?
← →
MsGuns © (2009-09-16 10:39) [15]ИМХО, налицо непонимание сущности понятия "транзакция".
Советую о транзакциях, в том числе и об уровнях их изоляции, почитать у Вострикова с Ковязиным. Более доступного и полного объяснения механизма транзакций не встречал.
Если измениния, производимые в нескольких таблицах БД, нужно "завернуть" в один "пакет", то лучше всего это делать в хранимой процедуре. Там же и возбуждать исключения. Клиент лишь запускает эту ХП и анализирует ее результат, сам же механизм со всеми тонкостями реализации для него не должен быть виден, т.к. является элементом бизнес-логики сервера, т.е. некоим образом не должен зависеть от клиента.
← →
Sergey13 © (2009-09-16 11:09) [16]> [13] Юрий Зотов © (16.09.09 10:21)
> "select Max(ID) + 1 into NewID from A for update";
Пробовать не начем, но сомневаюсь, что такой запрос вообще отработает. For update блокирует от изменения записи, а тут в наличии только результат функции.
Но и идеологически так делать нельзя. Нужно запроситьselect Gen_ID(N,Gen_name) from rdb$database
где N - число вставляемых записей
В результате получим максимальный зарезервированный ИД-шник. От него уже считать минимальный и промежуточные.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.013 c