Additional
dbCAP
AnyDAC
ThinDAC
NCOCI8
Topic: Глюки с транзакциями.
Глюки с транзакциями.
Posted: 2008/03/03 09:47
 
В примере по транзацции есть код:

      StartTransaction;     try       mmInfo.Lines.Add('  Execute simple command inside transaction');       ADQuery1.SQL.Text := 'select * from {id Categories}';       ADQuery1.Open;       mmInfo.Lines.Add('  Commit transaction');       Commit;     except       mmInfo.Lines.Add('  Rollback transaction');       Rollback;       raise;     end;


Во время выполнения возникает исключительная ситуация и код попадает в except следовательно Commit не выполняется, а выполняется Rollback - как и должно быть.
Изменим код:

         StartTransaction;     try       mmInfo.Lines.Add('  Execute simple command inside transaction');       ADQuery1.SQL.Text := 'select * from table1';       ADQuery1.Open;       ADQuery1.Edit;       ADQuery1.FieldByName('coll1').AsInteger := 10000;//Допустим значение которое данное поле принять не может.       ADQuery1.Post//Здесь происходит исключение       mmInfo.Lines.Add('  Commit transaction');       Commit;     except       mmInfo.Lines.Add('  Rollback transaction');       Rollback;       raise;     end;


Во время выполнения возникает исключительная ситуация и код попадает в except следовательно Commit не выполняется, а выполняется Rollback – Здесь тоже все верно.

Изменим код ещё (Включим кэширование изменений):

         ADQuery1.CachedUpdates := True;//Включаем кэширование     StartTransaction;     try       mmInfo.Lines.Add('  Execute simple command inside transaction');       ADQuery1.SQL.Text := 'select * from table1';       ADQuery1.Open;       ADQuery1.Edit;       ADQuery1.FieldByName('coll1').AsInteger := 10000;//Допустим значение которое данное поле принять не может.       ADQuery1.Post;       ADQuery1.ApplyUpdates();//Здесь должно пройти исключение       mmInfo.Lines.Add('  Commit transaction');       Commit;     except       mmInfo.Lines.Add('  Rollback transaction');       Rollback;       raise;     end;


Во время выполнения ни какой исключительной ситуации не происходит и транзакция завершается оператором Commit, секция except не выполняется. Хотя во всех случаях изменения в базе не были произведены.
Таблица Table существует на самом деле и поле coll1 тоже существует и имеет тип TINYINT(1). Если оператор ADQuery1.FieldByName('coll1').AsInteger := 10000; заменить на ADQuery1.FieldByName('coll1').AsInteger := 10; то изменения в базу нормально заносятся.
Также во время первого выполнения программы (в последнем варианте) при выполнении инструкции ADQuery1.ApplyUpdates(); Выскочило сообщение об ошибке обновления, но программа в секцию except не попала. При последующих запусках программы больше ни какого сообщения не выскакивало.

Пробовал ADQuery1.ApplyUpdates(); заменить на ADQuery1.ApplyUpdates(0); - ни какого эффекта не произвело, все осталось на том же уровне.
В Мониторе для последнего варианта проходит:

 BEGIN select from table1 UPDATE table1SET coll1 10000 WHERE id AND coll1 10 AND coll2 '0001' COMMIT


Поле выполнения чего изменений в базе не происходит.