【问题标题】:Commit vs CommitRetaining提交与提交保留
【发布时间】:2017-05-08 12:20:04
【问题描述】:

我制作了一个 Delphi 应用程序,它在 Firebird 数据库中插入一行。 通过 CommitRetaining 解决的查询存在问题,但我读到使用它是不正确的,因为它可能会影响服务器更慢。当我只使用 Commit 时会发生奇怪的事情,查询运行正常,但是当我想查看是否插入了行时,Retainingit 没有。它仅在应用程序终止时插入。但是当使用 CommitRetaining 时,会立即插入行。

什么可能导致问题? 编辑:使用 CommitRetaining 的代码

             adqPom := TADQuery.Create(nil);
             adqPom.Connection := form1.ADOConnection1;
             adTransakcija := TADTransaction.Create(nil);
             adTransakcija.Connection:=form1.ADOConnection1;
             adqPom.Transaction:=adTransakcija;
             adTransakcija.StartTransaction;
             try
               with adqPom do
               begin
                 close;
                 sql.Clear;
                 sql.Add('insert into uplate(sifra,b_prijema,magacin,datum,iznos,b_uplate,b_izvoda,banka,godina,tr_rac,datum_dokument)');
                 sql.Add('values(:S,:BP,:M,:D,:I,:BU,:BI,:B,:G,:TR,:DD)');
                 ParamByName('S').Value := strtoint(edit1.Text);
                 if Form15.adoqDostavn.FieldValues['A1'] = 3 then
                     edit3.Text := '99999';
                 ParamByName('BP').Value := edit3.Text;
                 ParamByName('M').Value := edit2.Text;
                 ParamByName('D').Value := strtodate(edit4.Text);
                 ParamByName('I').Value := StrToFloat(edit5.Text);
                 ParamByName('BU').Value := Br_Uplate+1;
                 ParamByName('BI').Value := strtoint(Edit6.Text);
                 ParamByName('B').Value := Edit8.Text;
                 ParamByName('G').Value := 2006;
                 if Form15.adoqDostavn.FieldValues['A1'] = 3 then
                   ParamByName('TR').Value:= form15.adoqDostavn.FieldValues['B_PRIJEMA']
                 else
                   ParamByName('TR').Value:= Form15.adoqDostavn.FieldValues['B_DOST'];
                 ParamByName('DD').Value:=StrToDate(edit9.Text);
                 ExecSQL;
               end;
               adTransakcija.CommitRetaining;
             except
               adTransakcija.RollbackRetaining;
               raise;
             end;
             FreeAndNil(adTransakcija);
             FreeAndNil(adqPom);

编辑:使用提交的代码(实际上查询的属性设置为自动提交)

               adqPom := TADQuery.Create(nil);
               adqPom.Connection := form1.ADOConnection1;
               with adqPom do
               begin
                 close;
                 sql.Clear;
                 sql.Add('insert into uplate(sifra,b_prijema,magacin,datum,iznos,b_uplate,b_izvoda,banka,godina,tr_rac,datum_dokument)');
                 sql.Add('values(:S,:BP,:M,:D,:I,:BU,:BI,:B,:G,:TR,:DD)');
                 ParamByName('S').Value := strtoint(edit1.Text);
                 if Form15.adoqDostavn.FieldValues['A1'] = 3 then
                     edit3.Text := '99999';
                 ParamByName('BP').Value := edit3.Text;
                 ParamByName('M').Value := edit2.Text;
                 ParamByName('D').Value := strtodate(edit4.Text);
                 ParamByName('I').Value := StrToFloat(edit5.Text);
                 ParamByName('BU').Value := Br_Uplate+1;
                 ParamByName('BI').Value := strtoint(Edit6.Text);
                 ParamByName('B').Value := Edit8.Text;
                 ParamByName('G').Value := 2006;
                 if Form15.adoqDostavn.FieldValues['A1'] = 3 then
                   ParamByName('TR').Value:= form15.adoqDostavn.FieldValues['B_PRIJEMA']
                 else
                   ParamByName('TR').Value:= Form15.adoqDostavn.FieldValues['B_DOST'];
                 ParamByName('DD').Value:=StrToDate(edit9.Text);
                 ExecSQL;
               end;
               FreeAndNil(adqPom); 

【问题讨论】:

  • 我可能是错的,但我知道的唯一区别是 CommitRetaining 应该只保持事务处于活动状态。您从哪里读到 CommitRetaining 不是一个好的做法?尝试在“正常”提交后重新激活事务,您应该会找到您插入的行。
  • @ExDev 提交保留可能会出现问题,因为如果事务存活时间过长,事务间隙会增加,这会抑制垃圾收集,从而导致更长的记录版本链需要进行扫描,这会导致性能下降。
  • 在我看来,您正在从插入记录之前开始的事务中查询。您需要显示出现此问题的代码。
  • 当然,已发布代码。
  • @MarkRotteveel - 此外,BLOB id 开始泄漏 - 它们仅在事务提交时被释放。这意味着,即使是声明为只读的事务,如果它们是长期存在的,如果在表达式中使用文本 blob,它们往往会创建越来越多的数据库对象。

标签: sql delphi firebird


【解决方案1】:

提交释放事务环境,而 CommitRetaining 是一个不释放事务环境的提交(游标仍然打开)。您可以在进程中使用 CommitRetaining,但最后必须使用 Commit 来释放内存。

通常 CommitRetainning 用于优化一个进程(包括大量的 Begin/Commit),但在这个进程结束时你必须使用 Commit 来清除内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-13
    • 2011-05-13
    • 2015-04-18
    • 2015-02-25
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多