spring 事务相关
https://www.jianshu.com/p/2f79ee33c8ad
https://www.freesion.com/article/24951147266/
https://segmentfault.com/a/1190000013341344
https://blog.csdn.net/trigl/article/details/50968079
只读事务(@Transactional(readOnly = true))的一些概念
念:从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)
应用场合:
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】
怎样设置:
对于只读查询,可以指定事务类型为readonly,即只读事务。
由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。
(1)在JDBC中,指定只读事务的办法为: connection.setReadOnly(true);
(2)在Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER);
此时,Hibernate也会为只读事务提供Session方面的一些优化手段
(3)在Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“readOnly”
或者用注解方式@Transactional(readOnly=true)
【 if the transaction is marked as read-only, Spring will set the Hibernate Session’s flush mode to FLUSH_NEVER,
and will set the JDBC transaction to read-only】也就是说在Spring中设置只读事务是利用上面两种方式
在将事务设置成只读后,相当于将数据库设置成只读数据库,此时若要进行写的操作,会出现错误
念:从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)
应用场合:
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】
怎样设置:
对于只读查询,可以指定事务类型为readonly,即只读事务。
由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。
(1)在JDBC中,指定只读事务的办法为: connection.setReadOnly(true);
(2)在Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER);
此时,Hibernate也会为只读事务提供Session方面的一些优化手段
(3)在Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“readOnly”
或者用注解方式@Transactional(readOnly=true)
【 if the transaction is marked as read-only, Spring will set the Hibernate Session’s flush mode to FLUSH_NEVER,
and will set the JDBC transaction to read-only】也就是说在Spring中设置只读事务是利用上面两种方式
在将事务设置成只读后,相当于将数据库设置成只读数据库,此时若要进行写的操作,会出现错误
很多人认为MySQL只读事务没啥用,有点鸡肋,以前我也这么认为,自从认真研究了事务的隔离级别和事务的并发问题后,发现这个只读事务其实并不是大家想象的那么无用。下面举一个实际开发中可能会遇到的例子来说明只读事务的作用。
展示用户列表的需求,后台从数据库查询用户列表返回给前端分页显示,分页通过数据库的分页功能实现,前端分页插件需要后台返回总共有多少条记录,以便渲染分页效果,后端返回的数据大概长这样:
{ total:8, // 总共多少条记录 list: [...] // 只包含当前页的记录 }
所以后台需要查询两次数据库:查询总数和查询列表。(有人会说,就不能全部查询出来再在代码里通过sublist分页吗?我这个例子里只有8条数据,万一有80万条数据呢,全部加载到内存不怕内存溢出吗?)
假设我先查询总数返回的是8条,然后在我查询列表前数据表中插入了一条数据,结果我查询列表得到了9条数据。接着就在页面看到了神奇的一幕:总共8条数据,按照每页显示10条来分页,结果第一页有9条数据,这不是有毛病么?
是的,上述情景就是典型的不可重复读问题。我们都知道有个事务隔离级别叫“REPEATABLE READ”,此隔离级别可以实现可重复读,但是别忘了事务的隔离级别前提是要有事务啊,两个查询语句都没有处于事务中,还谈啥事务的隔离级别啊?还谈啥可重复读啊?这个我还真做过实验,就算事务的隔离级别是可重复读级别,两个查询语句没有处于事务中时,还是会出现不可重复读问题。
所以在REPEATABLE READ隔离级别下需要结合事务才能实现可重复读,而只读事务比读写事务更高效,因为不需要写数据,所以做了一些优化。没错,只读事务就是这么来的。
还有人说只读事务不能进行写操作,这确实没错,但我认为不能写是结果而不是目的。