开发者社区> 问答> 正文

oracle 并发执行 for update 语句遇到阻塞问题

各位有没有遇到过 oracle 并发执行 for update 语句遇到阻塞问题?
来源:云原生后端社区

展开
收起
Atom 2020-04-25 15:04:01 2978 0
1 条回答
写回答
取消 提交回答
  • 按道理,一条 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对象时会发生阻塞。


    来源:云原生后端社区

    2020-04-25 15:04:38
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
PostgresChina2018_樊文凯_ORACLE数据库和应用异构迁移最佳实践 立即下载
PostgresChina2018_王帅_从Oracle到PostgreSQL的数据迁移 立即下载
Oracle云上最佳实践 立即下载

相关镜像