Spring的事务经常会有这样的配置:

1

或者这样的注记:

1 @Transactional(readOnly = true)

正好我正在做的项目中这样配置了,而且偶然发现配置了不生效,本着“不弄明白对不起祖国对不起人民”的精神,参考了不少帖子和文档,总结了网上形形色色的答案,稍有收获,规整如下,不正确请指出。

1 readonly并不是所有数据库都支持的,不同的数据库下会有不同的结果。2 设置了readonly后,connection都会被赋予readonly,效果取决于数据库的实现。3 在ORM中,设置了readonly会赋予一些额外的优化,例如在Hibernate中,会被禁止flush等。

经实践,上面的观点基本正确。

环境:Spring-3.1.1、jdk6、oracle-11gR2、mysql-5.6.16、ojdbc6、mysql-connector-java-5.1.31、ibatis-2.3.4.726等,使用的Spring的DataSourceTransactionManager 事务管理器。

查看DataSourceTransactionManager 相关代码可知readOnly值最终是传给Connection的:

1 //Set read-only flag.

2 if (definition != null &&definition.isReadOnly()) {3 try{4 if(logger.isDebugEnabled()) {5 logger.debug("Setting JDBC Connection [" + con + "] read-only");6 }7 con.setReadOnly(true);8 }9 catch(SQLException ex) {10 Throwable exToCheck =ex;11 while (exToCheck != null) {12 if (exToCheck.getClass().getSimpleName().contains("Timeout")) {13 //Assume it's a connection timeout that would otherwise get lost: e.g. from JDBC 4.0

14 throwex;15 }16 exToCheck =exToCheck.getCause();17 }18 //"read-only not supported" SQLException -> ignore, it's just a hint anyway

19 logger.debug("Could not set JDBC Connection read-only", ex);20 }21 catch(RuntimeException ex) {22 Throwable exToCheck =ex;23 while (exToCheck != null) {24 if (exToCheck.getClass().getSimpleName().contains("Timeout")) {25 //Assume it's a connection timeout that would otherwise get lost: e.g. from Hibernate

26 throwex;27 }28 exToCheck =exToCheck.getCause();29 }30 //"read-only not supported" UnsupportedOperationException -> ignore, it's just a hint anyway

31 logger.debug("Could not set JDBC Connection read-only", ex);32 }33 }

1、在oracle下测试,发现不支持readOnly,也就是不论Connection里的readOnly属性是true还是false均不影响SQL的增删改查;

2、在mysql下测试,发现支持readOnly,设置为true时,只能查询,若增删改会异常:

1 Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed2 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)3 at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:792)

3、为了排除各种框架封装的影响,写JDBC原生代码也是相同的结论。

====================疑问的分隔线==============================================

网上的各种资料里众说纷纭:

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

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

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

---------------------------------------------

早期的提问会有这样的结论:

readOnly对oracle不生效是因为:

1 con.setReadOnly(true);2 con.setAutoCommit(false);

autoCommit与readOlny赋值的顺序对其有影响,readonly在后则生效,readolny在前是无效的可进行insert/update/delete操作。

同样,DataSourceTransactionManager 里也是因为这个原因:

1 Integer previousIsolationLevel =DataSourceUtils.prepareConnectionForTransaction(con, definition);2 txObject.setPreviousIsolationLevel(previousIsolationLevel);3

4 //Switch to manual commit if necessary. This is very expensive in some JDBC drivers,5 //so we don't want to do it unnecessarily (for example if we've explicitly6 //configured the connection pool to set it already).

7 if(con.getAutoCommit()) {8 txObject.setMustRestoreAutoCommit(true);9 if(logger.isDebugEnabled()) {10 logger.debug("Switching JDBC Connection [" + con + "] to manual commit");11 }12 con.setAutoCommit(false);13 }

因为DataSourceUtils.prepareConnectionForTransaction(con, definition)里会先设置readOnly属性,导致readOnly对oracle不生效;

-------------------------------------------------

他们的实践结果使我不得不相信他们说的真是这样,但以我现在的环境测试,不管什么顺序均无影响,readOnly就是对oracle不生效;看那些帖子时间已是几年前,版本差别太大,已无从考证……

====================疑问的分隔线==============================================

我也看到有人找到oracle的官方文档链接里句子来说原因:

10.1、10.2和11.1的文档里写着:

