首先介绍一下事务处理的过程:
1. 开始一个事务。进入“事务待命”状态。
2. 在“事务待命”状态,记录事务中改变的数据库记录。此改变不能直接改变数据库中的值,必须先用一个顺序
的“事务日志”记录在一边。同时,对于要改变的原始记录加锁,让其它用户无法读和写。如果记录已经被其
它事务加锁,则报错。
3. 在“事务待命”,如果用户给出commit transaction命令,则进入“事务拷贝”状态,拷贝所有加锁的记录成备
份。
4. 上面3执行完,则进入“事务更新”状态,用“事务日志”中记录一一更新实际的数据库记录。
5. 上面4执行完,则进入“事务结束”状态,释放所有的记录锁,然后抛弃“事务日志”和备份的原数据库记录。
6. 上面5做完后,事务被删除
但是,最为关键的是,事务系统必须执行以下过程:一但数据库由于软件、硬件问题发生故障,重启动后,一旦有事务没正常删除,则:
– 7. 如果在“事务待命”、“事务结束”状态,则重新从5中结束事务的动作开始执行。
– 8. 如果在“事务更新”状态,则重新从4开始更新记录,并继续想下执行。结果,虽然系统崩溃过,但事务仍然能正常提交。
事务处理有关事项
• 事务处理的关键是在提交事务或者取消事务时,万一系统崩溃了,数据库在再次启动时,仍然需要保持数据可逻辑一致性。
• 应用中包含的事务应当尽量让它“瞬间”完成,避免在比较忙时造成用户进程的互锁。
• Informix、Oracle、DB2等数据库的实际事务处理流程更复杂,目的是具有更好的抵抗系统错误性质,因为事务保护是业务系统安全稳定的最后一道防线。
事务处理方法分为三种:
• 直接写入SQL
• 通过ADO.NET实现
• COM+事务(分布式事务)
• 直接写入SQL
在存储过程中使用BEGIN TRAN,
COMMIT TRAN, ROLLBACK TRAN实现
• 优点:
– 所有事务逻辑包含在一个单独的调用中
–拥有运行一个事务的最佳性能
– 独立于应用程序
• 限制:
–事务上下文仅存在于数据库调用中
–数据库代码与数据库系统有关
• 通过ADO.NET实现
在ADO.NET 中,可以使用Connection 和Transaction 对象来控制事务。若要执行事务,请执行下列操作:
• 调用Connection 对象的BeginTransaction 方法来标记事务的开始。
• 将Transaction 对象分配给要执行的Command的Transaction 属性。
• 执行所需的命令。
• 调用Transaction 对象的Commit 方法来完成事务,或调用Rollback 方法来取消事务。
优点:
–简单性
–和数据据事务差不多的快
–独立于数据库,不同数据库的专有代码被隐藏
了
• 缺点:
–事务不能跨越多个数据库连接
–事务执行在数据库连接层上,所以需要在事务
过程中维护一个数据库连接
myConnection.Open();
// 启动一个事务
SqlTransaction myTrans = myConnection.BeginTransaction();
// 为事务创建一个命令
SqlCommand myCommand = new SqlCommand();
myCommand.Connection = myConnection;
myCommand.Transaction = myTrans;
try
{
myCommand.CommandText = " Insert into Region (RegionID, RegionDescription) VALUES (110, 'Description') " ;
myCommand.ExecuteNonQuery();
// myTrans.Commit();
myCommand.CommandText = " Insert into Region (RegionID, RegionDescription) VALUES (111, 'Description') " ;
myCommand.ExecuteNonQuery();
myTrans.Commit();
Response.Write( " 成功写入记录! " );
}
catch (Exception Ex)
{
myTrans.Rollback();
Response.Write(Ex.ToString());
Response.Write( " 写入数据库失败! " );
}
finally
{
myConnection.Close();
}
• COM+事务(分布式事务)
一般的数据库事务控制要求事务里所做的操作必须在同一个数据库内,这样在出现错误的时候才能回(RllBack)到初始状态。这就存在一个问题,在分布式应用程序中,我们往往需要同时操作多个数据库,使用数据库本身的事务处理,很难满足程序对事务控制的要求。在COM+中,提供了完整的事务服务,我们可以利用它来完成在分布式应用程序中的事务控制。
创建参与自动事务的类的步骤:
1. 将TransactionAttribute 类应用于您的类,指定组件请求的自动事务类型。事务类型必须是TransactionOption 枚举的成员。
2. 从ServicedComponent 类派生您的类。ServicedComponent 是所有使用COM+ 服务的类的基类。
3. 用强名称(strong name) 标记(sign) 程序集(assembly),确保程序集包含唯一的密钥对。
4. 在COM+ catalog 中注册包含您的类的程序集。
• 定义一个COM+事务处理的类
[Transaction(TransactionOption.Required)]
public class DataAccess:System.EnterpriseServices.ServicedComponent
{
}
• TransactionOption枚举类型支持5个COM+值
– Disabled 忽略当前上下文中的任何事务。
– NotSupported 使用非受控事务在上下文中创建组件。
– Required 如果事务存在则共享事务,并且如有必要则创建新事务。
– RequiresNew 使用新事务创建组件,而与当前上下文的状态无关。
– Supported 如果事务存在,则共享该事务。
强名称
• 确保使用COM+ 服务的所有项目都有一个强名称。
• 使用COM+ 服务的所有类都必须继承服务组件。服务组件位于System.EnterpriseServices 命名空间中。
• 进行调试时,事务在提交或终止前可能会超时。要避免出现超时,请在事务属性中使用一个超时属性。在下面的示例中,在完成任何事务时,关联的方法在超时前都有1,200 秒的执行时间。
[Transaction(TransactionOption.Required,timeout:=1200)]