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

本文探讨了在Java中只读事务与不使用事务的区别,以及事务的ACID属性。Oracle和MySQL对于只读事务的处理方式有所不同,只读事务在保证数据一致性的同时提供了性能优化。在MySQL的InnoDB表中,不使用只读事务可能导致读取的数据不一致。文章通过实验展示了在不同事务设置下查询结果的变化,并提到了在Oracle平台上的可能表现。
摘要由CSDN通过智能技术生成

转转转,,还需要具体验证(

决定把readonly类型的事务完全去掉,以提高性能,这里有讨论:http://stackoverflow.com/questions/2562865/spring-transaction-readonly

)。。。

如果只提交一个查询,有必要用事务吗?这个问题之前已经讨论过

http://forum.javaeye.com/viewtopic.php?t=1603

但是并没有得出明确的结论。先让我们看看事务的定义:

引用:

Transactions are described in terms of ACID properties, which are as follows:

n Atomic: all changes to the database made in a transaction are rolled back if any

change fails.

n Consistent: the effects of a transaction take the database from one consistent

state to another consistent state.

n Isolated: the intermediate steps in a transaction are not visible to other users of

the database.

n Durable: when a transaction is completed (committed or rolled back), its effects

persist in the database.

即ACID的定义,从上面看来,似乎除了isolated之外,和只读查询都没有关系。那么是否只读查询不需要事务呢?

再看看Oracle对于只读事务的定义:

引用:

Read-Only Transactions

By default, Oracle guarantees statement-level read consistency. The set of data returned by a single query is consistent with respect to a single point in time. However, in some situations, you might also require transaction-level read consistency. This is the ability to run multiple queries within a single transaction, all of which are read-consistent with respect to the same point in time, so that queries in this transaction do not see the effects of intervening committed transactions.

If you want to run a number of queries against multiple tables and if you are not doing any updating, you prefer a read-only transaction. After indicating that your transaction is read-only, you can run as many queries as you like against any table, knowing that the results of each query are consistent with respect to the same point in time.

Oracle默认情况下保证了SQL语句级别的读一致性,即在该条SQL语句执行期间,它只会看到执行前点的数据状态,而不会看到执行期间数据被其他SQL改变的状态。

而Oracle的只读查询(read-only transaction)则保证了事务级别的读一致性,即在该事务范围内执行的多条SQL都只会看到执行前点的数据状态,而不会看到事务期间的任何被其他SQL改变的状态。

因此我们可以得出结论:

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;

如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

只读事务与读写事务区别

对于只读查询,可以指定事务类型为readonly,即只读事务。由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。

在JDBC中,指定只读事务的办法为:

connection.setReadOnly(true);

在Hibernate中,指定只读事务的办法为:

session.setFlushMode(FlushMode.NEVER);

此时,Hibernate也会为只读事务提供Session方面的一些优化手段

在Spring的Hibernate封装中,指定只读事务的办法为:

bean配置文件中,prop属性增加“readOnly”

我在MySQL4.1试验了一下,过程和结果如下:

数据库:MySQL4.1

表类型:InnoDB

Spring:1.1.2

Hibernate:2.1.7

使用Spring的声明式事务管理

试验过程如下:

不设置查询方法的事务类型(即不需要事务):访问查询页面,后台执行Spring的Bean方法,让 Hibernate发送select语句,然后手工在MySQL里面修改该记录某字段值,再访问查询页面,发现被修改过的字段值并没有变 化,Hibernate输出的log显示,数据库还是把老的字段值返回,而没有返回新的字段值。

设置查询方法的事务类型(只读事务):访问查询页面,后台执行Spring的Bean方法,让Hibernate发 送select语句,然后手工在MySQL里面修改该记录某字段值,再访问查询页面,发现被修改过的字段值已经变化,Hibernate输出的log显 示,数据库返回新的字段值。

这个试验说明,至少在MySQL4.1的InnoDB情况下,不使用只读事务的查询将无法读取到数据更新值,必须使用只读事务来保证读记录的数据一致性。这个结果非常令我诧异,和我预期完全两样。

我将在Oracle平台上试试看会有什么样的结果。

BTW: 如果MySQL的表类型改为MyISAM,那么即使不设置事务,也不会出现读数据不一致的现象。

oracle有两种方法保证在事务级读数据一致性(Transaction-Level Read Consistency)

一是用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ,

当执行这条命令后读数据时会产生一些重复copy, 你也可以做数据修改, 但在大量数据修改的情况下容易造成deadlock或异常, 用commit或rollback将把ISOLATION LEVEL设回为缺省模式read committed,

二是用SET TRANSCATION READ ONLY

当执行这条命令时数据库会生成一个快 照的latch, 这个latch会耗费一些resource, 如果你想进行数据修改会导致异常. 用commit或rollback会把latch释放掉, 也将把ISOLATION LEVEL设回为缺省模式read committed,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值