最近項目上需要實現這么一個功能:統計每個人每個軟件的使用時長,客戶端發過來消息,如果該用戶該軟件已經存在增更新使用時間,如果沒有則新添加一條記錄,代碼如下:
<!-- 批量保存軟件使用時長表 --> <update id="saveApp" parameterType="java.util.List"> <foreach collection="appList" item="item" index="index" separator=";"> insert into app_table(userName,app,duration) values(#{userName},#{item.app},#{item.duration}) on duplicate key update duration=duration+#{item.duration} </foreach> </update>為了效率用到了on duplicate key update進行自動判斷是更新還是新增,一段時間后發現該表的主鍵id(已設置為連續自增),不是連續的自增,總是跳躍的增加,這樣就造成id自增過快,已經快超過最大值了,通過查找資料發現,on duplicate key update有一個特性就是,每次是更新的情況下id也是會自增加1的,比如說現在id最大值的5,然后進行了一次更新操作,再進行一次插入操作時,id的值就變成了7而不是6.為了解決這個問題,有兩種方式,第一種是修改innodb_autoinc_lock_mode中的模式,第二種是將語句修拆分為更新和操作2個動作
第一種方式:innodb_autoinc_lock_mode中有3中模式,0,1和2,MySQL5的默認配置是1,
0是每次分配自增id的時候都會鎖表.
1只有在bulk insert的時候才會鎖表,簡單insert的時候只會使用一個light-weight mutex,比0的并發性能高
2.沒有仔細看,好像是很多的不保證...不太安全.
數據庫默認是1的情況下,就會發生上面的那種現象,每次使用insert into .. on duplicate key update 的時候都會把簡單自增id增加,不管是發生了insert還是update
由于該代碼數據量大,同時需要更新和添加的數據量多,不能使用將0模式,只能將數據庫代碼拆分成為更新和插入2個步驟,第一步先根據用戶名和軟件名更新使用時長,代碼如下:
<update id="updateApp" parameterType="App"> update app_table set duration=duration+#{duration} where userName=#{userName} and appName=#{appName} </update>然后根據返回值,如果返回值大于0,說明更新成功不再需要插入數據,如果返回值小于0則需要進行插入該條數據,代碼如下:<insert id="saveApp" keyPRoperty = "id" useGeneratedKeys = "true" parameterType="App"> insert into app_table(userName,appName,duration) values(#{userName},#{appName},#{duration}) </insert>這樣解決效率上肯定為受到影響,不知道會不會丟數據,觀察一段時間再優化吧!
新聞熱點
疑難解答