spring事务管理与查询是否需要事务以及可重复读的问题


本文摘自classinstance.cn。

我们先来看下通常的spring配置:

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="remove*" propagation="REQUIRED" />
			<tx:method name="newTx*" propagation="REQUIRES_NEW" /> 
			<tx:method name="get*"  read-only="true"/>
			<tx:method name="find*" read-only="true" />
			<tx:method name="*" read-only="true"/>
		</tx:attributes>
	</tx:advice>

上面的配置中增删改中用propagation="REQUIRED"和"REQUIRES_NEW",都是需要开启写事务的,应该每个人都知道,但查询是否需要开启事务呢?

反正我在这之前,真的以为不用,也没必须开启。

但今天研究了下mycat的读写分离,发现写事务里的读都走写库,这种做法是为了保证查询数据的一致性,也就是保证数据库的可重复读事务隔离性。

我们再看看上面的读配置:

<tx:method name="get*"  read-only="true"/>

其中tx里的默认传播性是propagation="REQUIRED" read-only默认为"false",默认可写的意思,也就是说上面的配置是有事务的,只是告诉数据库此事务没有需要更新的语句,事务只读,用spring这么久了,我才发现虽然配置了read-only="true",但上面的事务配置查询也是有事务的!

所以说查询也是需要开启事务的,以MySQL为例,这是为了这一组事务里的所有查询在Repeatable Read隔离级别下能做到一致性,也就是常说的可重复读。

举个例子,如果上面的读配置成无事务,如下:

<tx:method name="get*"  propagation="NEVER"/>

那么就可能在一组查询中出现数据不致的问题,如:

public void getUserList(){

	select count(*) from user_info
	
	select * from user_info limit 0,10
}

如上我们service里有这么一个方法(事务切面定义的是service里的方法),用来分页查询的,当第一条查询出来count为6条数据时,正好有人删除了其中一条数据,因为getUserList()方法定义为无事务,下面这条语句查询用户数据查询出来就只有5条,造成了前后数据不一致,这违背了Repeatable Read隔离级别。

我们也不希望用户看到这种情况。

所以说为了保证可重复读,查询也是需要事务的,只不过为了优化数据查询,将read-only设为"true"。

另外,如果你的方法里或者说此次查询操作只有一个查询语句,那就没必要开启只读事务了,因为只有一个语句,没有一致性的问题,数据库默认可重复读的事务级别,也就是说spring里的事务配置,可以给这种方法配置成无事务,这样做会让你的查询性能提升很多,当然如果你的程序的查询密集型,并且不在意查询一致性的问题的话,一样可以设置成查询无事务,因为这么做相对于有只读事务的查询来说,性能可以提升3-4倍。

相关阅读 >>

spring如何获取配置在application.properties文件中属性的值?

使用spring4实现websocket连接

使用spring4实现websocket连接(二)

spring事务管理与查询是否需要事务以及可重复读的问题

springspringmvc、springboot和springcloud的区别

更多相关阅读请进入《spring》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...