mysql中on duplicate key update 使用詳解

嘮叨一下

在mysql中插入數據,如果碰到主鍵衝突或者唯一索引衝突的時候,程序中會拋出SQLIntegrityConstraintViolationException異常,如果只是單純的由於主鍵衝突或者唯一索引衝突引起的異常的話,這個問題很容易解決,如果是主鍵衝突的話可以更新爲其他主鍵,如果是唯一索引的話可以將唯一索引刪除或者將引起唯一索引衝突的數據更新一下;但是還有另外一種情況是比較棘手的,那就是我插入一條數據的時候如果出現這樣的衝突的時候,我不希望什麼都不做,而是當出現這樣插入失敗的時候我將衝突的這條數據進行一些更新操作,出現了這樣的訴求的時候,下面的這個關鍵字就可以粉墨登場啦:on duplicate key update,這個關鍵字最重要的作用就是當我們在插入數據出現主鍵或唯一索引重複的時候,可以執行它後面的一個更新操作,而不是什麼都不做,直接返回異常,接下來我們就來詳細的瞭解一下 on duplicate key update 這個mysql中關鍵字在開發中正確使用。

在這裏插入圖片描述

實現原理

  • 嘗試插入新數據到數據庫表中,如果插入成功則直接返回插入的列。
  • 如果由於主鍵或唯一索引出現重複而造成插入失敗的話,則先數據庫表中已存在的出現衝突的數據行加上共享鎖,然後將該數據返回數據庫服務器中。
  • 數據庫服務器在內存中對改行數據執行on duplicate key update 後的update語句。
  • 然後對該行數據加上排它鎖。
  • 最後將內存中update後的數據寫入改行,全部執行完畢

使用實例

mybatis中單個插入on duplicate key update的使用

@Insert({"<script>",
            "insert into user set id = #{id}, mobile = #{mobile}, email = #{email}, name = #{name}, link_name = #{linkName}, create_user_id = #{createUserId} ",
            " on duplicate key update create_user_id = #{createUserId} ",
            "</script>"})
    int insertTest(User user);

mybatis中批量插入on duplicate key update 的使用

@Insert({"<script>",
            "insert into user  (id , mobile, email, name, link_name, create_user_id)  ",
            " values ",
            "<foreach collection='list' index='index' item='item' separator=','> (#{item.id}, #{item.mobile}, #{item.email}, #{item.name}, #{item.linkName}, #{item.createUserId} )</foreach>",
            " on duplicate key update create_user_id = values(create_user_id), mobile = values(mobile) ",
            "</script>"})
    int batchInsertTest(List<User> userList);

存在問題

  • 高併發情況可能會出現死鎖

由於主鍵或唯一索引出現重複的時候,在更新該調存在的數據的時候,會爲該條數據加一個共享鎖和一個排它鎖,最後纔會寫入該條數據,如果併發比較高,兩個線程幾乎同時來操作這條數據的話,如果兩個線程同時給一條數據加上共享鎖和排它鎖的話,就會出現死鎖的情況。

使用總結

在使用 on duplicate key update 關鍵字的時候,一定要注意它操作後返回結果,它的返回結果和我們平常使用的insert是不同的,使用insert … on duplicate key update時,如果主鍵或唯一索引沒有重複,成功插入了新增數據則返回1,如果主鍵或唯一索引已經重複,沒有插入成功,但是 on duplicate key update 後的更新的字段的數據和 原數據不同,則表示更新成功,此時返回的結果是2, 如果 on duplicate key update 的更新數據和原始數據相同,則表示更新也沒有成功,則返回0.
在mysql中,同樣可以實現通過判斷主鍵或唯一索引是否存在來執行不同操作的關鍵字還有兩個,分別是:replace into 和 insert ignore into,這幾種每一種方式都會存在一些問題,具體存在哪些問題,就等着各位去進一步的深入探究啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章