美文网首页
Mybatis SqlSession嵌套使用bug

Mybatis SqlSession嵌套使用bug

作者: yoga0108 | 来源:发表于2017-03-19 22:43 被阅读0次

    摘要

    工作中有使用Mybatis,碰到一种情况。

    try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
       //dao delete from t1 where jid = 2; ----dao1
       //dao insert into t1(sid, jid) where jid=2; --dao2
       session.flushstatement --flush1
       try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false))  {
         //dao insert into t1() ---dao3 
         session.flushstatement --- flush2
       }
    }
    这样使用在flush2的时候,mysql报错,lock wait time out
    

    排查中有两个问题先要明确

    1. session嵌套是开了几个事务?
    2. sql哪里锁住了?

    开了几个事务?

    参考http://blog.csdn.net/hupanfeng/article/details/9238127 分析Mybatis源码,可以发现一个session 对应着一个连接MySQL连接,所以嵌套的session应该是两个事务。并且batchexcutor模式下,session.flushstatement的时候,才会去写入mysql io中,也就是执行flush的时候,才会在mysql server端查询到该事务。

    MySQL事务提交

    同时MySQL中也不存在事务嵌套的说法,其事务提交的情况说明如下:

    autocommit

    autocommit是对于一个连接session来说,默认情况下,一个新的session里,autocommit=1;

    autocommit=1时候,
    如果没有begin, 一条sql语句就是一个事务,即任务要么被提交、要么失败回滚。
    如果有begin,则无视了autocommit设置,走begin显式事务的规则。

    autocommit=0时候,
    则即使你不显示得begin,你的sql也在begin块里,即已经处在一个事务里了。
    完全按照begin开始的事务的方式处理。

    begin-commit

    begin:
    begin ----------- 1
    sql1
    sql2
    sql3
    commit --------------- 2
    这是一个标准的显式事务块。

    除去autocommit=1一条sql组成一个事务块之外
    但是在某些情况下1,2都可以不显式的标识。
    事务开始:
    begin,
    autocomit=0 ,当前不在事务中则默认开启一个事务

    事务commit:
    commit
    一些mysql规定的语句,如begin等。e Section 14.3.3, “Statements That Cause an Implicit Commit”.

    MySQL卡在哪里

    所以刚两个事务卡在哪里了?

    session 1 session2
    begin
    delete from t1 where jid = 2
    insert into t1 values(2,3)
    begin
    insert into t1 values(2,4)
    lock time wait out

    事务1 在索引上2上删除了数据,导致锁住next-key锁,
    事务2 在索引2上插入,需要访问next-key ,锁超时,事务失败。
    具体参见超赞的博文:http://tech.meituan.com/innodb-lock.html

    相关文章

      网友评论

          本文标题:Mybatis SqlSession嵌套使用bug

          本文链接:https://www.haomeiwen.com/subject/yxeknttx.html