1 Read-only connections are supported by the Oracle server, but not by the Oracle JDBC drivers.

11.2的文档里写着:

1 Read-only connections are supported by Oracle JDBC drivers, but not by the Oracle server.

再结合oracle可以设置 “set transaction read only”,搞不清楚哪个对哪个错,反正就是不支持。。。

java 数据库 事务 只读_Spring 事务 readOnly 到底是怎么回事?相关推荐

  1. java spring 事务传播_spring事务传播机制实例讲解

    天温习spring的事务处理机制,总结如下 对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011 spri ...

  2. java事务类型_Spring事务类型祥解

    大家可能在spring中经常看到这样的定义: PROPAGATION_REQUIRED,readOnlyPROPAGATION_REQUIRED 估计有好多朋友还没有弄清楚里面的值的意思,仔细看完下面 ...

  3. 事务例子_Spring事务专题(四)Spring中事务的使用、抽象机制及模拟Spring事务实现...

    Spring中事务的使用示例.属性及使用中可能出现的问题 前言 本专题大纲如下: 「对于专题大纲我又做了调整哈,主要是希望专题的内容能够更丰富,更加详细」,本来是想在源码分析的文章中附带讲一讲事务使用 ...

  4. spring的事务隔离_spring事务基础及常见问题详解

    一:基础知识介绍 1.1:事务四个特性:ACID 原子性(Atomicity):事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成,要么全部失败. 一致性(Consistency) ...

  5. java 回滚异常_Spring事务管理只对出现运行期异常进行回滚

    Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚. 如果一个方法抛出Exception或者Checked异常,Spring事务管理默 ...

  6. java spring 事务提交_Spring 事务提交之后再执行操作

    Spring代码实现: import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ster ...

  7. java 数据库 事务 只读_不使用事务和使用只读事务的区别

    转转转,,还需要具体验证( 决定把readonly类型的事务完全去掉,以提高性能,这里有讨论:http://stackoverflow.com/questions/2562865/spring-tra ...

  8. java事务 Dao层_spring事务到底用于service层还是dao层

    Spring事务为业务逻辑进行事务管理,保证业务逻辑上数据的原子性. 事务得根据项目性质来细分:事务可以设置到三个层面(dao层.service层和web层). 第一:web层事务,这一般是针对那些安 ...

  9. spring配置mysql事务管理_Spring 数据库事务管理机制

    要点1 Spring事务管理方法编程式事务(TransactionTemplate.PlatformTransactionManager) 声明式事务(配置式.注解式) 2 Spring 注解 @Tr ...

最新文章

  1. Activity的setContentView的流程
  2. 图像增强之对比度拉伸
  3. 直接打开php非法请求
  4. hibernate级联操作详解
  5. 【LeetCode】4月2日打卡-Day18-矩阵操作
  6. 一维数组去重处理法一(C语言)
  7. 有奖征文 | 蒋涛邀你悦评《UNIX传奇》新书,赢技术进阶好礼
  8. 1047. 编程团体赛(20)-PAT乙级真题
  9. 第二次作业(贪吃蛇)
  10. C++笔记(1):使用STL中sort()对struct排序
  11. 文件名的查找——find
  12. invalid use of constructor as a template 编译错误
  13. ScalaReact式编程书
  14. math.floor
  15. linux下proc目录部分说明
  16. 第二人生的源码分析(三十)UDP接收数据和Windows网络关闭
  17. 超详细图文教程·阿里云免费学生ECS云服务器领取并使用全过程(部署Python多人聊天室程序)
  18. js原生css修改,原生js获取、添加、修改_非行间css样式
  19. 解决虚拟机ubuntu20.04不能连外网问题
  20. iOS10新特性——————陈Hong鑫

热门文章

  1. 电动汽车巨作|新能源汽车简史:电动汽车沉浮录
  2. 【数字图像处理matlab】(HSI变换融合算法)
  3. 推荐10款效率可以翻倍的IDEA插件,撸码利器
  4. 爱因斯坦《社会和个人 》
  5. 腹有诗书气自华——记环宇通软CEO骆永华 1
  6. Scikit入门指南
  7. 如何判断自己外网IP是否为真实公网IP,以及解决方案
  8. bzoj-2818 Gcd
  9. 如何将视频上传到网站服务器,如何将本地视频上传到云服务器
  10. MVC模式和DDD模式对比,谁才是银弹?