参见:Delphi 中 FireDAC 数据库连接(总览)
描述了如何使用FireDAC来管理DBMS事务。FireDAC提供TFDConnection和TFDTransaction组件来帮助你处理数据库事务。
一、概述
默认情况下,FireDAC应用程序在自动提交模式下工作,当需要时,FireDAC会自动启动一个事务,并在命令执行成功时提交,或在失败时回滚。自动提交是由TFDTxOptions.AutoCommit属性控制的。自动提交模式对应用程序来说很简单,但它:
减慢了对数据库的多次更新。
不允许你在一个事务中执行更多的数据库操作。
不能在一个时间内延长。
另外,应用程序可以使用显式事务控制。为此,使用TFDConnection方法StartTransaction, Commit, Rollback。另一个选择是使用TFDTransaction组件。
注意:在FireDAC中,TFDTransaction组件的使用是可选的。
FireDAC提供了Isolation, ReadOnly, Params属性,允许你控制事务模式。它们同时适用于自动提交和显式事务。并非所有的模式都被DBMS支持,例如只读模式,因为FireDAC使用了一个限制性较小的模式。注意,所有的设置将只应用于下一个事务。
使用显式事务的标准代码如下:
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
FDQuery1.ExecSQL;
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
TFDTransaction组件将事务控制功能包装成一个组件。实际上,它提供了与TFDConnection相同的事务功能,但允许你通过将命令和数据集链接到一个特定的事务对象来分组。起初,这指的是对多个活动事务的支持,也就是Interbase和Firebird的服务器功能。
TFDTxOptions.Params可以用来指定DBMS特定的事务属性。目前,只有Firebird / InterBase驱动支持这种属性。每个属性必须在一个单独的行中指定。它与isc_tpb_<属性名称>事务参数相对应。
二、嵌套事务
虽然没有一个支持的数据库管理系统支持嵌套事务,但是FireDAC使用保存点来模拟它们。这意味着嵌套的StartTransaction调用并不启动一个新的事务,也不引发一个异常,而是放置一个保存点。如果一个DBMS不支持保存点,那么就会引发 "不支持能力 "的异常。
要禁用嵌套事务,将TFDTxOptions.EnableNested设置为False。然后,嵌套的StartTransaction调用会引发一个异常。
相应的Commit调用会释放一个保存点,Rollback会回滚到一个保存点。比如说:
// start new transaction
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
// set savepoint
FDConnection1.StartTransaction;
try
FDQuery1.ExecSQL;
....
// release savepoint
FDConnection1.Commit;
except
// rollback to savepoint
FDConnection1.Rollback;
raise;
end;
// commit transaction
FDConnection1.Commit;
except
// rollback transaction
FDConnection1.Rollback;
raise;
end;
注意:一个嵌套交易(事务)使用最上层交易(事务)的设置。
三、连续交易(事务)
CommitRetaining和RollbackRetaining方法与Commit和Rollback方法类似,但它们不会完成事务。因此,在这些调用之后,它仍然处于活动状态。Firebird / InterBase服务器在DBMS核心层面上支持这个功能。对于所有其他的数据库管理系统,这个功能是用Commit / Rollback和StartTransaction调用来模拟的。
四、多个有效交易(事务)
Firebird和InterBase在DBMS核心层支持多个活动事务。这意味着一些命令可以在一个事务上下文中执行,另一些在第二个事务上下文中执行,以此类推。为了支持这一特性,FireDAC提供了TFDTransaction组件。它的单一实例允许你在任何时候处理单一事务。
TFDCustomConnection属性可以用来设置默认的事务对象。
Transaction - 所有命令的默认交易对象。
UpdateTransaction - 所有更新命令的默认事务对象,用于发布FireDAC数据集的更新。请注意,UpdateTransaction不会被使用,例如,对于明确指定给TFDQuery组件的UPDATE查询。
TFDCustomQuery和其他组件有类似的属性。
Transaction - 用于执行SQL查询的显式事务对象。
UpdateTransaction - 明确的事务对象,用于发布数据集的更新。
一般来说,为Firebird / InterBase应用程序设置事务对象的最佳方式如下:
UpdateTransaction: TFDTransaction;
ReadTransaction: TFDTransaction;
...
// setup transaction for updating commands: read_committed, rec_version, nowait
UpdateTransaction.Connection := FDConnection1;
FDConnection1.UpdateOptions.LockWait := False;
UpdateTransaction.Options.ReadOnly := False;
UpdateTransaction.Options.Isolation := xiReadCommitted;
...
ReadTransaction.Connection := FDConnection1;
ReadTransaction.Options.ReadOnly := True;
ReadTransaction.Options.Isolation := xiReadCommitted;
...
SelectQuery.Transaction := ReadTransaction;
SelectQuery.UpdateTransaction := UpdateTransaction;
注意:你可以为其他数据库管理系统使用一个以上的TFDTransaction。然后,所有TFDTransaction组件共享同一个事务。
五、事务和游标
DBMS将一个开放的游标与交易上下文相关联,在那里它被打开。当事务完成后,DBMS可能会使活动游标失效。具体的行为取决于DBMS。
DBMS | Action |
Microsoft Access | 在StartTransaction / Commit / Rollback中使游标无效。 |
Firebird | 在提交/回滚时使游标无效。 |
Informix | <nothing> |
InterBase | 在提交/回滚时使游标无效。 |
IBM DB2 | 在回滚时使游标无效。 |
MySQL | 在StartTransaction / Commit / Rollback中使游标无效。 |
Oracle | <nothing> |
PostgreSQL | 在提交/回滚时使游标无效。 |
SQLite | 在回滚时使游标无效。 |
SQL Anywhere | <nothing> |
SQL Server | 在StartTransaction / Commit / Rollback中使游标无效。 |
Teradata Database | <nothing> |
当FireDAC发现一个导致游标失效的事务控制命令时,它会执行FetchOptions.AutoFetchAll指定的动作,并释放游标。
注意:Firebird / InterBase服务器在事务完成后会使准备好的语句失效。因此,自动提交模式可能导致这些数据库管理系统的性能下降。