背景:

背景:

有关分布式事务的3个误解:使用了TransactionScope就一定会打开分布式事务吗?,

背景:

     
事务是数据库管理类别的3个基本概念,事务有着七个为主性格,即ACID:原子性(Atomicity)、一致性(Consistency)、隔开性(Isolation)和持久性(Durability),通过作业机制能够保险数据库的壹致性和完整性。

     
可是数据库事务只可以在数据库实例的同多个对话级别举办工作控制。而分布式事务能够协调二个数据库实例五个会话之间的操作,甚至是几个数据库实例之间的数据库操作,并有限支撑工作脾性。可是规格上我们不推荐应用分布式事务,因为分布式事务对财富消耗较多,执行作用较差。

     
然则直接以来,我们对分布式事务的代码应用和功能都留存误解:使用了TransactionScope就自然会敞开分布式事务吗?

 

验证:

     
我们做二个回顾的德姆o:八个三番五次字符串完全相同,ADO.NET会复用连接池中的连接,结果会怎么?

    using (TransactionScope ts = new TransactionScope())
    {
        SqlConnection conn;
        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");

        conn.Open();
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "select 1 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");
        conn.Open();
        cmd = conn.CreateCommand();
        cmd.CommandText = "select 2 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        ts.Complete();
    }

    Console.WriteLine("OK");
    Console.ReadKey();

 

不料的事体产生了,并不曾观看我们的觉得的分布式事务!!!

using (TransactionScope ts = new TransactionScope()) { SqlConnection
conn; conn = new SqlConnection(“server=.;uid=tkk123;pwd=aaaaaa”);
conn.Open(); SqlCommand cmd = conn.CreateCommand(); cmd.CommandText =
“select 1 as tkk”; cmd.ExecuteNonQuery(); conn.Close(); conn = new
SqlConnection(“server=.;uid=tkk123;pwd=aaaaaa;”);
–加了八个分公司,不共享连接 conn.Open(); cmd = conn.CreateCommand();
cmd.CommandText = “select 二 as tkk”; cmd.ExecuteNonQuery();
conn.Close(); ts.Complete(); } Console.WriteLine(“OK”);
Console.ReadKey();

 

让大家看一下分布式事务是什么样协调各个数据库连接,当前的案例大家使用的是同三个数据库,所以固然创造了五个数据库连接,但最终在数据库层面依旧是同1业务ID。

一经大家开辟的是三个不等数据库实例,将会看到怎么着的结果吗? try
it。。。

金沙注册送58 1

SOA供给怎么样的工作控制措施,关于分布式事务的三个误解。
背景: 事务是数据库管理类别的三个基本概念,事务有着…

在二个基于SOA架构的分布式系统连串中,服务(瑟维斯)成为了基本的功能提供单元,无论与事务流程非亲非故的基础意义,如故实际的作业逻辑,均完成在相应的服务内部。服务对外提供联合的接口,服务时期利用标准的通讯方式举行互相,各样单一的服务精又实用的结合、编排成为三个有机的共同体。在这么3个分布式系统中有些活动(Activity)的兑现多次须求跨越单个服务的界线,如何协调八个劳务中间的涉嫌使之为活动功效的达成服务,涉及到SOA三个重要的课题:服务同盟(ServiceCoordination)。而具体来讲,二个分布式的位移恐怕会执行几分钟,比如银行转帐;也说不定实施几分钟、多少个小时、几天甚至越来越长,比如移民局处理移民的报名。事务,无疑是属于短暂运转服务同盟(Short-Running
Service Coordination)的框框。

     
事务是数据库管理种类的三个基本概念,事务有着两在那之中心特征,即ACID:原子性(Atomicity)、1致性(Consistency)、隔绝性(Isolation)和持久性(Durability),通过业务机制能够有限支撑数据库的1致性和完整性。

     
事务是数据库管理类其他3个基本概念,事务有着四个基本特点,即ACID:原子性(Atomicity)、一致性(Consistency)、隔断性(Isolation)和持久性(Durability),通过业务机制得以确认保障数据库的一致性和完整性。

1、 什么是工作(Transaction)

业务提供1种机制将二个运动关系的有着操作纳入到三个不可分割的实施单元,组成工作的兼具操作只有在颇具操作均能平常履行的景况下方能交付,只要个中任壹操作实践破产,都将招致整个事情的回滚。简单地说,事务提供1种“要么什么都不做,要么做任何(All
or
Nothing)”机制。事务有着如下三个特性,依据其首字母,大家1般将其称作事务的ACID四大属性:

  • 原子性(Atomicity):“原子”这些词的本义正是不可分割的情致,事务的原子性的意义是:二个作业的保有操作被松绑成三个1体化,全数的操作还是全部履行,要么都不执行;
  • 一致性(Consistence):业务的原子性确定保障2个业务不会破环数据的1致性,假设事情成功交付,数据的情景是组成工作的装有操作根据优先编排的措施实施的结果,数据状态有所一致性;要是工作任何二个中等步骤出错,整个业务回滚并将数据恢复生机到原来的景观,数据状态依然具备壹致性。所以,事务只会将数据状态从1个1致性状态转换成另四个一致性状态;
  • 隔离性(Isolation):从业务的外表来看,事务的壹致性完结了数码在七个一致性状态之间的更换,可是从工作内部来看,组成工作的壹一操作是依照一定的逻辑顺序执行的,所以数据颇具位于五个一致性状态的“中间状态”。不过,那种中间状态被割裂于业务内部,对于工作外部是不可知的;
  • 持久性(Durability):持久性的趣味是假诺得逞交付,基于持久化能源(比如数据库)的多上将会被持久化,对数据的更改是永久性的。

事情最初源于数据库管理种类(DBMS),反映的是对存款和储蓄于数据库中的数据操作。除了主流的关系型数据库管理体系,比如SQL
Server,Oracle和DB二等提供对事情的支持,基于事务的数量操作形式也能够应用到别的一些数额存款和储蓄财富,比如MSMQ。自Windows
Vista伊始将文件系统(NTFS)以至于注册表纳入了事务型财富(Transactional
Resource)的层面。

     
可是数据库事务只可以在数据库实例的同2个会话级别实行工作控制。而分布式事务能够协调一个数据库实例八个会话之间的操作,甚至是两个数据库实例之间的数据库操作,并保持业务本性。不过规格上大家不推荐使用分布式事务,因为分布式事务对能源消耗较多,执行成效较差。

     
但是数据库事务只可以在数据库实例的同二个会话级别实行工作控制。而分布式事务能够协调1个数据库实例八个会话之间的操作,甚至是多少个数据库实例之间的数据库操作,并保持业务个性。然而规格上大家不推荐使用分布式事务,因为分布式事务对财富消耗较多,执行作用较差。

2、 事务的显式控制

就算如此事务型财富家族成员更多,不过不可不可以认的是,数据库依然大家利用作用最高的事务型能源。对于某个有早晚经验的开发职员,应该都在存款和储蓄进度(Stored
Procedure)中编辑过基于事务的SQL,或许编写过基于ADO.NET事务的代码,对工作的特别介绍就从那边谈起。

1、SQL中的事务处理

任由基于SQL
Server的T-SQL,抑或是依据Oracle的PL-SQL都对作业提供了原生的支撑,有意思的是T-SQL中的T本身指的便是业务(Transaction)。以T-SQL为例,大家得以由此如下四个SQL语句完成工作的开发银行、提交与回滚:

  • BEGIN TRANSACTION: 开端二个事务;
  • COMMIT TRANSACTION:付给全部位于BEGIN TRANSACTION和COMMIT
    TRANSACTION之间的操作;
  • ROLLBACK TRANSACTION:回滚全体位于BEGIN TRANSACTION和COMMIT
    TRANSACTION之间的操作。

咱俩举一个很卓绝的依照事务型操作的事例:银行转帐,而且以此例子将会贯通于本章的始终。为此,大家先创制三个Infiniti简练的用来存储帐户的数据表:T_ACCOUNT,整个表近仅仅包罗七个字段(ID、NAME和BALANCE),它们分别表示银行帐号的ID、名称和余额。创立该表的T-SQL如下:

   1: CREATE TABLE [dbo].[T_ACCOUNT](

   2:     [ID]        VARCHAR(50)     PRIMARY KEY,

   3:     [NAME]      NVARCHAR(50)    NOT NULL,

   4:     [BALANCE]   FLOAT           NOT NULL)

   5: GO

银行转帐是一个简单的复合型操作,由三个基本的操作结合:存款和储蓄和领取,即从2个帐户中提取相应金额出入另1个帐户。对数据完整性的渴求是我们务必将那五个单纯的操作纳入同二个工作。即使大家因而1个存款和储蓄进程来成功全体转帐的流水生产线,具体的SQL应该使用上边包车型客车写法:

   1: CREATE Procedure P_TRANSFER

   2:     (

   3:         @fromAccount    VARCHAR(50),

   4:         @toAccount      VARCHAR(50),

   5:         @amount         FLOAT

   6:     )

   7: AS

   8:  

   9: --确保帐户存在性

  10: IF NOT EXISTS(SELECT * FROM [dbo].[T_ACCOUNT] WHERE ID = @fromAccount)

  11:     BEGIN

  12:         RAISERROR ('AccountNotExists',16,1) 

  13:         RETURN

  14:     END    

  15: IF NOT EXISTS(SELECT * FROM [dbo].[T_ACCOUNT] WHERE ID = @toAccount)

  16:     BEGIN

  17:         RAISERROR ('AccountNotExists',16,1) 

  18:         RETURN

  19:     END

  20: --确保余额充足性

  21: IF NOT EXISTS(SELECT * FROM [dbo].[T_ACCOUNT] WHERE ID = @fromAccount AND BALANCE >= @amount)

  22:     BEGIN

  23:         RAISERROR ('LackofBalance',16,1)

  24:         RETURN

  25:     END

  26: --转帐

  27: BEGIN TRANSACTION

  28:     UPDATE     [dbo].[T_ACCOUNT] SET BALANCE = BALANCE - @amount WHERE ID = @fromAccount

  29:     IF @@ERROR <> 0 

  30:         BEGIN

  31:             ROLLBACK TRANSACTION

  32:         END

  33:     UPDATE     [dbo].[T_ACCOUNT] SET BALANCE = BALANCE + @amount WHERE ID = @toAccount

  34:     IF @@ERROR <> 0 

  35:         BEGIN

  36:             ROLLBACK TRANSACTION

  37:         END

  38: COMMIT TRANSACTION

  39: GO

二、 ADO.NET事务控制

任由T-SQL,依然PL-SQL,抑或是其它数据库管理系统对标准SQL的扩大,不仅仅是提供基于专业SQL的DDL(Data
Definition Language)和DML(Data Manipulation
Language),还提供了对函数、存款和储蓄进程和流程序控制制的援助。SQL
Server至200伍起,甚至完结了与CLLacrosse(Common Language
Runtime)的并轨,使开发人士能够选择别的一种.NET语言编写编写函数也许存储进度。毫无夸张地说,你可以经过SQL实现其余事情逻辑。

不过,在大部景况我们并不那样做,大家越多地依然将SQL作为最核心的多少操作语言在动用。对于.NET开发者来说,大家仍然习惯将复杂的逻辑和流程序控制制实现在通过C#要么VB.NET那样的外貌对象编制程序语言编写的先后中。究其原因,笔者认为根本有两点:

  • 外貌对象的言语更能便于地实现复杂的逻辑:较之SQL那种依照集合记录的言语,面绝对象的言语更是接近于我们真正的世界,通过外貌对象的办法模拟具体的逻辑更是身入其境于人类的切磋方法。其余,通过面相对语言本人的有些表征,大家得以特别不难地利用各个设计格局和探讨;
  • 将太多逻辑运算的推行放在数据库中不方便人民群众应用的壮大:从下级的角度来讲,数据操作运算负载到现实的服务器中,以3个名列三甲的分布式Web应用为例,Web服务器(承载Web应用)、应用服务器(承载种种服务)和数据库服务器均可以承接最后对逻辑的运算。可是,从可扩大性(大概可伸缩性)上考虑,将首要的总结放在前两者比位居数据库更具优势。尽管大家将凝聚的演算(那种运算需求占用更加多的CPU时间和内部存储器)迁移到Web服务器也许应用服务器,大家得以因此负载均衡(Load
    Balance)将其疏散到多台服务器上边,那些服务器机群能够根据负荷情状展开动态地安顿。然则,数据库服务器对负荷均衡的援救就不那么简单。

正因为那样,对于工作的决定,较之采取SQL的兑现格局,大家选择得最多的要么采取基于面相对象语言编程的艺术。对于.NET开发人士,大家得以一向利用ADO.NET将依据单个数据库连接的四个操作纳入同一个业务之中。同样以地点的银行转帐事务为例,此次大家将1切转帐作为叁个服务(BankingService)的二个操作(Transfer)。上边包车型地铁代码通过①种与实际数据库类型无关的ADO.NET编制程序情势实现了总体银行转帐操作,最后的转帐通过调用1个仓库储存进度达成:

   1: public class BankingService : IBankingService

   2: {

   3:     //其他操作

   4:     public void Transfer(string fromAccountId, string toAccountId, double amount)

   5:     {

   6:         string connectionStringName = "BankingDb";

   7:         string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

   8:         string providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName;

   9:         DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory(providerName);

  10:         using (DbConnection connection = dbProviderFactory.CreateConnection())

  11:         {

  12:             connection.ConnectionString = connectionString;

  13:             DbCommand command = connection.CreateCommand();

  14:             command.CommandText = "P_TRANSFER";

  15:             command.CommandType = CommandType.StoredProcedure;

  16:  

  17:             DbParameter parameter = dbProviderFactory.CreateParameter();

  18:             parameter.ParameterName = BuildParameterName("fromAccount");

  19:             parameter.Value = fromAccountId;

  20:             command.Parameters.Add(parameter);

  21:  

  22:             parameter = dbProviderFactory.CreateParameter();

  23:             parameter.ParameterName = BuildParameterName("toAccount");

  24:             parameter.Value = toAccountId;

  25:             command.Parameters.Add(parameter);

  26:  

  27:             parameter = dbProviderFactory.CreateParameter();

  28:             parameter.ParameterName = BuildParameterName("amount");

  29:             parameter.Value = amount;

  30:             command.Parameters.Add(parameter);

  31:  

  32:             connection.Open();

  33:             using (DbTransaction transaction = connection.BeginTransaction())

  34:             {

  35:                 command.Transaction = transaction;

  36:                 try

  37:                 {

  38:                     command.ExecuteNonQuery();

  39:                     transaction.Commit();

  40:                 }

  41:                 catch

  42:                 {

  43:                     transaction.Rollback();

  44:                     throw;

  45:                 }

  46:             }

  47:         }

  48:     }

  49: }

注:为了使地方1段代码能够同时用于分化的数据库类型,比如SQL
Server和Oracle,笔者通过提取连接字符串配置中的数据库提供者(DbProvider)名称,借此创制相应的DbProviderFactory对象。全体ADO.NET对象,包含DbConnection、DbCommand、DbParameter以及DbTransaction均经过DbProviderFactory创立,所以并不和具体的数据库类型绑定在共同。其余,基于分化数据库类型的储存进度的参数命名各差别,比如
SQL
Server的参数会加上”@”前缀,为此作者将对参数名称的解析实以后一个独门的法子(BuildParameterName)之中。

叁、事务的显式控制范围于对单壹能源的走访

透过在SQL中开始展览作业的支配,只好将依照某一段SQL语句的操作纳入到1个单一的业务中;假使选取基于ADO.NET的数码控制,被纳入到同3个事情的操作仅仅限于有个别数据库连接。换句话说,上边介绍的这二种对工作的显式控制仅仅限于对单壹的本土财富的决定。

我们将工作的定义引进服务,若是大家将多少个纯粹的服务操作作为贰个业务,假设利用上述的显式事务控制的主意,那么万事服务操作只可以涉及一个单纯的作业能源。服务于存取的能源事关如图1所以。

金沙注册送58 2

图一 本地下工作作对单一能源的操纵

上述的那种依照有些服务单壹本地能源的走访的事务,被号称本地下工作作(Local
Transaction),在二个根据SOA分布式应用环境下,大家须求的还要能将多个能源、多少个服务开始展览统一合营的分布式事务(Distributed
Transaction)。接下来,大家来介绍三种典型的分布式事务应用的景色。

     
然则一直以来,大家对分布式事务的代码应用和机能都设有误解:使用了TransactionScope就肯定会敞开分布式事务吗?

     
不过一向以来,我们对分布式事务的代码应用和作用都存在误会:使用了TransactionScope就必将会张开分布式事务吗?

3、分布式事务(Distributed Transaction)应用场景

对此二个分布式事务(Distributed
Transaction)来讲,事务的参预者分布于网络环境中的差别的节点。也正是说,大家得以将八个工作能源纳入到一个10足的事体之中,并且那些事情财富能够分布到区别的机械上。那么些承载分布式资源的机器只怕是出于同二个互联网中,也大概处于分化的互连网中。甚至说,有个别事务财富本质上正是二个经过HTTP访问的无非的Internet财富。

站在SOA的角度来看分布式事务,意味着将劳动的有些服务操作视为二个单一的工作。该服务操作或许会造访不止一个业务财富(比如访问多少个区别的数据库服务器),也恐怕调用另多少个服务。下边介绍了八个独立的分布式事务应用场景,先从最简单易行的谈起。

一、将对四个能源的拜访纳入同1业务

率先个分布式事务应用场景最简便易行,即三个服务操作并不会调用另1个劳务,可是服务操作涉及到对多个工作能源的拜访。当一个服务操作访问分歧的数据库服务器,比如两台SQL
Server,只怕壹台SQL Server和壹台Oracle
Server;当3个劳动操作访问的是一样数据库,不过相应的数据库访问时根据分裂的数量连接;当叁个劳务操作处理访问数据库财富,还必要拜访别的份数据库的业务财富,就必要利用分布式事务来对富有的事情加入者举行同盟了。图2体现了这么的分布式应用场景。

金沙注册送58 3

图2 单一服务对多个业务财富的拜会

2、将对种种服务的调用纳入同壹业务

对此地方介绍的分布式应用场景,即便3个劳务操作会访问五个工作财富,但是毕竟整个工作如故决定在单纯的服务内部。假如2个劳务操作要求调用其它二个劳务,那是的事体就必要跨越多少个服务了。在那种景观下,初步于有些服务的工作在调用别的三个劳务的时候,供给以某种机制流转到此外多少个劳动,以使被调用的服务走访的能源自动进入进去。图3呈现了如此二个抢先八个劳务的分布式事务。

金沙注册送58 4金沙注册送58 , 图三跨越多个劳务的业务

三、 将对多少个能源和劳务的访问纳入同1个业务

万壹将方面那三种现象(3个劳动能够调用多少个业务财富,也得以调用别的服务)结合在联合,对此展开延伸,整个工作的参加者将会结合如图4所示的树形拓扑结构。在三个依据分布式事务的劳务调用中,事务的发起者和交给均系同三个,它能够是任何调用的客户端,也得以是客户端先河调用的可怜服务。

金沙注册送58 5 图4基于SOA分布式事务拓扑结构

比起基于单一财富访问的地头工作,分布式事务的贯彻机制要复杂得多。Windows平台提供了依照DTC分布式事务基础架构,下壹篇小说中自作者将对针对该框架结构模型详细介绍分布式事务时咋做事的。

 

分布式事务连串: 探究分布式事务之1:SOA供给哪些的事务控制方法
探讨分布式事务之二:基于DTC的分布式事务管理模型[上篇]
斟酌分布式事务之二:基于DTC的分布式事务管理模型[下篇]
议论分布式事务之3:
System.Transactions事务详解[上篇]
议论分布式事务之3:
System.Transactions事务详解[下篇]

作者:Artech出处:

 

 

验证:

验证:

     
我们做2个归纳的德姆o:四个延续字符串完全相同,ADO.NET会复用连接池中的连接,结果会怎么?

     
大家做一个简约的德姆o:七个延续字符串完全相同,ADO.NET会复用连接池中的连接,结果会怎么样?

    using (TransactionScope ts = new TransactionScope())
    {
        SqlConnection conn;
        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");

        conn.Open();
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "select 1 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");
        conn.Open();
        cmd = conn.CreateCommand();
        cmd.CommandText = "select 2 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        ts.Complete();
    }

    Console.WriteLine("OK");
    Console.ReadKey();
    using (TransactionScope ts = new TransactionScope())
    {
        SqlConnection conn;
        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");

        conn.Open();
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "select 1 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");
        conn.Open();
        cmd = conn.CreateCommand();
        cmd.CommandText = "select 2 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        ts.Complete();
    }

    Console.WriteLine("OK");
    Console.ReadKey();

 

 

殊不知的事情时有爆发了,并未观察大家的以为的分布式事务!!!

意料之外的作业时有发生了,并不曾观察我们的觉得的分布式事务!!!

金沙注册送58 6

金沙注册送58 7

 

 

咱俩转移内部的一个老是字符串,使得ADO.NET认为是三个数据源,这样才会真的含义上开启分布式事务。

大家改变内部的三个延续字符串,使得ADO.NET认为是多少个数据源,这样才会真正意义上打开分布式事务。

    using (TransactionScope ts = new TransactionScope())
    {
        SqlConnection conn;
        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");

        conn.Open();
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "select 1 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa;"); --加了一个分号,不共享连接
        conn.Open();
        cmd = conn.CreateCommand();
        cmd.CommandText = "select 2 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        ts.Complete();
    }

    Console.WriteLine("OK");
    Console.ReadKey();
    using (TransactionScope ts = new TransactionScope())
    {
        SqlConnection conn;
        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa");

        conn.Open();
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = "select 1 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        conn = new SqlConnection("server=.;uid=tkk123;pwd=aaaaaa;"); --加了一个分号,不共享连接
        conn.Open();
        cmd = conn.CreateCommand();
        cmd.CommandText = "select 2 as tkk";
        cmd.ExecuteNonQuery();
        conn.Close();

        ts.Complete();
    }

    Console.WriteLine("OK");
    Console.ReadKey();

 

 

让大家看一下分布式事务是怎样协调每一个数据库连接,当前的案例我们使用的是同二个数据库,所以即便成立了三个数据库连接,但最终在数据库层面照旧是同一业务ID。

让大家看一下分布式事务是怎么协调各类数据库连接,当前的案例大家利用的是同一个数据库,所以固然创立了多少个数据库连接,但最后在数据库层面依旧是如出壹辙业务ID。

万1大家开拓的是七个例外数据库实例,将会看到哪些的结果吧? try
it。。。

只要大家开辟的是多少个不相同数据库实例,将会看出什么样的结果吧? try
it。。。

金沙注册送58 8

金沙注册送58 9

相关文章

网站地图xml地图