`
geng2483759
  • 浏览: 5605 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
文章分类
社区版块
存档分类
最新评论

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

阅读更多

最新测试结果 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。
但一切似乎都没有效果。







分享到:
评论
20 楼 panny1982 2009-10-19  
你如果纯用了jdbc那是肯定有效果的,但如果用了Ibatis,Hibernate的第三方,那么往往readonly会被忽略,其实如果你是纯粹取数据,不声明事务也没关系。
19 楼 geng2483759 2009-08-08  
<div class="quote_title">gates_lee 写道</div>
<div class="quote_div"><ol>
<li>readonly并不是所有数据库都支持的,不同的数据库下会有不同的结果。</li>
<li>设置了readonly后,connection都会被赋予readonly,效果取决于数据库的实现。</li>
<li>在ORM中,设置了readonly会赋予一些额外的优化,例如在Hibernate中,会被禁止flush等。</li>
</ol></div>
<p>oracle在odbc14的jar下是绝对支持readonly的,这点吾容置疑。但为何会出现我文中所说的现象,这才是本质问题。</p>
18 楼 gates_lee 2009-08-08  
<ol>
<li>readonly并不是所有数据库都支持的,不同的数据库下会有不同的结果。</li>
<li>设置了readonly后,connection都会被赋予readonly,效果取决于数据库的实现。</li>
<li>在ORM中,设置了readonly会赋予一些额外的优化,例如在Hibernate中,会被禁止flush等。</li>
</ol>
17 楼 geng2483759 2009-08-06  
ahuaxuan 说的没错,的确是设置了,但readonly还是不起作用,最新测试结果看我正文中的修改。
16 楼 KimShen 2009-07-27  
READ ONLY是需要底层数据库支持的! 至少MySQL中没有问题
15 楼 summeryhrb 2009-07-27  
是通过数据库的事务控制实现的,spring只是把事务控制的参数传给jdbc而已。
关于测试的问题,完全可以通过多线程模拟出来,模拟测试+源码研究
14 楼 jayxu 2009-07-27  
ahuaxuan 写道
1.readonly语义不是所有的数据库驱动都支持的。
2.在spring+hibernate的条件下,readonly有一些优化
http://www.iteye.com/topic/95124

是的

有些数据库驱动不支持readonly的

像我就从来都没能用上readonly
13 楼 ahuaxuan 2009-07-26  
geng2483759 写道
ahuaxuan 写道
1.readonly语义不是所有的数据库驱动都支持的。
2.在spring+hibernate的条件下,readonly有一些优化
http://www.iteye.com/topic/95124

说的没错, 有的数据库驱动是不支持readonly的。但在oracle下绝对支持,上面也已经验证过了。
顺便回答下你帖子里一个问题: 使用jdbc不但没有优化,压根jdbc的这个DataSourceTransactionManager就不支持readonly。因为它源代码里面没有一处调用con.setReadOnly(true)之类的方法。
而HibernateTransactionManager中正如你所说的会有这么一段:
if (definition.isReadOnly() && txObject.isNewSession()) {
                                // Just set to NEVER in case of a new Session for this transaction.
                                session.setFlushMode(FlushMode.NEVER);
                        }


详细分析: http://www.iteye.com/problems/10624

这位同学,你最好修改一下你的结论,DataSourceTransactionManager不是不设置readonly,只是你没有看到,DataSourceTransactionManager#doBegin()方法中有这么一句:Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);,你跟进去看看会发现:


public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition)
			throws SQLException {

		Assert.notNull(con, "No Connection specified");

		// Set read-only flag.
		if (definition != null && definition.isReadOnly()) {
			try {
				if (logger.isDebugEnabled()) {
					logger.debug("Setting JDBC Connection [" + con + "] read-only");
				}
				con.setReadOnly(true);
			}
			catch (Throwable ex) {
				// SQLException or UnsupportedOperationException
				// -> ignore, it's just a hint anyway.
				logger.debug("Could not set JDBC Connection read-only", ex);
			}
		}

		。。。。。。。。。。。。。。。。。
	}


所以即使是spring+jdbc还是会设置readonly的
12 楼 geng2483759 2009-07-24  
ahuaxuan 写道
1.readonly语义不是所有的数据库驱动都支持的。
2.在spring+hibernate的条件下,readonly有一些优化
http://www.iteye.com/topic/95124

说的没错, 有的数据库驱动是不支持readonly的。但在oracle下绝对支持,上面也已经验证过了。
顺便回答下你帖子里一个问题: 使用jdbc不但没有优化,压根jdbc的这个DataSourceTransactionManager就不支持readonly。因为它源代码里面没有一处调用con.setReadOnly(true)之类的方法。
而HibernateTransactionManager中正如你所说的会有这么一段:
if (definition.isReadOnly() && txObject.isNewSession()) {
                                // Just set to NEVER in case of a new Session for this transaction.
                                session.setFlushMode(FlushMode.NEVER);
                        }


详细分析: http://www.iteye.com/problems/10624
11 楼 ahuaxuan 2009-07-23  
1.readonly语义不是所有的数据库驱动都支持的。
2.在spring+hibernate的条件下,readonly有一些优化
http://www.iteye.com/topic/95124
10 楼 pantiansheng 2009-07-23  
By setting the JDBC connection to read-only, Spring prevents a distracted user from persisting changes by flushing the Hibernate session to the database.

9 楼 grave 2009-02-04  
难道现在Connection和Transaction都被混为一谈了?
8 楼 daquan198163 2009-02-04  
readonly不是用来保证“读取数据的一致性”的,隔离级别是由它前面的相邻那个属性配置的
例如:PROPAGATION_REQUIRED,REPEATABLE READ,readOnly,-MyCheckedException,3

readOnly表示对应的事务应该被最优化为只读事务,例如在使用Hibernate时避免dirty checking
7 楼 geng2483759 2009-02-04  
theone 写道
你应该仔细看一下Spring的文档,在事务那一章有明确的解释:

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

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

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


1. 和spring文档没有任何关系,spring事务仅仅是一层封装,最后都要调用底层驱动的setReadonly方法来开启。
2.在大多数数据库系统下,只读事务里面是不可以修改数据,并且,在同一个事务里面同一个sql读出来的同一条记录是不会变化的,这是我们开启readonly最重要的原因:我们需要能够可重复读。
3. 在一个系统中,为了保证在同一个事务中读取数据的一致性,对一系列读操作开启readonly是很重要的做法,并不仅仅是性能优化的推荐配置。
4. 最重要的是,spring的DataSourceTransactionManager确实不支持readonly,我开头的连接中已经给出了原因。
6 楼 theone 2009-02-01  
拜托你好好学习一下Spring的事务好不好?PROPAGATION_NEVER你知道是什么意思嘛? 不知道的话,别在这里瞎误导,搞笑嘛。PROPAGATION_NEVER和readOnly压根两码事。PROPAGATION_NEVER是禁止事务传播,懂不懂?
5 楼 xiao007hua 2009-02-01  
看了楼上的论述,实在是令人难受,不得已回一篇帖子


DefaultTransactionDefinition trans = new DefaultTransactionDefinition();

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

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

import org.springframework.transaction.support.DefaultTransactionDefinition;
4 楼 theone 2009-01-31  
你应该仔细看一下Spring的文档,在事务那一章有明确的解释:

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

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

因此,“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可。
3 楼 workman93 2009-01-22  
geng2483759 写道

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

我也正在困扰中,我使用SQL 2005貌似也没有起作用。楼主要是有结果的话麻烦告知一下,非常感谢。
2 楼 geng2483759 2009-01-21  
@Transactional(readonly="true") 也测试过,也是不行。

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

我相信大家很多都在项目中配了readonly,可以动手测一下。
1 楼 myyate 2009-01-21  
没有测试过,不过你可以换种配置方式:@Transactional(readonly="true")试试看,可能你这种用schema配置哪儿自己弄错了;
不过楼主不要首先怀疑spring,人家发布都几年了,如果连只读事物都没有搞定,你觉得可能吗?

相关推荐

    Spring 管理事务(传播特性、隔离级别、readonly).rar

    本知识点将深入探讨Spring中的事务管理,主要包括事务的传播特性、隔离级别以及readonly属性。 1. 事务的传播特性: 在Spring中,事务的传播特性定义了在一个事务方法被另一个事务方法调用时,应该如何处理事务...

    Spring事务原理、Spring事务配置的五种方式

    Spring事务原理是指Spring框架中的一种机制,用于管理事务,并提供了多种配置方式。事务是指一系列的操作,作为一个整体执行,如果其中某个操作失败,整个事务将回滚。Spring事务原理围绕着两个核心:...

    spring声明事务的配置

    在Spring 1.x中,声明式事务有两种主要的配置方式,第一种是通过XML配置逐个为每个业务类创建事务代理。首先,你需要声明一个事务管理器,如`HibernateTransactionManager`,然后定义业务层的bean,并为其创建一个...

    Spring事务类型祥解

    这种方式灵活性较高,但会导致代码中事务管理的逻辑过于耦合,不易维护。在Spring中,可以使用`@Transactional`注解的`propagation`属性配合`TransactionTemplate`进行更安全的编程式事务管理。 2. **声明式事务...

    spring事务配置的5中方式

    在Spring中,事务配置主要涉及到三个核心组件:DataSource、TransactionManager和代理机制。下面将详细介绍Spring的五种事务配置方式。 1. **基于XML的事务配置** - **每个Bean都有一个代理**: 在这种配置方式中...

    Spring事务五种不同的代理配置

    总的来说,掌握 Spring 事务管理的五种配置方式,有助于我们在开发中更好地控制事务边界,保证数据的一致性和完整性。理解并灵活运用这些知识,能够提升我们的代码质量,降低系统风险,提高系统的稳定性和可靠性。

    Spring事务管理的三种方式

    本篇文章将详细探讨Spring中的三种事务管理方式:编程式事务管理、声明式事务管理和基于注解的事务管理。 首先,编程式事务管理是通过编码来控制事务的开始、提交、回滚等操作。Spring提供了...

    spring_事务管理(实例代码)

    在Spring中,我们可以配置事务的传播行为,比如REQUIRED(默认,如果当前存在事务,则加入当前事务,否则新建一个事务)、PROPAGATION_SUPPORTS(如果当前存在事务,则加入,否则不开启事务)、PROPAGATION_REQUIRES...

    Spring 事务代理配置

    在深入探讨Spring事务代理配置之前,我们先简要回顾一下Spring...通过以上步骤,我们就可以在Spring中成功配置事务代理,使得应用程序中的业务方法能够自动进行事务管理,极大地提高了代码的可维护性和事务的一致性。

    Spring的事务配置的五种方式

    在Spring中,事务管理通常分为三部分:DataSource、TransactionManager和代理机制。DataSource是数据源,TransactionManager是事务管理器,而代理机制则是实现事务控制的关键。 1. **基于XML的AOP代理配置** 这是...

    Spring事务配置的五种方式

    Spring 事务管理是其核心特性之一,用于确保在执行数据库操作时的一致性和可靠性。它提供了五种不同的配置方式来适应不同的应用场景。以下是对这些配置方式的详细解释: 1. **基于代理的事务管理(Proxy-based ...

    spring注解事务实现demo

    注解中可以包含多个属性,如`value`(指定事务管理器)、`propagation`(事务传播行为)、`isolation`(事务隔离级别)、`readOnly`(是否只读事务)等,以定制事务的行为。 3. **事务传播行为** 事务传播行为定义...

    实例详解Spring JDBC事务管理.doc

    在本文中,我们将以JDBC事务管理为例,详细介绍Spring的事务管理机制。 Spring事务管理机制 Spring的事务管理机制是基于PlatformTransactionManager接口的实现的,该接口定义了三个方法:getTransaction、commit...

    spring事务管理1

    Spring 事务管理是Java开发中的核心概念,尤其是在企业级应用中,它确保了数据的完整性和一致性。在Spring框架中,事务管理通过实现ACID(原子性、一致性、隔离性和持久性)属性来保证数据库操作的正确性。 **原子...

    Spring相关测试3

    在Spring中,可以设置`readOnly=true`,告知事务管理器该事务不需要修改数据。 接下来,我们看看两种事务配置方式: - **基于注解的事务管理**:这是Spring 2.5引入的新特性,通过在方法上使用`@Transactional`...

    Spring中的事务控制

    在Spring中,`@Transactional`注解可以设置多个属性,如`propagation`(事务传播行为),`isolation`(事务隔离级别),`timeout`(事务超时时间),`readOnly`(是否只读事务)和`rollbackFor`/`noRollbackFor`...

    使用Spring的声明式事务----Annotation注解方式

    在Spring中,我们可以使用XML配置文件来声明事务,但更常见的是通过Java注解来完成。这里我们将重点讨论Annotation注解方式。主要涉及的注解有`@Transactional`,`@Rollback`以及`@Transactional(propagation=...

    spring框架的学习--事务

    在Spring中,事务传播行为有七种,包括REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER和NESTED。每种行为都对应不同的事务处理策略,比如REQUIRED是默认行为,意味着如果当前存在事务,则加入...

    Spring中的事务管理

    声明式事务管理是Spring中非常受欢迎的特性,因为它允许开发者在不编写任何事务控制代码的情况下,通过配置来管理事务。这种方式使得事务管理与业务逻辑解耦,提高了代码的可维护性。 #### 基于注解的声明式事务...

Global site tag (gtag.js) - Google Analytics