议论分布式事务之1,关于分布式事务的一个误会

背景:

背景:

有关分布式事务的三个误解:使用了TransactionScope就必将会打开分布式事务吗?,

背景:

     
事务是数据库管理系列的三个基本概念,事务有着多个宗旨性格,即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 2 as tkk”; cmd.ExecuteNonQuery();
conn.Close(); ts.Complete(); } Console.WriteLine(“OK”);
Console.ReadKey();

 

让我们看一下分布式事务是怎么样协调每一种数据库连接,当前的案例我们采纳的是同一个数据库,所以即使创造了八个数据库连接,但聊起底在数据库层面依然是1模1样业务ID。

倘使我们打开的是多少个区别数据库实例,将会看出怎么着的结果吧? try
it。。。

美高梅开户网址 1

背景: 事务是数据库管理种类的2个基本概念,事务有着…

在二个根据SOA架构的分布式系统连串中,服务(Service)成为了骨干的效率提供单元,无论与业务流程非亲非故的基础功效,依然现实的作业逻辑,均落实在对应的劳务中间。服务对外提供统一的接口,服务中间接选举拔规范的通讯情势开始展览互动,各种单壹的服务精又可行的咬合、编排成为1个有机的共同体。在那样1个分布式系统中有个别活动(Activity)的达成多次须要跨越单个服务的界线,怎么着协调八个服务期间的关系使之为活动机能的落到实处劳务,涉及到SOA八个珍视的课题:服务同盟(ServiceCoordination)。而具体来讲,一个分布式的运动或许会履行几分钟,比如银行转帐;也大概举办几分钟、多少个钟头、几天照旧越来越长,比如移民局处理移民的申请。事务,无疑是属于短暂运营服务同盟(Short-Running
Service Coordination)的范畴。

议论分布式事务之1,关于分布式事务的一个误会。     
事务是数据库管理种类的三个基本概念,事务有着四个着力特色,即ACID:原子性(Atomicity)、1致性(Consistency)、隔离性(Isolation)和持久性(Durability),通过工作机制得以确认保障数据库的1致性和完整性。

     
事务是数据库管理种类的2个基本概念,事务有着八个主导特色,即ACID:原子性(Atomicity)、一致性(Consistency)、隔开性(Isolation)和持久性(Durability),通过工作机制能够保险数据库的1致性和完整性。

1、 什么是事情(Transaction)

作业提供一种体制将三个移动涉及的有着操作纳入到一个不可分割的实施单元,组成工作的装有操作唯有在富有操作均能健康实施的意况下方能交到,只要个中任1操作实施破产,都将招致整个业务的回滚。简单地说,事务提供一种“要么什么都不做,要么做任何(All
or
Nothing)”机制。事务有着如下多个个性,依据其首字母,我们一般将其称为事务的ACID第四次全国代表大会属性:

  • 原子性(Atomicity):“原子”那些词的本义便是不可分割的趣味,事务的原子性的含义是:一个事务的具有操作被松绑成3个整机,全部的操作仍然全部实施,要么都不履行;
  • 一致性(Consistence):政工的原子性确定保证一个政工不会破环数据的壹致性,如若工作成功交付,数据的境况是构成工作的保有操作依据事先编排的诀窍执行的结果,数据状态有所壹致性;倘若事情任何3个中间步骤出错,整个业务回滚并将数据恢复生机到原来的场馆,数据状态依旧拥有一致性。所以,事务只会将数据状态从二个一致性状态转换成另多个壹致性状态;
  • 隔离性(Isolation):从事情的表面来看,事务的一致性达成了数量在多少个1致性状态之间的变换,但是从作行业内部部来看,组成工作的顺序操作是遵照一定的逻辑顺序执行的,所以数据有所位于四个一致性状态的“中间状态”。可是,那种中间状态被隔开于工作内部,对于事情外部是不可知的;
  • 持久性(Durability):持久性的趣味是1旦得逞交付,基于持久化能源(比如数据库)的多准将会被持久化,对数码的改动是永久性的。

事情最初源于数据库管理连串(DBMS),反映的是对存款和储蓄于数据库中的数据操作。除了主流的关系型数据库管理连串,比如SQL
Server,Oracle和DB2等提供对业务的支撑,基于事务的数目操作办法也得以使用到其余部分数据存款和储蓄能源,比如MSMQ。自Windows
Vista开始将文件系统(NTFS)以至于注册表纳入了事务型能源(Transactional
Resource)的范围。

     
可是数据库事务只幸好数据库实例的同叁个会话级别实行工作控制。而分布式事务能够协调一个数据库实例多个会话之间的操作,甚至是三个数据库实例之间的数据库操作,并保证业务特性。然则规格上我们不引入应用分布式事务,因为分布式事务对财富消耗较多,执行效用较差。

     
可是数据库事务只可以在数据库实例的同2个会话级别举办作业控制。而分布式事务能够协调三个数据库实例多少个会话之间的操作,甚至是多少个数据库实例之间的数据库操作,并维持业务性子。不过规格上我们不推荐使用分布式事务,因为分布式事务对财富消耗较多,执行功用较差。

2、 事务的显式控制

即使事务型能源家族成员尤其多,可是不可以还是不可以认的是,数据库依旧我们运用频率最高的事务型能源。对于有个别有肯定阅历的开发职员,应该都在储存进程(Stored
Procedure)中编辑过基于事务的SQL,恐怕编写过基于ADO.NET事务的代码,对业务的特别介绍就从此间谈起。

一、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之间的操作。

大家举七个很出众的基于事务型操作的事例:银行转帐,而且那个例子将会贯通于本章的一味。为此,大家先成立二个卓殊简单的用来存款和储蓄帐户的数据表: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

银行转帐是3个归纳的复合型操作,由两当中央的操作结合:存款和储蓄和提取,即从2个帐户中领到相应金额出入另二个帐户。对数据完整性的渴求是我们亟须将那五个单纯的操作纳入同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五起,甚至完成了与CL陆风X8(Common Language
Runtime)的集成,使开发人士能够应用其余一种.NET语言编写编写函数可能存款和储蓄进度。毫无夸张地说,你能够由此SQL达成别的工作逻辑。

而是,在大部情景大家并不那样做,大家越多地照旧将SQL作为最主旨的数目操作语言在动用。对于.NET开发者来说,大家还是习惯将复杂的逻辑和流程序控制制实今后通过C#大概VB.NET那样的样子对象编程语言编写的主次中。究其原因,作者以为关键有两点:

  • 面相对象的言语更能便于地贯彻复杂的逻辑:较之SQL那种依照集合记录的语言,面相对象的言语更是切近于大家真正的世界,通过外貌对象的法子模拟具体的逻辑更是贴近于人类的构思方法。其余,通过面相对语言本人的片段本性,我们能够更进一步简单地行使各样设计方式和思想;
  • 将太多逻辑运算的推行放在数据库中不方便人民群众应用的扩大:从下级的角度来讲,数据操作运算负载到实际的服务器中,以四个超群绝伦的分布式Web应用为例,Web服务器(承载Web应用)、应用服务器(承载各样劳动)和数据库服务器均能够承接最后对逻辑的演算。但是,从可扩张性(也许可伸缩性)上思虑,将第3的计量放在前两者比位居数据库更具优势。假若我们将密集的运算(那种运算须求占用越多的CPU时间和内部存款和储蓄器)迁移到Web服务器只怕应用服务器,我们能够通过负载均衡(Load
    Balance)将其疏散到多台服务器下边,那几个服务器机群能够依照负荷意况展开动态地安顿。不过,数据库服务器对负荷均衡的支撑就不那么不难。

正因为如此,对于工作的主宰,较之选用SQL的兑现格局,大家应用得最多的要么采取基于面相对象语言编制程序的点子。对于.NET开发人士,大家能够直接行使ADO.NET将依照单个数据库连接的七个操作纳入同三个政工之中。同样以地点的银行转帐事务为例,此次我们将全部转帐作为1个劳务(BankingService)的贰个操作(Transfer)。上面包车型客车代码通过壹种与现实数据库类型非亲非故的ADO.NET编程格局达成了上上下下银行转帐操作,最后的转帐通过调用三个储存进度完毕:

   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的参数会添加”@”前缀,为此笔者将对参数名称的分析达成在3个独门的方法(BuildParameterName)之中。

三、事务的显式控制范围于对单纯能源的拜访

通过在SQL中进行工作的主宰,只好将依照某一段SQL语句的操作纳入到二个拾足的政工中;假设使用基于ADO.NET的数量控制,被纳入到同一个作业的操作仅仅限于有些数据库连接。换句话说,上边介绍的那两种对事情的显式控制仅仅限于对单纯的地面财富的操纵。

我们将业务的定义引入服务,若是大家将叁个单一的劳务操作作为1个政工,假若使用上述的显式事务控制的诀要,那么任何服务操作只可以涉及八个纯净的工作财富。服务于存取的能源事关如图1所以。

美高梅开户网址 2

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

上述的那种根据有些服务单壹本地财富的走访的事情,被誉为本地工作(Local
Transaction),在一个依照SOA分布式应用环境下,大家需求的还要能将多个财富、三个服务开始展览统1同盟的分布式事务(Distributed
Transaction)。接下来,我们来介绍两种典型的分布式事务应用的情景。

     
但是平昔以来,咱们对分布式事务的代码应用和功效都留存误会:使用了TransactionScope就必定会张开分布式事务吗?

     
但是直白以来,我们对分布式事务的代码应用和职能都存在误解:使用了TransactionScope就必定会敞开分布式事务吗?

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

对此一个分布式事务(Distributed
Transaction)来讲,事务的参与者分布于网络环境中的差异的节点。也正是说,大家能够将多少个事情财富纳入到一个纯净的工作之中,并且这么些工作财富能够分布到分歧的机器上。那些承载分布式财富的机械大概是出于同2个互连网中,也或然处于差别的互联网中。甚至说,某个事务财富本质上正是一个通过HTTP访问的单纯的Internet财富。

站在SOA的角度来看分布式事务,意味着将劳动的某些服务操作视为3个纯粹的工作。该服务操作恐怕会访问不止一个作业能源(比如访问七个不等的数据库服务器),也说不定调用另2个劳动。上面介绍了多个优异的分布式事务应用场景,先从最简便易行的提及。

一、将对多少个能源的拜会纳入同壹业务

第3个分布式事务应用场景最简单易行,即二个劳务操作并不会调用另贰个劳动,可是服务操作涉及到对多少个业务财富的拜会。当2个劳务操作访问分裂的数据库服务器,比如两台SQL
Server,大概1台SQL Server和1台Oracle
Server;当三个劳务操作访问的是一致数据库,可是相应的数据库访问时依照不相同的多寡连接;当二个服务操作处理访问数据库能源,还亟需拜访其余份数据库的工作财富,就供给运用分布式事务来对全部的作业加入者举行同盟了。图2反映了那般的分布式应用场景。

美高梅开户网址 3

美高梅开户网址,图二 单一服务对八个工作财富的访问

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

对此地点介绍的分布式应用场景,即便2个服务操作会访问三个事情财富,但是到底整个事情照旧决定在单纯的劳动中间。要是贰个服务操作须求调用其余2个服务,那是的业务就必要跨越多少个劳务了。在那种地方下,起先于某些服务的事情在调用别的三个服务的时候,须求以某种机制流转到此外叁个劳动,以使被调用的劳动走访的财富自动进入进去。图3反映了这么三个抢先多少个服务的分布式事务。

美高梅开户网址 4 图3跨越三个劳务的作业

3、 将对八个资源和劳动的走访纳入同贰个工作

假设将上面那二种处境(二个劳务能够调用多个事情财富,也能够调用其余服务)结合在协同,对此开始展览延伸,整个事情的出席者将会组成如图4所示的树形拓扑结构。在三个基于分布式事务的劳务调用中,事务的发起者和交由均系同1个,它能够是整整调用的客户端,也得以是客户端开端调用的百般服务。

美高梅开户网址 5 图四基于SOA分布式事务拓扑结构

同期比较基于单一财富访问的本地下工作作,分布式事务的贯彻机制要复杂得多。Windows平台提供了依照DTC分布式事务基础架构,下1篇小说中自笔者将对针对性该架构模型详细介绍分布式事务时怎么办事的。

 

分布式事务体系: 议论分布式事务之壹:SOA供给哪些的业务控制措施
议论分布式事务之二:基于DTC的分布式事务管理模型[上篇]
议论分布式事务之2:基于DTC的分布式事务管理模型[下篇]
座谈分布式事务之3:
System.Transactions事务详解[上篇]
钻探分布式事务之三:
System.Transactions事务详解[下篇]

作者:Artech出处:

 

 

验证:

验证:

     
大家做贰个大约的德姆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();

 

 

出人意料的事情时有产生了,并未见到大家的以为的分布式事务!!!

意外的作业发生了,并从未见到大家的觉得的分布式事务!!!

美高梅开户网址 6

美高梅开户网址 7

 

 

咱俩改变内部的1个老是字符串,使得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();

 

 

让我们看一下分布式事务是怎么样协调每一种数据库连接,当前的案例我们应用的是同一个数据库,所以就算创建了七个数据库连接,但聊起底在数据库层面依旧是1律业务ID。

让我们看一下分布式事务是什么协调各种数据库连接,当前的案例我们使用的是同1个数据库,所以纵然创制了七个数据库连接,但最终在数据库层面依然是同一业务ID。

一旦大家开辟的是三个不等数据库实例,将会看出如何的结果吗? try
it。。。

如果我们打开的是两个分化数据库实例,将汇合到如何的结果吧? try
it。。。

美高梅开户网址 8

美高梅开户网址 9

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图