关于使用Transaction对于非数据库事务的操作

在操作数据库的过程中,为了数据的一致性,我们可以使用Transaction,要么成功的时候全部提交,要么有任何一个操作失败立即全部回滚。不仅仅是在数据库方面,有时候操作其他的内容,比如说对于系统文件的操作,也需要把一些操作组合看做是一个事务。

现在我们看这样一个例子。现在我们需要在计算机的硬盘上创建3个目录A,B,C,要求要么3个全部创建成功,要么一个也不要创建。我们可以把这个看成是一个事务。如果我们自己写代码来操作,可以这样写。

            bool createA = false;
            bool createB = false;
            bool createC = false;

            try
            {
                //这里的操作是创建3个目录
                Directory.CreateDirectory("\\A");
                createA = true;
                Directory.CreateDirectory("\\B");
                createB = true;
                Directory.CreateDirectory("\\C");
                createC = true;
            }
            catch (System.Exception ex)
            {
                //这里在捕捉到异常时,根据运行的结果进行回滚
                if (createB)
                {
                    Directory.Delete("\\B");
                    Directory.Delete("\\A");
                }
                if (!createB && createA)
                {
                    Directory.Delete("\\A");
                }
            }

但是这里我们是把这3个操作当成一个整体来回滚,及时是简单的创建删除文件夹,我们可以看到catch中的回滚逻辑已经很复杂了。可以想象,如果A,B,C这3步不仅仅是创建目录,还有一些其他的操作,那么回滚的逻辑就非常复杂,此时,我们可以考虑把这一个分成几个小事务,分开回滚。代码可以这样写,这里我们使用了Framework提供的Transactin以及TransactioScope类。

class Program
    {
        static void Main(string[] args)
        {
            //这里就不需要了try catch,因为scope就已经完成了这个功能,
            //即当有异常发生向外抛的时候,会尝试跳出这个using代码块,
            //CLR会在向代码块外边跑异常之前,分别取调用每个transaction的
            //roolback方法,只要rollback中你定义的逻辑没有问题,那么所有
            //的已发生的操作就会安全的回滚。
            using (var scope = new TransactionScope())
            {
                var A = new OperationA();
                Transaction.Current.EnlistVolatile(A, EnlistmentOptions.None);
                A.DoWork();

                OperationB B = new OperationB();
                Transaction.Current.EnlistVolatile(B, EnlistmentOptions.None);
                B.DoWork();
                scope.Complete();
            }
        }

    }
}

class OperationA : IEnlistmentNotification
{
    private bool _isCommitSucceed = false;

    public void Commit(Enlistment enlistment)
    {
        enlistment.Done();
    }

    public void DoWork()//这是自定义的方法,不是继承IEnlistmentNotification
    {
        Directory.CreateDirectory("\\A");
        //这里还有一些其他的关于A的复杂操作
        _isCommitSucceed = true;
    }

    public void InDoubt(Enlistment enlistment)
    {
        enlistment.Done();
    }
    public void Prepare(PreparingEnlistment preparingEnlistment)
    {
        preparingEnlistment.Prepared();
    }
    public void Rollback(Enlistment enlistment)
    {
        //这里回滚A的一些操作,当然这里的操作逻辑需要你自己来写。
        //比如说查看是否创建成功,或者有一些其他的信号标记,通过这些
        //标记你来决定是删除目录还是其他的什么回滚操作。
        if (_isCommitSucceed)
            Directory.Delete("\\A");
        enlistment.Done();
    }
}

class OperationB : IEnlistmentNotification
{
    private bool _isCommitSucceed = false;

    public void Commit(Enlistment enlistment)
    {
        enlistment.Done();
    }

    public void DoWork()
    {
        //这里是关于B的一些复杂操作
        throw new Exception("test");
        //这里依然有一些操作代码,但是我们模拟的是B操作途中抛出异常,所以这里的代码不会执行
    }

    public void InDoubt(Enlistment enlistment)
    {
        enlistment.Done();
    }
    public void Prepare(PreparingEnlistment preparingEnlistment)
    {
        preparingEnlistment.Prepared();
    }
    public void Rollback(Enlistment enlistment)
    {
        if (_isCommitSucceed)
        {
            //这里回滚B的一些已经存在的操作。
        }
        enlistment.Done();
    }

这里的机制是这样的,可能是scope.Complete()方法中有某种特别的操作,去告诉CLR这次所有的操作都顺利完成了,在跳出这个scope的时候就不用调用那些transaction的rollback方法了。如果没有执行到scope.Complete()方法,那么就会在跳出这个scope代码块的时候调用rollback方法。一般造成这个的原因是在某个transaction的逻辑操作中出现异常,造成从此次直接抛出异常跳出这个代码块,没有机会执行下边的代码。可以看出这里的重点也是写rollback的逻辑,但是相对于原来的catch中的逻辑,这里分开为多个小的逻辑,相对来说容易了很多。

这只是个人写的一种使用回滚的逻辑。在使用IEnlistmentNotification的时候,也有人把业务逻辑写入到Commit中。如果想真正理解transaction回滚的机制,建议深入理解一下TransactionScope与Transactiond的实现机制。

关于使用Transaction对于非数据库事务的操作

时间: 2024-08-29 13:24:22

关于使用Transaction对于非数据库事务的操作的相关文章

JavaWeb中对数据库事务的操作

对于用JDBC操作数据库,使用Connection类的setAutoCommit(false)方法可以开启事务,用commit()方法可以提交事务. 由于三层架构的设计模型,事务的逻辑必须在service层,而dao层只是提供简单的CRUD操作,所以必须由service获取Connection并开启事务,将这个Connection传给dao层进行操作后,在service层将事务提交. 将Connection传给dao层可以在调用dao层方法(或构造函数)时以参数形式传入,但是这样不但会污染dao

如何将一个操作“绑定到数据库事务上”

摘要 spring-cache简介 基本机制 事务上下文中的问题 将操作绑定到数据库事务上 spring-cache的相关实现 TransactionSynchronizationManager和TransactionSynchronizationAdapter 事务相关操作注册与回调流程 其它应用 摘要 在开发中,我们常常会遇到(或者需要)把一些操作"绑定到数据库事务上".也就是说,如果数据库事务成功提交,则执行这个操作:如果数据库事务回滚,则不执行这个操作(或者执行另一个操作).

Mysq数据库事务的四大特性:

什么是事务? 事务Transaction,是指作为一个基本工作单元执行的一系列SQL语句的操作,要么完全地执行,要么完全地都不执行.为什么要使用事务:保证对数据操作的完整性和准确性.1,原子性:一个事务是一个一个不可分割的最小单位对数据库事务的操作要么完全的地执行,要么完全的不执行,不可能执行其中的一部分.(如:增删改一条数据,整个事务要么提交成功,要么失败回滚)2,一致性:指对数据库的操作不提交,所有的修改就不会保存到数据库.3,隔离性:每个事务在修改提交前,相对其他的事务都是不可见的.4,持

MySQL数据库事务隔离级别(Transaction Isolation Level)

今天在学习JDBC的时候看到了关于MySql的事务的隔离级别的问题,感觉内容挺高级的,所以记录一篇文章,以备后面使用. 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. 2 [mysqld] 3 transaction-isolation = R

数据库事务的四个基本特征以及事务的隔离级别

一.数据库事务的四个基本特征 事务是作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为 ACID(原子性.一致性.隔离性和持久性)属性,只有这样才能成为一个事务. 1.原子性(Atomicity):事务中包含的操作被看做一个逻辑单元,这个 逻辑单元中的操作要么全部成功,要么全部失败. 2.一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态. 拿转账来说,假设用户A和用户B两

数据库事务的四大特性以及事务的隔离级别

本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响. ⑵ 一致性(Consistency) 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执

数据库事务与隔离等级

事务(transaction)是数据库管理系统的执行单位,可以是一个数据库操作(如Select操作)或者是一组操作序列.事务ACID属性,即原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持久性(Durability). 原子性:保证事务中的所有操作全部执行或全部不执行.例如执行转账事务,要么转账成功,要么失败.成功,则金额从转出帐户转入到目的帐户,并且两个帐户金额将发生相应的变化:失败,则两个账户的金额都不变.不会出现转出帐户扣了钱,而目的帐户没有

数据库事务的四大特性及事务隔离级别

摘自:http://www.cnblogs.com/fjdingsd/p/5273008.html 本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响. ⑵ 一致性(Consi

数据库事务的四大特性和隔离级别

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么全部执行,要么全部都不执行. 一个逻辑工作单元要成为事务,必须满足事务的四大特性(ACID).即原子性(Atomic).一致性(Consistent).隔离性(Insulation)和持久性(Duraction). 原子性(Atomic):事务是一个完整的操作,事务的各个操作步骤是不可分的.即要么都执行,要么都不执行. 一致性(Consistent):事务执行的结果必须使数据库从一个一致性状态