数据库为了保证数据的一致性,提出了事务的概念。事务就是一系列的SQL语句构成的单元,这些SQL语句要么同时在数据库上执行成功,要么同时失败,不会出现一部分成功,一部分失败的情况,以保证数据的一致性。例如:入库时候,需要在入库单表中增加一条记录,同时要修改库存表中的库存数量,这两个动作如果执行一半就会造成数据不一致。
1. Transaction
1.1. 相关属性和方法
function Start(AImmediate: Boolean): TTransactionHandle;
启动事务procedure Commit(AHandle: TTransactionHandle);
提交事务procedure Rollback(AHandle: TTransactionHandle);
回滚事务property Rollbacked: Boolean;
只读属性,是否回滚了事务
1.2. 用法示例
1 var
2 lHandle: TTransactionHandle;
3 begin
4 lHandle := DataSet.Connection.Transaction.Start(False);
5 try
6 //...在这里处理每一条需要提交的数据数据,并且提交.
7 DataSet.Connection.Transaction.Commit(lHandle);
8 except
9 DataSet.Connection.Transaction.RollBack(lHandle);
10 end;
11 end;
2. 立即事务与非立即事务
- 立即事务是在启动事务同时,数据库的事务也随之启动,直到该立即事务最后一次被提交或回滚,才结束数据库的事务;
- 非立即事务是启动事务后,数据库的事务并不立即启动,从该事务启动到提交前的所有操作都保存到业务服务器中,直到最后一次被提交时,才真正启动数据库的事务并执行提交操作。
- 一般推荐使用非立即事务,这样可以减少服务器上的等待时间,减少死锁的机会。如果需要在事务中修改表的值,而且在事务中用到刚才修改的内容,就需要用立即事务了。
- 使用立即事务,需要在启动事务和提交事务直接用时非常的短,一般不要超过2秒,中间肯定不应该有:
ShowMessage显示信息给客户
- 等待客户输入信息
- 在事务中尽量使访问的数据量最小,这样可以减少锁定的行数,从而减少事务之间的争夺。
2.1. 相关属性和方法
function Start(AImmediate: Boolean): TTransactionHandle;
启动事务- 参数AImmediate=True为立即事务
- 参数AImmediate=False为非立即事务
2.2. 用法示例
- 立即事务
1 var 2 lHandle: TTransactionHandle; 3 begin 4 lHandle := DataSet.Connection.Transaction.Start(True); 5 try 6 //...在这里可以访问到事务中间修改的数据库的值,例如数据库中定义了触发器等等. 7 DataSet.Connection.Transaction.Commit(lHandle); 8 except 9 DataSet.Connection.Transaction.RollBack(lHandle); 10 end; 11 end;
- 非立即事务
1 var 2 lHandle: TTransactionHandle; 3 begin 4 lHandle := DataSet.Connection.Transaction.Start(False); 5 try 6 //...在这里不能访问事务中间修改的数据库的值. 7 DataSet.Connection.Transaction.Commit(lHandle); 8 except 9 DataSet.Connection.Transaction.RollBack(lHandle); 10 end; 11 end;
3. 数据集、数据连接与事务
- 一个事务中,可以有多个数据连接
- 一个数据连接中,可以有多个数据集
- 不同的数据库,他们的数据连接不同,只要定义事务是同一个就可以保证在同一个事务中
- 同一个数据连接的多个数据集,在同一个事务中
- 只要多个数据集对应同一个事务,或者对应同一个数据连接,那么就可以在一个事务中提交
3.1. 用法示例
- 设置连接同一个数据库的数据集在同一个事务中(其实设置它的数据连接)
1 DataSet2.Connection := DataSet1.Connection;
- 设置连接同一个数据库的数据集在同一个事务中(其实设置它的数据连接)
1 DataSet3.Connection.Transaction := DataSet1.Connection.Transaction;
- 多个数据集的设置
1 DataSet2.Connection := DataSet1.Connection;
2 DataSet3.Connection.Transaction := DataSet1.Connection.Transaction;
4. 平台上各个数据集所在的事务
- 同一个信息中的数据集在同一个事务中
- 不同信息的数据集不在同一个事务中,需要自己代码中修改数据集所在的事务才可以保证不在同一个信息中的多个数据集的数据一致性
- 窗体上定义的数据集不在同一个事务中
主从关系的数据集不需要显式的启动事务,默认就是在一个事务中提交的(调用主从关系中任何一个数据集的ApplyUpdates(True))
5. 业务数据与流程数据的一致性
流程中,默认业务数据和流程数据是在同一个事务中,可以保证业务数据与流程数据的一致。只要在流程事件中对业务数据修改,不需要主动的启动和提交事务,这些事务的控制是由平台来完成的
5.1. 用法示例
在流程成功后,修改数据记录的状态
1 procedure FlowBroker1AfterFlowOut(Sender: TObject; Command: TFlowOutCommand);
2 begin
3 //直接修改字段的值,不需要启动和提交事务.
4 DataSetBroker1.DataSet.Edit;
5 DataSetBroker1.DataSet.FieldByName('ZT').AsString := 'F';
6 DataSetBroker1.DataSet.Post;
7 DataSetBroker1.DataSet.ApplyUpdates;
8 end;
[[PageComment2()]]