Spring Transactional ReadOnly 和 不加Transactional的区别
在网络上搜了下,答案如下两个。
说下我的理解,其实不管你写不写transaction
,事务是肯定有的。只是默认单条sql一个事务
,如果我们在Service
层的方法上加Transaction
注解,那么事务的范围就会扩大,包含在service
方法执行的所有sql
。Mysql
默认的隔离级别是可以防止不可重复读
的,所以,加上Transactional
,里面如果涉及多次查询一条记录,中间即使被其它事务修改,这条记录还是一样的。这和是否加readOnly
没有关系,加了只会告诉数据库底层驱动,达到一个好的效率,仅此而已。但如果不加Transactional
,那么每条sql
一个事务,中间被其它事务改了数据,都会实时读取到最新值。
以上是我的理解,欢迎讨论指教!
作者:lee
链接:https://www.zhihu.com/question/39074428/answer/81473880
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持
read-only="true"表示该事务为只读事务,比如上面说的多条查询的这种情况可以使用只读事务,
由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。
(1)在JDBC中,指定只读事务的办法为: connection.setReadOnly(true);
(2)在Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER);
此时,Hibernate也会为只读事务提供Session方面的一些优化手段
(3)在Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“read-Only”
或者用注解方式@Transactional(readOnly=true)
Spring中设置只读事务是利用上面两种方式(根据实际情况)
在将事务设置成只读后,相当于将数据库设置成只读数据库,此时若要进行写的操作,会出现错误。
详见:https://www.zhihu.com/question/39074428
经过测试你的这个说法有点问题,不知道哪里有问题:
测试环境:
@Transactional 并没有加 readonly的参数
测试一:
> 我在一个service中写了一个循环查询一个表中的记录总数,中间使用sleep方法进行时间阻断,然后在请求开始之后查询出第一条记录之后,我更改数据库的数据量,但是程序并没有重新查询,而是一直拿的缓存的数据。也就是说,没有加readonly的情况下,在一个事务中,即便更改数据库内容,也不会重新被查询出来。
测试二:
> 我在service中写了一个好几个查询,第一个查询table1的记录总数,第二个查询table2的总数,第三个查询table3的总数,每个查询中间也都使用sleep进行时间阻断,我在第一个查询执行之后,马上修改table3的数据量,可是在查询的结果里面仍然是修改之前的记录总数,也就是说,在这种情况,即便没有readonley,在一个事务中,修改了数据库的内容,也不会直接反应在结果中。
测试三:
> 我在测试二的基础上去掉了@Transactional,也就是不要事务了,这样的话,每一个查询都会到连接池中拿新的链接。也就是只要修改了数据,那么轮到查询的时候就会将最新的数据取出来!
测试四:
> 在测试二的基础上加了readonly=true,结果跟测试二一样,性能跟测试二也没啥区别。这个倒无所谓,可能是因为本来都很快的原因。
综上所述:只要开通了@Transactional就能保证数据的一致性,能保证你在事务开始之前其他的修改对你的查询不影响,跟加不加readonly没有区别。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本和我理解的一样,下面说下我的理解:
楼主说的基本没啥大毛病