【发布时间】: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,它们往往会创建越来越多的数据库对象。