多线程读数据库会造成以下问题:
一.脏读
线程b读取了线程a尚未提交的数据,并且进行了一系列操作,最终得到错误结果
二.重复读
线程a读取两次数据,中间线程b新增了数据,造成了线程a两次读取内容不一致
三.幻读
线程a读取两次数据,中间线程b更新了数据,造成了线程a两次读取内容不一致
通过提供事务的隔离,可以解决以下问题
隔离级别 | 脏读 | 重复读 | 幻读 |
READ_UNCOMMITED | y | y | y |
READ_COMMITED | n | y | y |
REPEATABLE_READ | n | n | y |
SERIALIZABLE | n | n | n |
如果有了事务之间的相互调用,那么怎么办,如:
@Transaction
funca
@Transaction
funcb
funca(){
funcb()
}
a调用了b,那么事务是如何执行的,有以下七种情况:
PROPAGATION_REQUIRED:如果a有,b加入a,如果没有,自己新建
PROPAGATION_REQUIRED_NEW:如果a有,b新建一个,将a的挂起,如果没有,自己新建
PROPAGATION_NESTED:如果a有事务,在a中嵌套b的事务,如果a回滚,b也要回滚,如果没有,自己新建
PROPAGATION_SUPPORTS:如果有,则加入,如果没有,算了。
PROPAGATION_NOT_SUPPORTS:如果没有,就不用,如果a有,也不用,挂起来。
PROPAGATION_NEVER:反正我不用,如果a有,我就报错。
PROPAGATION_MANDATORY:如果a没有,我就报错。
另外,spring提供了:
timeout,来控制超时。
readOnly,当前事务是否是只读事务,提高效率。
rollbackFor,throwable的子类,哪些错误引起回滚。
noRollbackFor,那些错误不会滚。