查询操作方法需要使用事务吗?

mysql的RR不是完全基于mvcc的Snapshot Isolation,而是mvcc+lock混合实现的,比如有范围查询,mysql会上gap lock,如果有unindexed row update,即使只有一个row行匹配,RR模式下update也会持有多个lock,直到事务结束。

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

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

引用:

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”


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

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


“还有mysql默认是自动提交,如果不加事务的话,每个select sql都会自动的开启事务和提交事务,开销是不是要比都放在一个事务里要高?” 这个问题要看具体情况,定性的分析下

如果pure read,RR或者RC,那么多个select一起提交跟每个select提交一次,性能相差不会太大,每个事物申请txID的时候在mysql内部会有并发冲突,但这个时间跟sql解析,查询优化,磁盘IO跟,可以忽略;

读写混合场景,如果多个select放一个事务,要看这个batch读事务,跟包含写操作的事务之间有没有锁冲突;假如是RR(不要以为MVCC了就没有锁冲突,范围查询也有gap lock),冲突的可能性比较大,那最好每个select单独提交,如果RC应该区别不大。

你可能感兴趣的:(查询操作方法需要使用事务吗?)