事务与锁是不同的。事务具有ACID属性:

原子性:持久性:由redo log重做日志来保证事务的原子性和持久性,
一致性:undo log用来保证事务的一致性
隔离性:一个事务在操作过程中看到了其他事务的结果,如幻读。锁是用于解决隔离性的一种机制。事务的隔离级别通过锁的机制来实现。

数据库的事务隔离级别有(多个事务并发的情况下):

√: 可能出现    ×: 不会出现

 事务的隔离级别
脏读  事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。违反隔离性导致的问题,添加行锁实现 不可重复读  事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务2修改后的记录(修改批更新或者删除)需要添加行锁进行实现 幻读   事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录。需要添加表锁进行实现
Read uncommitted 
Read committed  ×
Repeatable read × ×
Serializable × × ×
注意点:
 
(1)要分清不可重复读和幻读的区别 一个是更新记录,另外一个是读取了新增的记录
 
(2)不同的数据库存储引擎其实并没有严格按照标准来执行,如innodb默认的repeatable read隔离级别下就可以做到避免幻读的问题(采用了Next-Key-Lock锁的算法)
 
 

对应着Spring中的5个事务隔离级别(通过lsolation的属性值指定)

1、default   默认的事务隔离级别。使用的是数据库默认的事务隔离级别

2、read_uncommitted  读未提交,一个事务可以操作另外一个未提交的事务,不能避免脏读,不可重复读,幻读,隔离级别最低,并发性能最高

3、read_committed(脏读)  大多数数据库默认的事务隔离级别。读已提交,一个事务不可以操作另外一个未提交的事务, 能防止脏读,不能避免不可重复读,幻读

4、repeatable_read(不可重复读) innodb默认的事务隔离级别。能够避免脏读,不可重复读,不能避免幻读

5、serializable(幻读) innodb存储引擎在这个级别才能有分布式XA事务的支持。隔离级别最高,消耗资源最低,代价最高,能够防止脏读, 不可重复读,幻读

Spring中的事务完全基于数据库的事务,如果数据库引擎使用MyISAM引擎,那Spring的事务其实是不起作用的。另外,Spring为开发者提供的与事务相关的特性就是事务的传播行为,如下:

事务传播行为类型

说明

propagation_required

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择(Spring默认的事务传播行为)

propagation_supports

支持当前事务,如果当前没有事务,就以非事务方式执行

propagation_mandatory(托管)

使用当前的事务,如果当前没有事务,就抛出异常

propagation_requireds_new

新建事务,如果当前存在事务,把当前事务挂起

propagation_not_supported

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

propagation_never

以非事务方式执行,如果当前存在事务,则抛出异常

propagation_nested

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作,也就是新建一个事务

Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。

Spring可以配置事务的属性,但是隔离级别、读写事务属性、超时时间与回滚设置等都交给了JDBC,真正自己实现的只有事务的传播行为。那么什么时候发生事务的传播行为呢?

public class ForumService {
	private UserService userService;

	@Transactional(propagation = Propagation.REQUIRED)
	public void addTopic() {
		// add Topic
		this.updateTopic();
		userService.addCredits();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void updateTopic() {
		// add Topic
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}
}

看一下userService中的addCredits()方法,如下:

public class UserService {

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void addCredits() {

	}
}

然后测试下:

forumService.addTopic();

开启了Spring4日志的DEBUG模式后,输出如下:  

 

 - Returning cached instance of singleton bean 'txManager'
 - Creating new transaction with name [com.baobaotao.service.ForumService.addTopic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
 - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] for JDBC transaction
 - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] to manual commit
 - Suspending current transaction, creating new transaction with name [com.baobaotao.service.UserService.addCredits]
 - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] for JDBC transaction
 - Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] to manual commit
 - Initiating transaction commit
 - Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5]
 - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@773e2eb5] after transaction
 - Returning JDBC Connection to DataSource
 - Resuming suspended transaction after completion of inner transaction
 - Initiating transaction commit
 - Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69]
 - Releasing JDBC Connection [org.apache.commons.dbcp.PoolableConnection@1948ea69] after transaction
 - Returning JDBC Connection to DataSource

清楚的看到只有调用addCredis()方法时发生了事务的传播行为,而同一个类内的方法没有发生。在我们阅读了源代码后就可以知道这是为什么以及什么时候会发生传播行为了。

另外一点:决定事务传播行为是由首次调用有事务的方法决定的。如上例子中的事务传播行为由addTopic()方法来决定。

在使用事务中我们需要做到尽量避免死锁、尽量减少阻塞,根据不同的数据库设计和性能要求进行所需要的隔离级别,才是最恰当的。具体以下方面需要特别注意:

A、 事务操作过程要尽量小,能拆分的事务要拆分开来

B、 事务操作过程不应该有交互(系统交互,接口调用),因为交互等待的时候,事务并未结束,可能锁定了很多资源

C、 事务操作过程要按同一顺序访问对象。(避免死锁的情况产生)

D、 提高事务中每个语句的效率,利用索引和其他方法提高每个语句的效率可以有效地减少整个事务的执行时间。

E、 查询时可以用较低的隔离级别,特别是报表查询的时候,可以选择最低的隔离级别(未提交读)。

剑指架构师系列-InnoDB存储引擎、Spring事务与缓存的更多相关文章

  1. 剑指架构师系列-MySQL调优

    介绍MySQL的调优手段,主要包括慢日志查询分析与Explain查询分析SQL执行计划 1.MySQL优化 1.慢日志查询分析 首先需要对慢日志进行一些设置,如下: SHOW VARIABLES LI ...

  2. 剑指架构师系列-Struts2的缓存

    Struts2的缓存中最重要的两个类就是ReferenceMap与ReferenceCache.下面来解释下ReferenceCache中的get()方法. public V get(final Ob ...

  3. 剑指架构师系列-spring boot的logback日志记录

    Spring Boot集成了Logback日志系统. Logback的核心对象主要有3个:Logger.Appender.Layout 1.Logback Logger:日志的记录器 主要用于存放日志 ...

  4. 剑指架构师系列-持续集成之Maven+Nexus+Jenkins+git+Spring boot

    1.Nexus与Maven 先说一下这个Maven是什么呢?大家都知道,Java社区发展的非常强大,封装各种功能的Jar包满天飞,那么如何才能方便的引入我们项目,为我所用呢?答案就是Maven,只需要 ...

  5. 剑指架构师系列-tomcat6通过IO复用实现connector

    由于tomcat6的配置文件如下: <Connector port="80" protocol="org.apache.coyote.http11.Http11Ni ...

  6. 剑指架构师系列-Struts2构造函数的循环依赖注入

    Struts2可以完成构造函数的循环依赖注入,来看看Struts2的大师们是怎么做到的吧! 首先定义IBlood与BloodImpl类: public interface IBlood { } pub ...

  7. 剑指架构师系列-tomcat6通过伪异步实现connector

    首先在StandardService中start接收请求的线程,如下: synchronized (connectors) { for (int i = 0; i < connectors.le ...

  8. 剑指架构师系列-Hibernate需要掌握的Annotation

    1.一对多的关系配置 @Entity @Table(name = "t_order") public class Order { @Id @GeneratedValue priva ...

  9. 剑指架构师系列-Linux下的调优

    1.I/O调优 CentOS下的iostat命令输出如下: $iostat -d -k 1 2 # 查看TPS和吞吐量 参数 -d 表示,显示设备(磁盘)使用状态:-k某些使用block为单位的列强制 ...

随机推荐

  1. js系列(9)js的运用(一)

        本节开始介绍javascript在html页面中的运用.     (1)link样式表的动态绑定:(http://files.cnblogs.com/files/MenAngel/text04 ...

  2. JQ中 trigger()和triggerHandler()区别

    既然使用了trigger和triggerHandler,那么你应该了解了他们的差别了. trigger():在每一个匹配的元素上触发某类事件. triggerHandler():这个特别的方法将会触发 ...

  3. 密码太多记不住?SSO帮你轻松访问VDI及外部资源

    单点登录(SSO)有多种方式,简单来讲,SSO是一个允许用户使用单一登录访问多个资源的认证过程.使用云应用的VDI用户可能需要某种方式的认证访问桌面外部的应用.SSO只需要用户单次输入认证信息就可以访 ...

  4. 在Unicode版Inno Setup中使用ISSkin

    ISSkin是Code jock 公司出品的Inno Setup 皮肤插件,用于为Inno制作的安装程序提供皮肤功能. 自Delphi发布2009之后,Inno Setup 开始出现支持Unicode ...

  5. android: 服务的基本用法

    9.3   服务的基本用法 了解了 Android 多线程编程的技术之后,下面就让我们进入到本章的正题,开始对服务 的相关内容进行学习.作为 Android 四大组件之一,服务也少不了有很多非常重要的 ...

  6. 关于年终奖励的扣税算法BUG

    这么多年,第一次拿年终奖,于是查一下年终奖是怎么扣税的,根据 国税发[2005]9号 适用公式为: 应纳税额=雇员当月取得全年一次性奖金×适用税率一速算扣除数 年终奖: /= 的税率是3% 按照网上说 ...

  7. CoreOS实践(1)—CoreOS初体验

    CoreOS主要包含以下一些东西: (1)最小的OS:kernel+systemd (2)使用Docker运行应用 (3)使用fleet管理集群 (4)使用etcd实现服务发现:一个分布式的K/V存储 ...

  8. 进程、线程、轻量级进程、协程与 go 的 goroutine【转载+整理】

    本文内容 进程 线程 协程 Go 中的 goroutine 参考资料 最近,看一些文章,提到"协程"的概念,心想,进程,线程,协程,前两个很容易,任何一本关于操作系统的书都有说,开 ...

  9. Codeforces Round #384 (Div. 2)D - Chloe and pleasant prizes 树形dp

    D - Chloe and pleasant prizes 链接 http://codeforces.com/contest/743/problem/D 题面 Generous sponsors of ...

  10. Cocos2dx使用wxsqlite开源加密SQLite3数据库

    最近使用wxsqlite加密sqlite3数据库,刚开始折腾好几天,在xcode上一直编译不通过,后来在sqlite3.c找到配置,编译顺利通过,太激动了,哈哈,废话少说!总结一下android和io ...