FireDAC+Interbase部分窗体仅关闭应用后才更新数据库的问题
Delphi 10.3 + FireDAC + Interbase 更新延迟问题处理
问题场景
使用Delphi 10.3结合FireDAC连接Interbase数据库时,多数窗体执行Update语句后调用Commit能立即生效,但在某一窗体中,两次Update之间存在查询Open操作时,第二次Update不会立即更新数据库,必须关闭窗体并退出应用后才生效。
已发现的触发规律
单独执行Update后调用Commit可正常生效;但当两次Update中间插入查询Open操作时,必须在Open前调用StartTransaction,Open完成后执行Commit,后续的第二次Update才能立即生效。相关代码示例:
DM_IB.IBF_VHE.ExecSQL('Update BB_ASML_FORECAST set Uren_Montage = 100, Uren_Berekend = ''Ja'' ' + 'where AANMAAK_DATUMTIJD = ''19-10-2022 10:12:38'' and ItemCode = ''4022.472.18632'' ') ; DM_IB.IBF_VHE.Commit ; ShowMessage('1') ; // 无问题,正常生效 MEM_VPA.DisableControls ; MEM_Fouten.DisableControls ; Post_Confirm := False ; Try MEM_VPA.Close ; MEM_VPA.Open ; MEM_VPA.EmptyTable ; MEM_Fouten.Close ; MEM_Fouten.Open ; MEM_Fouten.EmptyTable ; With TFDQuery.Create(nil) do Try Connection := DM_IB.IBF_VHE ; SQL.Text := 'select * from PL_CAPACITEIT_NPW where ' + '(jaar = ' + FormatDateTime('yyyy', now()) + ' and ' + 'Weeknummer > ' + IntToStr(WeekofTheyear(Now())) + ') or ' + '(jaar = ' + FormatDateTime('yyyy', IncYear(Now())) + ' and ' + 'weeknummer < ' + IntToStr(52 - (52 - WeekofTheyear(Now()))) + ') order by jaar, weeknummer' ; DM_IB.IBF_VHE.StartTransaction ; // 若不加此行及后续Commit,下方更新需等到应用结束才生效 Open ; DM_IB.IBF_VHE.Commit ; DM_IB.IBF_VHE.StartTransaction ; DM_IB.IBF_VHE.ExecSQL('Update BB_ASML_FORECAST set Uren_Montage = 100, Uren_Berekend = ''Ja'' ' + 'where AANMAAK_DATUMTIJD = ''19-10-2022 10:12:38'' and ItemCode = ''4022.472.88135'' ') ; DM_IB.IBF_VHE.Commit ; ShowMessage('2') ; // 仅当上述Open操作处于事务中时才生效
原因分析
FireDAC默认事务行为中,当执行查询(Open)操作时,如果没有显式开启事务,FireDAC会隐式启动一个事务,并且不会自动提交这个事务。后续的Update操作会被纳入这个未提交的隐式事务中,只有当连接被关闭(比如应用退出)时,事务才会被提交,导致更新延迟生效。
解决方案
- 显式管理所有事务:无论是查询还是更新操作,都显式调用
StartTransaction和Commit,确保每个操作的事务及时结束,避免隐式事务堆积。 - 调整AutoCommit属性:将FireDAC连接组件的
TxOptions.AutoCommit设置为True,这样每个数据库操作都会自动提交事务,无需手动调用Commit。但注意此模式下无法实现跨多个操作的原子性事务,适合单步独立操作场景。 - 统一处理EmptyTable操作:
EmptyTable本质也是数据修改操作,建议同样包裹在显式事务中执行,避免触发额外的隐式事务。
内容的提问来源于stack exchange,提问作者FvS
相关产品推荐
相关产品推荐

