Spring 事务的传播行为

本贴最后更新于 2636 天前,其中的信息可能已经物是人非

事务的传播行为和隔离级别[transaction behavior and isolated level]

Spring 中事务的定义:
一、Propagation :

  key 属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

很多人看到事务的传播行为属性都不甚了解,我昨晚看了 j2ee without ejb 的时候,看到这里也不了解,甚至重新翻起数据库系统的教材书,但是也没有找到对这个的分析。今天搜索,找到一篇极好的分析文章,虽然这篇文章是重点分析 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRED_NESTED 的
解惑 spring 嵌套事务

TransactionDefinition 接口定义***********

**
	 int PROPAGATION_REQUIRED = 0;   

	**

** **

	 int PROPAGATION_SUPPORTS = 1;   

	 int PROPAGATION_MANDATORY = 2;   



** **

	 int PROPAGATION_REQUIRES_NEW = 3;   



	 int PROPAGATION_NOT_SUPPORTED = 4;   


	 int PROPAGATION_NEVER = 5;   



	 int PROPAGATION_NESTED = 6;   

在这篇文章里,他用两个嵌套的例子辅助分析,我这里直接引用了。

sample***

_ServiceA {   
	 void methodA() {   
		 ServiceB.methodB();   
	 }   

}   

ServiceB {   


	 void methodB() {   
	 }   

}      _

我们这里一个个分析吧
1: PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB 的事务级别定义为 PROPAGATION_REQUIRED, 那么由于执行 ServiceA.methodA 的时候,
ServiceA.methodA 已经起了事务,这时调用 ServiceB.methodB,ServiceB.methodB 看到自己已经运行在 ServiceA.methodA
的事务内部,就不再起新的事务。而假如 ServiceA.methodA 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在 ServiceA.methodA 或者在 ServiceB.methodB 内的任何地方出现异常,事务都会被回滚。即使 ServiceB.methodB 的事务已经被
提交,但是 ServiceA.methodA 在接下来 fail 要回滚,ServiceB.methodB 也要回滚

2: PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
这就跟平常用的普通非事务的代码只有一点点区别了。不理这个,因为我也没有觉得有什么区别

3: PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。

4: PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计 ServiceA.methodA 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB 的事务级别为 PROPAGATION_REQUIRES_NEW,
那么当执行到 ServiceB.methodB 的时候,ServiceA.methodA 所在的事务就会挂起,ServiceB.methodB 会起一个新的事务,等待 ServiceB.methodB 的事务完成以后,
他才继续执行。他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为 ServiceB.methodB 是新起一个事务,那么就是存在
两个不同的事务。如果 ServiceB.methodB 已经提交,那么 ServiceA.methodA 失败回滚,ServiceB.methodB 是不会回滚的。如果 ServiceB.methodB 失败回滚,
如果他抛出的异常被 ServiceA.methodA 捕获,ServiceA.methodA 事务仍然可能提交。

5: PROPAGATION_NOT_SUPPORTED
当前不支持事务。比如 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED ,而 ServiceB.methodB 的事务级别是 PROPAGATION_NOT_SUPPORTED ,
那么当执行到 ServiceB.methodB 时,ServiceA.methodA 的事务挂起,而他以非事务的状态运行完,再继续 ServiceA.methodA 的事务。

6: PROPAGATION_NEVER
不能在事务中运行。假设 ServiceA.methodA 的事务级别是 PROPAGATION_REQUIRED, 而 ServiceB.methodB 的事务级别是 PROPAGATION_NEVER ,
那么 ServiceB.methodB 就要抛出异常了。

7: PROPAGATION_NESTED
理解 Nested 的关键是 savepoint。他与 PROPAGATION_REQUIRES_NEW 的区别是,PROPAGATION_REQUIRES_NEW 另起一个事务,将会与他的父事务相互独立,
而 Nested 的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而 Nested 事务的好处是他有一个 savepoint。


ServiceA {      
 void methodA() {   
     try {
  //savepoint   
         ServiceB.methodB();    //PROPAGATION_NESTED 级别
     } catch (SomeException) {   
         // 执行其他业务, 如 ServiceC.methodC();   
     }   
 }   

}   

也就是说 ServiceB.methodB 失败回滚,那么 ServiceA.methodA 也会回滚到 savepoint 点上,ServiceA.methodA 可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在 EJB 标准中定义。

二、Isolation Level(事务隔离等级):
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。

3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。

4、Read Uncommitted:保证了读取过程中不会读取到非法数据。

隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的 3 中不讨人喜欢的事情
1: Dirty reads--读脏数据。也就是说,比如事务 A 的未提交(还依然缓存)的数据被事务 B 读走,如果事务 A 失败回滚,会导致事务 B 所读取的的数据是错误的。

2: non-repeatable reads--数据不可重复读。比如事务 A 中两处读取数据-total-的值。在第一读的时候,total 是 100,然后事务 B 就把 total 的数据改成 200,事务 A 再读一次,结果就发现,total 竟然就变成 200 了,造成事务 A 数据混乱。

3: phantom reads--幻象读数据,这个和 non-repeatable reads 相似,也是同一个事务中多次读不一致的问题。但是 non-repeatable reads 的不一致是因为他所要取的数据集被改变了(比如 total 的数据),但是 phantom reads 所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如 Select account.id where account.name="ppgogo*",第一次读去了 6 个符合条件的 id,第二次读取的时候,由于事务 b 把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了 7 个数据。

                      Dirty reads          non-repeatable reads            phantom reads
Serializable              不会                   不会                           不会
REPEATABLE READ           不会                   不会                            会
READ COMMITTED            不会                    会                             会
Read Uncommitted            会                     会                             会

三、readOnly
事务属性中的 readOnly 标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用 Object/Relational 映射工具(如:Hibernate 或 TopLink)时避免 dirty checking(试图“刷新”)。

四、Timeout

在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在 JTA 中,这将被简单地传递到 J2EE 服务器的事务协调程序,并据此得到相应的解释。

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 94 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • tmedivh

    不错!!!!!!

推荐标签 标签

  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    104 引用 • 126 回帖 • 434 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    123 引用 • 168 回帖
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖
  • 职场

    找到自己的位置,萌新烦恼少。

    126 引用 • 1699 回帖
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 44 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    219 引用 • 468 回帖 • 1 关注
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖 • 2 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    175 引用 • 994 回帖
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 94 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1386 回帖 • 322 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 3 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    28 引用 • 101 回帖
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    546 引用 • 3531 回帖
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 136 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 125 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 22 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    180 引用 • 400 回帖
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    58 引用 • 113 回帖 • 273 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    103 引用 • 294 回帖
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 31 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 45 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 2 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 1 关注