zoukankan      html  css  js  c++  java
  • 【文章阅读】事务和分布式事务学习理解

    一、事务的起源:

    事务是作用于数据的,防止数据不一致给业务造成影响。由此,产生了事务的概念。
    其实事务的本质是解决数据一致性问题。其他的各种概念,都是为了解决这个问题产生的具体方法,概念以及原则。理解了这个,就对事务没太多误解了。

    二、事务的4个特性:

    4.1 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。

    -

    4.2 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。

    理解:
    一致性有两层语义,一层是确保事务执行结束后,数据库从一个一致状态转变为另一个一致状态。另一层语义是事务执行过程中的中间状态不能被观察到。
    如果数据库中有没有执行完的事务,那就是不一致的,否则,就是一致的。即事务必须被执行完。

    事务的一致性决定了一个系统设计和实现的复杂度。事务可以不同程度的一致性:
    强一致性:读操作可以立即读到提交的更新操作。
    弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。
    最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。
    其他一致性变体还有:
    单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。
    会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。

    4.3 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。

    在事务并发操作时,可能出现的问题有:
    脏读:事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。
    不可重复读:在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
    幻读:在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
    事务的隔离级别从低到高有:
    Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
    Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
    Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
    Serialization:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
    通常,在工程实践中,为了性能的考虑会对隔离性进行折中。

    4.4 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

    三、分布式事务:

    主要参考文章即可。这里重点理解概念以及X/Open XA 协议,其他不做过多涉及

    • 本地事务:基于单个服务单一数据库资源访问的事务;
    • 分布式事务:当一个服务操作访问不同的数据库资源,又希望对它们的访问具有事务特性时,就要采用分布式事务来协调所有的事务参与者。
      1.最早的分布式事务应用架构:服务内操作涉及到对多个数据库资源的访问。(整个事务控制在单一服务的内部)
      2.后续的分布式事务应用架构:一个服务操作需要调用另外一个服务,这时的事务就需要跨越多个服务了。

    3.1 分布式事务模型:X/Open XA 协议

    3.1.1 DTP 模型(标准的分布式事务)

    ** 1、 DTP 模型中包含:**
    一个全局事务管理器(TM,Transaction Manager):负责管理全局事务状态与参与的资源,协同资源一起提交或回滚;
    多个资源管理器(RM,Resource Manager):负责具体的资源操作。

    2、基于 DTP 模型的分布式事务流程:

    解释:

    1. 应用程序(AP,Application)向 TM 申请开始一个全局事务。
    2. 针对要操作的 RM,AP 会先向 TM 注册(TM 负责记录 AP 操作过哪些 RM,即分支事务),TM 通过 XA 接口函数通知相应 RM 开启分布式事务的子事务,接着 AP 就可以对该 RM 管理的资源进行操作。
    3. 当 AP 对所有 RM 操作完毕后,AP 根据执行情况通知 TM 提交或回滚该全局事务,TM 通过 XA 接口函数通知各 RM 完成操作。TM 会先要求各个 RM 做预提交,所有 RM 返回成功后,再要求各 RM 做正式提交,XA 协议要求,一旦 RM 预提交成功,则后续的正式提交也必须能成功;如果任意一个 RM 预提交失败,则 TM 通知各 RM 回滚。
    4. 所有 RM 提交或回滚完成后,全局事务结束。

    3、ACID 的保证

    1. 原子性
      XA 协议使用 2PC(Two Phase Commit,两阶段提交)原子提交协议来保证分布式事务原子性。
    2. 隔离性:
      基于 XA 协议实现的分布式事务的隔离性是由每个 RM 本地事务的隔离性来保证的,当一个分布式事务的所有子事务都是隔离的,那么这个分布式事务天然的就实现了隔离性。
    3. 一致性

      一致性有两层语义,一层是确保事务执行结束后,数据库从一个一致状态转变为另一个一致状态。另一层语义是事务执行过程中的中间状态不能被观察到。

    前一层语义的实现很简单,通过原子性、隔离性以及 RM 自身一致性的实现就可以保证。
    后一层:单个 RM 上的本地事务是一致的,但是从全局来看,一个全局事务执行过程的中间状态被观察到了,全局一致性就被破坏了。MySQL 官方文档里就建议使用串行化的隔离级别来保证分布式事务一致性。基本思路是用一个集中式或者逻辑上单调递增的东西来控制生成全局 Snapshot,每个事务或者每条 SQL 执行时都去获取一次,从而实现不同隔离级别下的一致性。比如 Google 的 Spanner 就是用 TrueTime 来控制访问全局 Snapshot。

    3.1.2 分布式事务模型:TCC 模型:暂不整理

    四、JDBC事务:

    JDBC事务:是在Java中用来控制数据库事务的。
    JDBC的一切行为包括事务是基于一个Connection的,在JDBC中通过Connection对象进行事务管理。
    在JDBC中,常用的和事务相关的方法是: setAutoCommitcommitrollback等。

    注意:

    1. 数据库默认事务自动提交,即每次数据库更新都立即提交,所以要想自行控制事务,则必须关闭自动提交;
    2. 事务的操作实际只有两个:提交(commit)和回滚(rollback)
    3. 一个 JDBC 事务不能跨越多个数据库。这是JDBC事务的局限,也因此产生了分布式事务以及其他事务。

    五、JTA事务

    Java事务API(Java Transaction API),简称JTA。
    JTA和它的同胞Java事务服务(JTS;Java TransactionService),为J2EE平台提供了分布式事务服务。不过JTA只是提供了一个接口,并没有提供具体的实现,实现由J2EE服务器提供商根据JTS规范提供。

    JTA里面提供了 java.transaction.UserTransaction ,里面定义了下面几个方法

    begin:开启一个事务
    commit:提交当前事务
    rollback:回滚当前事务
    setRollbackOnly:把当前事务标记为回滚
    setTransactionTimeout:设置事务的事件,超过这个事件,就抛出异常,回滚事务

    注意:不是使用了UserTransaction就能把普通的JDBC操作直接转成JTA操作。
    JTA对DataSource、Connection和Resource 都有要求。只有符合XA规范,并且实现了XA规范的相关接口的类才能参与到JTA事务中来。目前主流的数据库都支持XA规范。

    要想使用用 JTA 事务,那么就需要有一个实现 javax.sql.XADataSourcejavax.sql.XAConnectionjavax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。
    一个 XADataSource 对象就是一个 XAConnection 对象的工厂。
    XAConnection 是参与 JTA 事务的 JDBC 连接。
    要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。
    XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。

    六、参考:

    1. 如何理解数据库事务中的一致性的概念? - 知乎 https://www.zhihu.com/question/31346392/answer/59815366
    2. 一篇文章带你学习分布式事务 https://mp.weixin.qq.com/s/RDnf637MY0IVgv2NpNVByw
    3. Java中的事务——JDBC事务和JTA事务 https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg%3D%3D&chksm=f36bb83dc41c312b896ffd89f30d99440a9ee1ac218eda6dee4d900bf66d1a72bc1bb0c02c64&idx=1&mid=2650121500&mpshare=1&scene=1&sn=65db8bdb83166eed8ba69cf47c0e12c6&srcid=0614GHqvDB6blh60XhA9XHF5

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

  • 相关阅读:
    Django-admin导出到表格
    Django1.11.4中文文档
    Django+uwsgi+nginx+angular.js项目部署
    angular.js 入门
    枚举类型的总结
    基于websocket的页面聊天程序
    java网络编程(三):一个类似QQ的聊天程序
    java网络编程(二)
    java网络编程(一)
    java中的序列化与反序列化,还包括将多个对象序列化到一个文件中
  • 原文地址:https://www.cnblogs.com/buwuliao/p/9196524.html
Copyright © 2011-2022 走看看