Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.11.01;
Скачать: CL | DM;

Вниз

Откат транзакции в 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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.018 c
2-1252096753
Shyrick
2009-09-05 00:39
2009.11.01
Межпроцессное взаимодействие IPC


4-1220278943
Lamer666
2008-09-01 18:22
2009.11.01
Motherboard ID?


6-1209048516
lobach
2008-04-24 18:48
2009.11.01
Передача нескольких строк Post


15-1252076055
Ruzzz
2009-09-04 18:54
2009.11.01
Не работает переименование(рефакторинг) в Windows 7


2-1252921892
dmitry83-nv
2009-09-14 13:51
2009.11.01
2 поля данных в ListBox