论坛首页 Java企业应用论坛

有人真正测试过spring事务中readonly吗

浏览 18911 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-01-21   最后修改:2009-08-06

最新测试结果 start...:

ahuaxuan 在回复中说的没错,在DataSourceUtils.prepareConnectionForTransaction(con, definition)中的确会设置readonly,我之前说的DataSourceTransactionManager中不设置readonly的说法是错误的。
但在oracle下,这个readonly确实有问题,我一步步测下来,原因就是出在 con.setAutoCommit(false) 这行代码上:
1. 如果 con.setReadOnly(true) 放在 con.setAutoCommit(false) 前面,就是代码现在的做法,readonly是不起作用的。
2. 反之,如果我把DataSourceUtils.prepareConnectionForTransaction(con, definition)  代码放在它的后面的时候,readonly 起了作用。


难道oracle的驱动对这个顺序还有影响吗,有点匪夷所思啊。
不知道在其他数据库中有没有影响。

//其中, DataSourceUtils.prepareConnectionForTransaction(con, definition)中会设置con.setReadOnly(true)
protected void doBegin(Object transaction, TransactionDefinition definition) {
....
....
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);

			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
			// so we don't want to do it unnecessarily (for example if we've explicitly
			// configured the connection pool to set it already).
			
			if (con.getAutoCommit()) {
				
				txObject.setMustRestoreAutoCommit(true);
				
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}
...
...
}


最新测试结果 end...


为何readonly不起作用,有人真正测过吗?

环境
1. spring2.5 + ibatis/jdbctemplate(测了这两个) + oracle10,
2. 驱动ojdbc14.jar
3. 连接池 dbcp和c3p0都测了。

先看部分后台,证明调用的方法确实开启了readonly:
21/01/2009 16:43:01,457 <DEBUG> (org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource)- Adding transactional method [search*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly]


21/01/2009 17:10:00,864 <DEBUG> (org.springframework.jdbc.datasource.DataSourceTransactionManager)- Creating new transaction with name [com.me.service.logic.ViewService.searchLeave]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly


先在oracle里面测试下
set transaction read only;
update stu set title = 'oh,god' where id='12345'

抛错,证明oracle对read only有效:
ORA-01456: may not perform insert/delete/update operation inside a READ ONLY transaction


程序中的配置
	<aop:config>
		<aop:pointcut id="serviceOperation"
			expression="execution(* com.me.service.logic.*ServiceImpl.*(..))" />
		<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
	</aop:config>

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="search*" read-only="true" />
		</tx:attributes>
	</tx:advice>


//ViewServiceImpl:
public List searchLeave(Leave leave) {
	
        //update stu set title = 'oh,god' where id='12345'
        int j = viewDAO.updateStu();
		
	return viewDAO.searchLeave(leave);
}


以上的searchLeave方法应该抛出错误的。readonly不允许update。
但一切似乎都没有效果。







   发表时间:2009-01-21  
没有测试过,不过你可以换种配置方式:@Transactional(readonly="true")试试看,可能你这种用schema配置哪儿自己弄错了;
不过楼主不要首先怀疑spring,人家发布都几年了,如果连只读事物都没有搞定,你觉得可能吗?
0 请登录后投票
   发表时间:2009-01-21  
@Transactional(readonly="true") 也测试过,也是不行。

并不是只是怀疑spring,我只是想弄清楚其中的缘由,不然怎么能在项目中使用呢。是吧。

我相信大家很多都在项目中配了readonly,可以动手测一下。
2 请登录后投票
   发表时间:2009-01-22  
geng2483759 写道

@Transactional(readonly="true") 也测试过,也是不行。 并不是只是怀疑spring,我只是想弄清楚其中的缘由,不然怎么能在项目中使用呢。是吧。 我相信大家很多都在项目中配了readonly,可以动手测一下。

我也正在困扰中,我使用SQL 2005貌似也没有起作用。楼主要是有结果的话麻烦告知一下,非常感谢。
0 请登录后投票
   发表时间:2009-01-31   最后修改:2009-01-31
你应该仔细看一下Spring的文档,在事务那一章有明确的解释:

“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。

但是你非要在“只读事务”里面修改数据,也并非不可以,只不过对于数据一致性的保护不像“读写事务”那样保险而已。

因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可。
2 请登录后投票
   发表时间:2009-02-01  
看了楼上的论述,实在是令人难受,不得已回一篇帖子


DefaultTransactionDefinition trans = new DefaultTransactionDefinition();

trans.setReadOnly(true);
trans.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_NEVER);

以上的事务配置是绝对支持只读的,

import org.springframework.transaction.support.DefaultTransactionDefinition;
0 请登录后投票
   发表时间:2009-02-01  
拜托你好好学习一下Spring的事务好不好?PROPAGATION_NEVER你知道是什么意思嘛? 不知道的话,别在这里瞎误导,搞笑嘛。PROPAGATION_NEVER和readOnly压根两码事。PROPAGATION_NEVER是禁止事务传播,懂不懂?
9 请登录后投票
   发表时间:2009-02-04  
theone 写道
你应该仔细看一下Spring的文档,在事务那一章有明确的解释:

“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。

但是你非要在“只读事务”里面修改数据,也并非不可以,只不过对于数据一致性的保护不像“读写事务”那样保险而已。

因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可。


1. 和spring文档没有任何关系,spring事务仅仅是一层封装,最后都要调用底层驱动的setReadonly方法来开启。
2.在大多数数据库系统下,只读事务里面是不可以修改数据,并且,在同一个事务里面同一个sql读出来的同一条记录是不会变化的,这是我们开启readonly最重要的原因:我们需要能够可重复读。
3. 在一个系统中,为了保证在同一个事务中读取数据的一致性,对一系列读操作开启readonly是很重要的做法,并不仅仅是性能优化的推荐配置。
4. 最重要的是,spring的DataSourceTransactionManager确实不支持readonly,我开头的连接中已经给出了原因。
0 请登录后投票
   发表时间:2009-02-04   最后修改:2009-02-04
readonly不是用来保证“读取数据的一致性”的,隔离级别是由它前面的相邻那个属性配置的
例如:PROPAGATION_REQUIRED,REPEATABLE READ,readOnly,-MyCheckedException,3

readOnly表示对应的事务应该被最优化为只读事务,例如在使用Hibernate时避免dirty checking
1 请登录后投票
   发表时间:2009-02-04  
难道现在Connection和Transaction都被混为一谈了?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics