这不是关于资源事务算法(实现)的文章,只是研究资源事务协作过程中,各种资源如何参与事务的(这是借用artech关于事务的文章,不过这里主要还是指数据库)。这里稍微提一下,可能一个业务的完成,需要多个资源或者服务的协作,但是任何服务到达底层依然无外乎资源的访问,这是一个树形结构,而根节点即是业务发起者,所以下面谈到参与者的时候一般泛指资源参与事务。
对于单个资源,事务控制可以显式调用类似BeginTransaction开始事务,然后提交或者回滚;但是如果需要多个资源,他们每个都有自己的资源管理方式和事务控制方式,怎样让他们协作,类似于一个资源一样完整的完成一项业务呢。这里需要单独提出事务管理器概念,从artech文章可以看到,事务管理器负责协调资源以便提供事务支持,但是事务管理器只是使用资源相应的资源管理器来协调资源,而真正实现事务操作或者事务算法的实现都是依赖资源自身的构造。
在这里,自己的理解有些模棱两可。事务管理器的概念问题,因为每个资源都有自己一套事务管理的方式,了解数据库的人都知道,数据库本身都提供事务支持,也就是说资源管理器本身就具备事务管理能力。而且事务本身就是资源管理器的一部分。自己觉得这里提到的事务管理器是一个纯粹的事务协调控制器,即他会协调那些能够提供事务支持的资源以便在业务层面上提供事务支持,但是他不会具体管理资源本身的事务,而且使用每个资源提供的相应的事务控制方式来完成整体性事务。所以本文接下来提到的事务管理器更多的是指高层次的事务协调控制器。
对于单个资源的访问操作,使用资源管理器的事务控制能力基本可以胜任。从数据库里面可以明显的看到。对于多个资源的访问操作,就没那么简单了。首先其中的任何一个资源的访问操作(下面简称参与者),他在进入操作之前,会检查上下文中是否存在上下文事务,如果存在,即把资源相应的资源管理器注册到当前上下文里面,然后继续操作。这个过程中,任何参与者的提交和回滚都会影响到当前上下文事务的其他参与者,保证要不全部提交,要不全部回滚,具体的提交机制可能略有不同,这个可以参照artech为博客文章。
上面提到事务参与者在操作之前都会检查当前上下文事务,然后决定是否需要把自己的资源管理器注册到上下文事务当中。检查当前上下文事务容易,在C#里面,Transaction.Current即是当前上下文事务。至于注册资源管理器,Transaction.Current对于不同的资源管理器提供三个不同的注册函数,
EnlistDurable
|
登记持久资源管理器以参与事务。
|
EnlistPromotableSinglePhase
|
使用可提升的单阶段登记 (PSPE) 登记具有内部事务的资源管理器。
|
EnlistVolatile
|
登记可变资源管理器以参与事务。
|
这里注册的资源管理器实际只是实现事务管理器相应的接口的类,具体的实现可以从函数的参数里面发现。从开源的sqlite和postsql的.net驱动里面可以看到,在打开连接时,他们即会完成这个操作,即检查上下文事务,然后注册相应的资源管理器。Sqlite的操作比较简单,postsql的略微复杂。从测试来看,sql server和oracle基本也是打开连接时进行这一个操作。
using (DbConnection con = factory.CreateConnection())
{
con.ConnectionString = connectionString;
con.Open();
using (TransactionScope scope = new TransactionScope())
{
using (DbCommand com = con.CreateCommand())
{
com.CommandText = "update t_tick set tick=111";
com.ExecuteNonQuery();
throw new ArgumentException("测试");
com.CommandText = "update t_tick set tick=222";
com.ExecuteNonQuery();
}
scope.Complete();
}
con.Close();
}
数据库原始值为0,而上面的代码测试结果是111不是0。
因为sqlite的实现资源管理器接口的类相对比较容易简单,先来看看他的实现,在连接打开函数Open里面有如下代码
if (Transactions.Transaction.Current != null && SQLiteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString)) == true)
EnlistTransaction(Transactions.Transaction.Current);
而EnlistTransaction函数最重要的就是初始化SQLiteEnlistment,一个资源管理器接口(IEnlistmentNotification)实现类。在他的构造函数里面,他调用连接启动数据库事务,然后在提交和回滚里面嗲用数据库事务的提交和回滚。这是最简单的实现。在以前讨论Rhinio.Queues队列时,也有过类似的事务实现想法,现在看来似乎当时太激进了。但是毕竟这是纯粹的数据库事务,直接使用资源本身的事务实现未尝不可。代码不多,干脆这里附上:
namespace System.Data.SQLite
{
using System;
using System.Data;
using System.Data.Common;
using System.Transactions;
internal class SQLiteEnlistment : IEnlistmentNotification
{
internal SQLiteTransaction _transaction;
internal Transaction _scope;
internal bool _disposeConnection;
internal SQLiteEnlistment(SQLiteConnection cnn, Transaction scope)
{
_transaction = cnn.BeginTransaction();
_scope = scope;
_scope.EnlistVolatile(this, System.Transactions.EnlistmentOptions.None);
}
private void Cleanup(SQLiteConnection cnn)
{
if (_disposeConnection)
cnn.Dispose();
_transaction = null;
_scope = null;
}
#region IEnlistmentNotification Members
public void Commit(Enlistment enlistment)
{
SQLiteConnection cnn = _transaction.Connection;
cnn._enlistment = null;
try
{
_transaction.IsValid(true);
_transaction.Connection._transactionLevel = 1;
_transaction.Commit();
enlistment.Done();
}
finally
{
Cleanup(cnn);
}
}
public void InDoubt(Enlistment enlistment)
{
enlistment.Done();
}
public void Prepare(PreparingEnlistment preparingEnlistment)
{
if (_transaction.IsValid(false) == false)
preparingEnlistment.ForceRollback();
else
preparingEnlistment.Prepared();
}
public void Rollback(Enlistment enlistment)
{
SQLiteConnection cnn = _transaction.Connection;
cnn._enlistment = null;
try
{
_transaction.Rollback();
enlistment.Done();
}
finally
{
Cleanup(cnn);
}
}
#endregion
}
}
至于sqlite的数据库事务实现,即DbTransaction的实现,相对简单得多,即在响应的函数里面执行sqlite的事务开始、提交、回滚命令。这个跟postsql基本没有太大的出入,postsql的数据库事务的实现基本也是执行数据库响应的命令来实现。
对于postsql的相应的驱动实现,比这个复杂。他调用的是EnlistPromotableSinglePhase函数,实现的是可提升的单阶段登记 (PSPE) 登记具有内部事务的资源管理器。目前对于PSPE在postsql中的实现不是很了解。
待续。。。
引用
System.Data.SQLite (http://sqlite.phxsoftware.com/)
实现资源管理器(http://msdn.microsoft.com/zh-cn/library/ms229975%28v=VS.90%29.aspx)
分享到:
相关推荐
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在...
为了实现分布式事务,需要使用下面将介绍的两阶段提交协议。 * 阶段一:开始向事务涉及到的全部资源发送提交前信息。...这就要求不同开发商开发的事务参与者必须支持一种标准协议,才能实现分布式的事务。
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于...
第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;第二阶段是执行阶段,协调者根据所有参与者的反馈,通知所有参与者,步调一致地在所有分支上提交或者回滚。 3.2 TCC方案 TCC方案在电商、...
【妇联组织应参与公共事务管理打造公共服务产品】管理公共事务的组织有哪些.docx
SARS参与活动指引-香港红十字会青年及义工事务部.docx
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统 的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上, 且属于...
同步阻塞、单点问题、脑裂、太过保守缺点原理简单,实现方便优点优缺点参与者协调者角色执行事务提交提交事务请求操作步骤Saga事务MQ事务数据不一致缺点降低参与者阻
当执行完关闭事务组的方法以后,TxManager将根据事务组信息来通知相应的参与模块提交或回滚事务。 事务控制原理 LCN事务控制原理是由事务模块TxClient下的代理连接池与TxManager的协调配合完成的事务协调控制。...
论会计师事务所担任破产管理人的优劣势.pdf
若要提交事务,所有参与者都必须保证对数据的任何更改是永久的。不论系统崩溃或是发生其他无法预料的事件,更改都须是持久的。只要有一个参与者无法做出此保证,整个事务就会失败。事务范围内的所有数据更改将回滚到...
2 两阶段提交在分布式系统中,事务往往包含有多个参与者的活动,单个参与者上的活动是能够保证原子性的,而多个参与者之间原子性的保证则需要通过两阶段提交来实现,两阶
对高校后勤服务部门的工作实现流程化管理,系统在用户登录之前首先将选择用户类型进行...-用户可以在系统中观察并参与事务流程, 提出问题和要求。 -管理员及工作人员按事务流程解决问题,对用户提出的问题进行 解答。
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于...
挪威国际事务研究所 这场大流行是对中亚外部势力参与的试金石(英文)2021.4(19页).pdf
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上
Neo4j-REST-API 的事务参与 这是一个 Neo4j 服务器扩展,使参与由启动的。 为什么我需要它? Neo4j 服务器的许多操作目前无法使用 Cypher 完成,但作为 REST-API 端点公开。 尤其是使用、和。 当 Cypher 端点启动...
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于...
ERP系统信息化资料:ERP_功能需求_事务对话_SD_促销折扣价不参与返利及返利计提公式_SD027_20170731_V2.3.docx