Spring Transactional ReadOnly 和 不加Transactional的区别

发布于 2022-09-04 14:11:45 字数 2017 浏览 11 评论 0

在网络上搜了下,答案如下两个。
说下我的理解,其实不管你写不写transaction,事务是肯定有的。只是默认单条sql一个事务,如果我们在Service层的方法上加Transaction注解,那么事务的范围就会扩大,包含在service方法执行的所有sqlMysql默认的隔离级别是可以防止不可重复读的,所以,加上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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的鱼塘能养鲲 2022-09-11 14:11:46

基本和我理解的一样,下面说下我的理解:

1.我认为单条sql执行的时候是没有事务的,在数据库层面已经保证了该sql的原子性,再加事务只会浪费性能。而且spring的事务是面向切面的,你没有做相关配置,它肯定不会多此一举给你加上事务。
2.在执行多条查询语句时加上事务是为了保证数据前后一致性,只要加上Transactional就能解决这个问题。
3.事务由多个级别,级别越高数据库为了提供相关支持肯定也会占用更多资源,而且数据库也考虑到了事务中只做查询的这个问题,所以它提供了read-only这个状态,相应数据做的支持也会少很多,占用的资源就自然少了。
无畏 2022-09-11 14:11:46

楼主说的基本没啥大毛病

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文