问题回顾:java
配送单提交生成分拣单,配送明细数量较多,分拣单提交时,因为须要循环调用出库单接口、请购单接口、批量更新配送单和配送明细状态、批量更新分拣单和分拣明细状态数量等耗时操做,现执行如下批量更新sql:sql
<foreach collection="list" item="d" separator=";"> update XXX set update_user=#{d.updateUser}, update_time=#{d.updateTime}, out_num=#{d.outNum}, curr_out_num=#{d.currOutNum} where id=#{d.id} </foreach>
这种多条语句批量更新方式只适合少数据量,若是数据量较多,在数据库执行更新的过程当中,一旦程序接下来有其余sql语句也须要操做该表,则会暴漏以下异常信息:数据库
Could not retrieve transaction read-only status from serveride
出现这种异常通常有三方面的缘由:spa
数据库事务状态为REPEATABLE-READ(用 SHOW VARIABLES LIKE '%iso%'; 查询)。此时应更改事务状态为READ-COMMITTED,既执行:SET GLOBAL tx_isolation='READ-COMMITTED';重启应用便可。code
由于驱动包都有相匹配的数据库版本,手动检查自身项目的jdbc驱动包版本和msyql数据版本。检索命令以下:server
数据库版本:SELECT VERSION();接口
他们的对照关系表以下:事务
Connector/J 5.1 支持Mysql 4.一、Mysql 5.0、Mysql 5.一、Mysql 6.0 alpha这些版本。
Connector/J 5.0 支持MySQL 4.一、MySQL 5.0 servers、distributed transaction (XA)。
Connector/J 3.1 支持MySQL 4.一、MySQL 5.0 servers、MySQL 5.0 except distributed transaction (XA) support。
Connector/J 3.0 支持MySQL 3.x or MySQL 4.1。it
这种状况多出如今项目中相邻的多条更新语句都执行批量更新或批量查询-更新相同表数据。为了规避这种异常状况,须要更改sql语句的语法,将上述批量更新语句修改成以下形式:
UPDATE xxx <trim prefix="set" suffixOverrides=","> <trim prefix="out_num = case" suffix="end,"> <foreach collection="details" item="item" index="index"> <if test="item.outNum != null"> when id = #{item.id} and goods_id = #{item.goodsId} then #{item.outNum} </if> </foreach> </trim> </trim> where <foreach collection="details" separator="or" item="item" index="index" open="(" close=")"> id=#{item.id} and goods_id = #{item.goodsId} </foreach>
其中When 条件后能够跟多参数,若是存在or,须要将when后面的参数用()括起来。
若是是单参数,Where 条件后须要把open=”(” close=”)” 去掉。
因为本人在项目中遇到此类问题,特此记录,与君分享。