Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
15-1251846861
TIF
2009-09-02 03:14
2009.11.01
Главный сайт страны обновился


2-1252089538
Achpile
2009-09-04 22:38
2009.11.01
Цвета


2-1253019089
Achpile
2009-09-15 16:51
2009.11.01
Диалоги


2-1252616137
fics)
2009-09-11 00:55
2009.11.01
TQuery


2-1252333617
Rembo
2009-09-07 18:26
2009.11.01
Многопоточный Indy (idHTTP)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский