不久之前团队有个新人问我一个很重要的web服务接口如何保证事务的问题。因为涉及到跨库事务,当时我只是回答目前我们的SOA框架都不支持跨库事务。然后就问到了数据库跨库事务是如何实现的,我只能凭印象含糊回答多数是基于数据库日志(后来知道就是所谓的预写日志Write-Ahead Logging),具体数据库内部如何控制数据一致性则真的说不清楚。后来一起查了一下事务的资料,原来DB的事务控制除了基于预写日志还要实现两阶段提交协议(2PC),参考MSDN摘抄两段加深印象。

一、2PC的两个阶段

1、准备阶段(Prepare Phase)

When the transaction manager receives a commit request, it sends a prepare command to all of the resource managers involved in the transaction. Each resource manager then does everything required to make the transaction durable, and all buffers holding log images for the transaction are flushed to disk. As each resource manager completes the prepare phase, it returns success or failure of the prepare to the transaction manager.

2、提交阶段(Commit Phase)

If the transaction manager receives successful prepares from all of the resource managers, it sends commit commands to each resource manager. The resource managers can then complete the commit. If all of the resource managers report a successful commit, the transaction manager then sends a success notification to the application. If any resource manager reported a failure to prepare, the transaction manager sends a rollback command to each resource manager and indicates the failure of the commit to the application.

二、2PC的原理示例

如何理解2PC实现分布式事务的呢?下面举例说明下。

假设有A、B、C三个数据库,A作为一个事务发起者,称为“主库”,B和C则称为”从库”。假设需要执行一个在A、B和C三个库的某个表中插入一行数据的事务。

准备阶段(Prepare Phase),A锁定表,并将事务写入自己的预写日志;A将事务发给从库B和C,B和C也各自锁定自己的表,并把事务写入预写日志,完成后返回告诉A准备阶段完成;
提交阶段(Commit Phase),A开始执行自己的事务,并通知B和C提交事务。如果在这个过程中没有任何错误,那么操作将在A、B和C库中完成;如果发生错误,比如从库C超时无响应,或者从库C磁盘空间不足…A将通知所有参与事务的B和C回滚该事务,并且回滚A自己的事务。

顺便重点再提一下预写日志,因为数据库的这种日志无比重要,普通的增删改查、数据还原、单库事务以及本文的分布式事务都离不开它,没有它绝大多数主流数据库的数据一致性根本无法实现。

到这里大家应该已经看到,相比单库事务,分布式事务控制更加复杂,而且开销极大。虽然一些高级开发框架如.net framework提供了较为强大丰富的类库如TransactionScope来简化开发分布式事务,但是建议能不用则不用,因为它被反映普遍存在性能问题无意识的死锁问题。这种分布式事务的场景如果频繁出现,重新拆分系统合理规划架构才是正道。

总结:在大型web应用中如何保持事务这个话题被问得非常多,个人已经是不止一次被问到所维护的站点是如何实现事务的。在分布式多集群环境下,业务逻辑错综复杂,保证数据库完全可靠存储当然并不容易。但是web应用程序的一个典型特点是读多写少,牺牲极少的数据一致性获得系统的高可扩展性可维护性以及高性能,那么一点点的数据不准确在业务上完全可以容忍,何况我们有日志,后续还有很多补偿措施,甚至直接人工介入处理也未尝不可。

参考:

http://msdn.microsoft.com/en-us/library/ms191440.aspx

http://technet.microsoft.com/zh-cn/library/ms186259(v=SQL.105).aspx

http://www.cnblogs.com/CareySon/archive/2012/02/13/2349751.html

http://www.cnblogs.com/CareySon/archive/2012/02/14/2351149.html

浅析SQL Server实现分布式事务的两阶段提交协议2PC的更多相关文章

  1. 分布式协议之两阶段提交协议(2PC)和改进三阶段提交协议(3PC)

    一. 事务的ACID 事务是保证数据库从一个一致性的状态永久地变成另外一个一致性状态的根本,当中,ACID是事务的基本特性. A是Atomicity,原子性.一个事务往往涉及到很多的子操作,原子性则保 ...

  2. sql server 锁与事务拨云见日(下)

    在锁与事务系列里已经写完了上篇中篇,这次写完下篇.这个系列俺自认为是有条不紊的进行,但感觉锁与事务还是有多很细节没有讲到,温故而知新可以为师矣,也算是一次自我提高总结吧,也谢谢大伙的支持.在上一篇的末 ...

  3. Microsoft SQL Server中的事务与并发详解

    本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...

  4. SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

    原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中 ...

  5. 【转】SQL Server中的事务与锁

    SQL Server中的事务与锁   了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂 ...

  6. SQL Server中的事务日志管理(8/9):优化日志吞吐量

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  7. MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】

    概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...

  8. SQL Server 2008 数据库同步的两种方式 (发布、订阅)

    参考转载: SQL Server 2008 数据库同步的两种方式 (发布.订阅) 使用Sqlserver事务发布实现数据同步

  9. sql server 锁与事务拨云见日(中)

    一.事务的概述 上一章节里,重点讲到了锁,以及锁与事务的关系.离上篇发布时间好几天了,每天利用一点空闲时间还真是要坚持.听<明朝那些事儿>中讲到"人与人最小的差距是聪明,人与人最 ...

随机推荐

  1. ServiceStack.OrmLite中的一些"陷阱"(3)

    前文说到如果使用多数据库(不同SQL方言)时要如何开发?其实前文(第二篇)也有“透露”到.就是直接使用库提供的OrmLiteConnection 及OrmLiteConnectionFactory(I ...

  2. 大前端学习笔记整理【四】LESS基础

    第一次接触CSS预编译,然后对比后发现其实less的上手容易度确实比sass高不少,再加上公司项目也是使用的less.所以想想还是根据网上的各种教程,整理出来了一些比较基础的.而且比较能让我们这种初学 ...

  3. delphi XE5皮肤的使用

      做皮肤其实是项浩大的工程,从美工设计.到贴图.到程序设计,都非常的麻烦,如果不是一个非常成熟的产品且有很大的用户群体,并且公司具有相当实力,一般都不会去自己做皮肤,毕竟涉及的东西太多,一旦出现问题 ...

  4. eclipse 搭建Swt 环境

    我本是想用java开发一个记事本,开发记事本使用到SWT插件,我从网上找了许多的资料去集成插件,创建我的第一个SWT项目,以下是我搭建SWT环境的过程. 一.查看当前使用的exlipse 版本型号 在 ...

  5. Python爬虫入门案例:获取百词斩已学单词列表

    百词斩是一款很不错的单词记忆APP,在学习过程中,它会记录你所学的每个单词及你答错的次数,通过此列表可以很方便地找到自己在记忆哪些单词时总是反复出错记不住.我们来用Python来爬取这些信息,同时学习 ...

  6. localStorage, localforage, web sql三者的比较

    最近的项目中用到了前端存储,最初选用的是localStorage,这个是html5里面新增的API,用法很简单.setItem getItem clear. 值得注意的是,localStorage中存 ...

  7. Merge在Sqlserver使用例子说明

    ---文章 MatchInt的方式 Create table SourceTable([ID] int,[Desc] varchar(50)); Create table TargetTable([I ...

  8. Mini projects #3 ---- Stopwatch: The Game

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  9. disconf使用

    1.创建app,确定version 2.创建配置文件redis.config 3.选择app下env环境,上传redis.config到disconf 4.创建disconf.properties到c ...

  10. 编译系统中BNF: Backus-Naur Form

    巴科斯范式(BNF: Backus-Naur Form 的缩写)是由 John Backus 和 Peter Naur 首次引入一种形式化符号来描述给定语言的语法. 简称为:BNF符号. 现在,几乎每 ...