`
tyny
  • 浏览: 75619 次
  • 性别: Icon_minigender_1
  • 来自: 黄冈
社区版块
存档分类
最新评论

事务参与1

 
阅读更多

    这不是关于资源事务算法(实现)的文章,只是研究资源事务协作过程中,各种资源如何参与事务的(这是借用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

 

分享到:
评论

相关推荐

    深入理解分布式事务,高并发下分布式事务的解决方案

    分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在...

    分布式事务之2PC事务处理原理

    2PC(两阶段提交)是一种经典的分布式事务处理算法,它试图通过协调参与者的操作来实现全局的一致性。 **两阶段提交(2PC)的工作原理** 1. **准备阶段(投票阶段)**: 在这个阶段,事务协调者(通常是应用...

    java分布式事务demo

    1. **JTA(Java Transaction API)**:这是Java平台的标准API,用于管理全局事务,可以跨越多个资源管理器(如数据库和消息队列)。JTA包括三个主要组件:JTAS(Java Transaction Service),定义了事务管理器接口;...

    java事务管理和事务分类

    1. **原子性**:事务中的每个操作要么全部完成,要么全部不完成。如果在事务执行过程中发生错误,所有已完成的操作都会被回滚,确保数据库状态不变。 2. **一致性**:事务结束后,数据库必须处于一致状态,即事务...

    Java事务设计模式_java_事务设计模式_

    1. **本地事务模型**:这是最基础的事务管理方式,通常在单个数据库连接上进行。开发者需要手动开启和提交事务,如果发生异常则需要回滚。例如,使用JDBC的Connection对象的commit()和rollback()方法。 2. **编程式...

    EJB与事务 -详细描述EJB和事务

    1. NotSupported:在这种情况下,EJB方法不参与任何事务,即使调用者有事务,也会在调用EJB方法时被挂起。 2. Required:如果调用者有事务,EJB方法将加入该事务;如果没有,容器会为EJB方法开启一个新的事务。 3....

    [[分布式事务]]支付宝分布式事务设计草案.doc

    X/Open模型是分布式事务处理的标准化框架,定义了TX和XA接口,分别用于应用程序与事务管理器交互,以及事务管理器控制资源管理器(如数据库)的事务参与。然而,X/Open模型在面对复杂的SOA环境和异常恢复时可能存在...

    深入理解分布式事务

    在这样的场景下,事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。例如,一个电子商务平台可能会涉及订单系统、库存系统和支付系统等多个服务,这些服务通常部署...

    DRDS跨库事务文档

    XA事务通过一个全局事务管理器来协调各个参与的数据库资源,确保所有资源要么全部提交成功,要么全部回滚,从而保证数据的一致性。 在XA事务中,DRDS充当全局事务管理器的角色,管理不同数据库实例上的本地事务。一...

    会员版分布式事务.rar

    为了实现分布式事务,需要使用下面将介绍的两阶段提交协议。 * 阶段一:开始向事务涉及到的全部资源发送提交前信息。...这就要求不同开发商开发的事务参与者必须支持一种标准协议,才能实现分布式的事务。

    分布式事务源代码

    1. **两阶段提交(2PC, Two-Phase Commit)**:这是最基础的分布式事务协议,包括准备阶段和提交阶段。在准备阶段,事务协调者询问所有参与者是否可以提交,参与者根据自身情况返回结果;在提交阶段,协调者根据准备...

    ejb3.0 分布式事务

    1. **ejb3.0 的事务管理** EJB3.0中,事务管理分为容器管理的事务(CMT, Container-Managed Transactions)和 bean 管理的事务(BMT, Bean-Managed Transactions)。CMT是默认模式,由容器自动管理事务的开始、...

    spring事务的传播特性和事务隔离级别

    这意味着如果方法被事务性方法调用,它将参与该事务;如果是独立调用,则将启动自己的事务。 2. **PROPAGATION_SUPPORTS** - 如果当前存在事务,则支持并参与该事务;如果没有,则以非事务的方式执行。这适用于...

    Java事务处理总结

    这些接口使JDBC连接能够参与JTA事务。 JTA事务的主要特点是支持跨多个资源的事务处理。这使得开发者能够在不同的数据库或其他资源间进行数据操作时,保证数据的一致性和完整性。 ##### 3. 容器事务 容器事务是...

    分布式事务详细介绍

    1. **一致性保证**:在分布式事务中,需要确保多个参与方的操作要么全部成功,要么全部失败。这通常通过两阶段提交协议(2PC)、三阶段提交协议(3PC)或其他一致性协议来实现。 2. **通信故障**:分布式系统中可能...

    JDBC事务和JTA(XA)事务

    在JTA事务中,事务管理器负责协调所有事务参与者之间的通信,资源管理器负责管理资源,例如数据库连接池。 JTA事务的优点是可以管理分布式事务,确保分布式事务的一致性和可靠性,但是,它的系统开销相对较大,因此...

    分布式事务.zip

    主要由四个组件构成:TC(Transaction Coordinator,事务协调者)、TM(Transaction Manager,事务管理器)、TCC(Try Confirm Cancel,尝试、确认、取消模式)、TM(Transaction Manager,事务参与者)。...

    跨库事务工具类

    在准备阶段,事务协调者询问所有参与者是否可以提交,如果所有参与者都同意,则进入提交阶段,否则回滚。但2PC存在性能瓶颈和单点故障问题。 2. **补偿事务(Compensating Transaction, CT)**:通过记录每个操作的...

Global site tag (gtag.js) - Google Analytics