3089589

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

最近在mybatis多线程插入数据时出现两则问题,记录如下:

问题1:我的逻辑如下

1 select表中category_name字段,如果有的话则取出其ID

2 如果木有的话则插入一条数据,同时用last_insert_id()函数将主键主增长ID找出

mybatis配置如下

<insert id="insertCommonCategory" parameterType="CommonCategory">
        insert ignore into common_category (category_name,category_group)
        values(#{categoryName},#{categoryGroup})
<!-- 多线程环境中会导致insert失败,导致该段逻辑有误
        <selectKey keyProperty="id" resultType="java.lang.Integer">
            select last_insert_id() as id
        </selectKey>
-->
</insert>
<select id="selectIdbyCategoryNameAndGroup" parameterType="CommonCategory" resultType="java.lang.Integer">
        select id from common_category where category_name=#{categoryName} and category_group=#{categoryGroup}
</select>
 

由于在多线程环境中,可能会导致逻辑同时进入2逻辑,此时会导致insert失败,last_insert_id()函数返回一个错误的id

问题2:根据以上现象,我的更改为

1 在insert加上ignore修饰,可让insert失败时不报错,但last_insert_id()函数依然有错,所以不用它

2 将逻辑改成 (1) 查找category_name字段,有的时候取出其ID,(2)木有的话新插入一条,insert语句加上ignore修饰,(3)重新进行(1)步骤

但此时依然报错,说是(3)步骤依然找不到ID,翻阅相关资料找到的原因为:Mysql的事务隔离级别为可重读, 即在同一个事务中始终看到相同的数据,此时错误发生的原因为,在进行(2)步骤时,insert失败,(3)步骤依然就查不到数据了,解决办法有二

1 更改mysql事务隔离级别Read Commited或更低级别

2 利用mybatis的cache,在mapper的配置文件中加上<cache/>标签,然后insert标签上flushCache属性设置为true,使其在多线程环境中能随时的刷新cache

看来多线程编程有很多难以预料的问题

 

 

posted on 2013-03-26 09:25  liangge0218  阅读(8232)  评论(0编辑  收藏  举报