各位有没有遇到过 oracle 并发执行 for update 语句遇到阻塞问题?
来源:云原生后端社区
按道理,一条 sql 语句 commit 或 rollback 了会释放数据库资源。autocommit 可以在三个地方设置,第一层框架层 mybatis,第二层数据库连接池,第三层数据库,而我看过一些 Spring 的事务管理器以及 Spring 整合 Mybatis 的 jdbc 事务管理器,发现数据库连接池的 autocommit 设置会覆盖掉框架层 mybatis 的 autocommit 设置,而 mybatis 的 autocommit 默认为 false,mybatis 的底层源码 commit 方法,会首先判断 connection 对象是否已提交,如果提交了就不再重复提交。从上面的分析得出,如果我们用了 mybatis,默认情况下执行一条 sql 都会帮我们 commit,也即是如果不加 spring 的事务,每条 sql 都是一个事务。基于上面的分析我试过了 mysql 数据的 autocommit 为 true 和 false 的并发执行,发现并不会阻塞,都会提交。oracle 数据库 autocommit 默认为 false,我试过了并发执行,发现 sql 如果在同一个 connection 对象(ID相同)执行,不会阻塞,如果并发执行时,有两个 connection(ID不同)对象,就会发生阻塞。按道理,mybatis执行每条sql都会自动帮我们commit了,也就是执行完for update语句之后就会释放,不存在阻塞。但现在就出现了mysql不会阻塞,而oracle会发生阻塞。基于上面的实战分析,我有将for update语句外面包装一层spring事务,这种情况下发现oracle并不会阻塞。按道理说,如果不加spring事务,mybatis会为每条sql commit,如果数据库连接池的autocommit=true,那么也就是连接对象帮我们提交了,mybatis不会重复提交。spring整个mybatis下的SpringManagedTransaction事务管理器。不加spring事务,mybatis同样会commit。虽然for update平时很少用,但是公司有些地方用,按照常识来说,我们一般都会将for update丢到spring事务里面,先for update锁住资源,然后执行一些涉及事务的操作,最后才通过spring事务提交commit,而我们公司有些人忘记将for update语句丢到spring事务了,导致了并发时发生阻塞,按照我的常规理解,这应该是for update语句此时不生效,应为执行完立马被mybatis给commit掉了,此时发生并发脏数据才是正常。然后我用mysql来测试,发现如我想的一毛一样,这时候for update不会有锁住资源,执行完就被commit释放掉了。是不是因为oracle并不会马上commit?导致了如果出现两个connection对象时会发生阻塞。
来源:云原生后端社区
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。