問題回顧: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=」)」 去掉。
因爲本人在項目中遇到此類問題,特此記錄,與君分享。