Spring 事务 readOnly 到底是怎么回事?

引用文章:(https://www.cnblogs.com/hackem/p/3890656.html)

环境: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                         throw ex;
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                         throw ex;
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 allowed
2     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
3     at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:792)

3、为了排除各种框架封装的影响,写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 explicitly
 6             // 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不生效;

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

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

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

有人找到oracle的官方文档链接里句子:

http://docs.oracle.com/cd/B14117_01/java.101/b10979/tips.htm#i1007231

http://docs.oracle.com/cd/B19306_01/java.102/b14355/apxtips.htm#i1007231

http://docs.oracle.com/cd/B28359_01/java.111/b31224/apxtips.htm#i1007231

http://docs.oracle.com/cd/E11882_01/java.112/e16548/apxtips.htm#i1007231

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.

总之越看越糊涂…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值