Транзакции в MyQuery

Обсуждение возникших проблем, предложений и ошибок MyDAC компонентов
Ответить
imobile
Сообщения: 103
Зарегистрирован: Сб 12 ноя 2011 00:12

Транзакции в MyQuery

Сообщение imobile » Вт 20 мар 2012 12:00

Подскажите, как правилно пользоваться транзакциями.
У меня есть несколко запросов, типа UPDATE и SELECT но разными query на разных формах, мне надо в случае ошибки данные не записывать.
Где можно посмотреть примеры с MyQuery работающие с SET AUTOCOMMIT, BEGIN,COMMIT,ROLLBACK? Можно их использовать, когда разные Query?Будут они связанные между собой в разных Query или будут независимые?

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Сообщение AndreyZ » Ср 21 мар 2012 10:23

Примеры:

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.ExecSQL('set autocommit = 0', []);
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.ExecSQL('commit', []);
except
  MyConnection.ExecSQL('rollback', []);
end;

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.ExecSQL('start transaction', []);
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.ExecSQL('commit', []);
except
  MyConnection.ExecSQL('rollback', []);
end;
Вместо использования данных MySQL запросов мы советуем использовать методы StartTransaction, Commit и Rollback компонента TMyConnection. Пример:

Код: Выделить всё

MyQuery.Connection := MyConnection;
MyQuery.SQL.Text := 'select * from tablename';
MyQuery.Open;
MyConnection.StartTransaction;
try
  MyQuery.Edit;
  MyQuery.FieldByName('fieldname').AsString := 'test';
  MyQuery.Post;
  MyConnection.Commit;
except
  MyConnection.Rollback;
end;
Транзакция открывается для сессии, поэтому все изменения в разных датасетах использующих одну сессию будут приниматься или откатываться одновременно.

imobile
Сообщения: 103
Зарегистрирован: Сб 12 ноя 2011 00:12

Сообщение imobile » Ср 21 мар 2012 10:49

СПАСИБО БОЛЬШОЕ, как просто все оказывается.

Jonnik
Сообщения: 2
Зарегистрирован: Ср 16 май 2012 20:08

Re: Транзакции в MyQuery

Сообщение Jonnik » Ср 16 май 2012 20:13

Почему у меня не работает так транзакция?

Сдесь более продробно расписано http://www.sql.ru/forum/actualthread.aspx?tid=941472

Также могу добавить, что последний из выше приведеных примеров работает. А этот нет.


Код: Выделить всё

 try
        DM.MyConnection1.StartTransaction;
        
            with DM.MyQuery1 do
              begin
                Close;
                sql.text:='INSERT INTO Org(  ID_Tip_O, NK, ND,  Kom)'
                +' VALUES ( :ID_Tip_O, :NK, :ND, :Kom)';
                Params[0].Value:=s[12];
                Params[1].Value:=s[2];
                Params[2].Value:=s[3];
                Params[3].Value:=s[4];
                ExecSQL;
              end;

            if ListView1.Items.Count>0 then
              begin
                for i:=0 to ListView1.Items.Count-1 do
                  begin
                    with DM.MyQuery1 do
                      begin
                        Close;
                        sql.text:='INSERT INTO Org_Kont( ID_Org, ID_Tip, N)'
                        +' VALUES ( :ID_Org, :ID_Tip, :N)';
                        Params[0].Value:=s[15];
                        Params[1].Value:=s[16];
                        Params[2].Value:=ListView1.Items[i].SubItems[2];
                        ExecSQL;
                      end;
                  end;
              end;

          end;
        DM.MyConnection1.Commit;
      except
        DM.MyConnection1.Rollback;
        
      end;


AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Транзакции в MyQuery

Сообщение AndreyZ » Чт 17 май 2012 10:25

Данная проблема вызвана установкой свойства TMyQuery.FetchAll в False. Если FetchAll=True , TMyQuery получает с сервера все данные сразу, если FetchAll=False , данные получаются по мере необходимости, что позволяет экономить ресурсы клиента. Но при FetchAll=False выполнение запросов блокирует текущую сессию. Для избежания этого MyDAC создает дополнительную сессию, которая выполняется вне контекста транзакции. Это приводит к тому что методы TMyConnection.Commit и TMyConnection.Rollback главной сессии не учитывают изменений сделанных в дополнительных сессиях. Для решения проблемы Вы можете использовать один из следующих подходов:
1. Установить TMyQuery.FetchAll в True.
2. Оставить TMyQuery.FetchAll=False и установить TMyQuery.Options.CreateConnection в False. TMyQuery.Options.CreateConnection определяет создавать или нет дополнительные сессии.
3. Использовать компонент TMyCommand вместо TMyQuery для выполнения запросов не возвращающих данных (INSERT, UPDATE, DELETE).

Jonnik
Сообщения: 2
Зарегистрирован: Ср 16 май 2012 20:08

Re: Транзакции в MyQuery

Сообщение Jonnik » Чт 17 май 2012 16:10

Спасибо.

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: Транзакции в MyQuery

Сообщение AndreyZ » Пт 18 май 2012 08:04

Я рад что смог помочь. Если у Вас возникнут дальнейшие вопросы по MyDAC, пишите нам.

readiv
Сообщения: 1
Зарегистрирован: Чт 25 дек 2014 22:36

Re: Транзакции в MyQuery

Сообщение readiv » Чт 25 дек 2014 22:50

Понекропостю.

Код: Выделить всё

  con1.StartTransaction;
  try
    myqry1.SQL.Clear;
    myqry1.SQL.Add('INSERT INTO shop_brands (url) VALUES ('+QuotedStr(Translit_URL(S))+');');
    myqry1.SQL.Add('SELECT @@IDENTITY;');
    myqry1.ExecSQL;
    id:=myqry1.Fields[0].AsInteger;
    myqry1.SQL.Add('INSERTtttt INTO shop_brands_i18n (id,locale,name,meta_title,meta_description,meta_keywords) VALUES ('+
                   IntToStr(id)+', ''ru'', ' +
                   QuotedStr(S)+', '+QuotedStr(S)+', '+QuotedStr(S)+', '+QuotedStr(S)+');');
    myqry1.ExecSQL;
    con1.Commit;
  except
    con1.Rollback;
  end;
INSERTtttt - ошибка сделана специально что бы вызвать исключение. После исключения должен отработать Rollback и откатить первый INSERT, но этого не происходит. Вместо этого в этой таблице создаются аж 2 :shock: индентичные записи. FetchAll = True. CreateConnection = False.

Пробовал с MyConnection.ExecSQL('set autocommit = 0', []); результат тот же. Посоветуйте в какую сторону копать.

ViktorV
Devart Team
Сообщения: 199
Зарегистрирован: Чт 31 июл 2014 09:52

Re: Транзакции в MyQuery

Сообщение ViktorV » Пт 26 дек 2014 12:24

К сожалению, мы не смогли воспроизвести проблему описанным Вами способом. Пожалуйста, обновите MyDAC до последней версии (8.4.12) и, если это не решит проблему, пришлите небольшой пример на viktorv*devart*com, демонстрирующий проблему, включающий скрипт на создание и заполнение таблиц БД.
2 идентичные записи в таблице "shop_brands" создаются потому, что Вы используете метод myqry1.SQL.Add и после второго вызова myqry1.ExecSQL опять выполняется запрос "INSERT INTO shop_brands", для решение этой проблемы Вы можете использовать вместо метода myqry1.SQL.Add свойство myqry1.SQL.Text или перед вызовом myqry1.SQL.Add вызвать метод myqry1.SQL.Clear.

Goris
Сообщения: 5
Зарегистрирован: Вс 21 янв 2018 22:44

Re: Транзакции в MyQuery

Сообщение Goris » Вс 21 янв 2018 23:32

Здравствуйте!
Работаю в Delphi 7, установлен MyDAC 7.1.6.

Есть tDBGridEh, связанный с tDataSource-tMyQuery-tMyConnection
Таблица в БД MySQL типа InnoDB. Свойство MyQuery.FetchAll=true.

При создании формы ставлю MyConnection1.StartTransaction
В DBGridEh редактирую данные, потом жму на соответствующую кнопку для MyConnection1.Commit либо MyConnection1.Rollback.
Выяснилось, что в любом случае происходит запись данных в таблицу, Rollback не срабатывает, ошибок при этом не возникает. Насчет работы Commit ничего не могу сказать, т.к. запись происходит как при его наличии, так и при его отсутствии.
Попытка писать через MyConnection.ExecSQL('set autocommit = 0', []); и MyConnection.ExecSQL('rollback', []); также не работает - нет отмены транзакции.

Перечитал практически весь форум, перепробовал предлагаемые варианты, решения моего вопроса не нашел. Подскажите, как идет работа с транзакциями, может чего пропустил.

Goris
Сообщения: 5
Зарегистрирован: Вс 21 янв 2018 22:44

Re: Транзакции в MyQuery

Сообщение Goris » Вт 23 янв 2018 05:21

вопрос перенес в новую тему

ViktorV
Devart Team
Сообщения: 199
Зарегистрирован: Чт 31 июл 2014 09:52

Re: Транзакции в MyQuery

Сообщение ViktorV » Вт 23 янв 2018 13:52

Мы ответили вам на форуме viewtopic.php?t=14285

Ответить