中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL中使用if not exists需要注意什么

發布時間:2021-11-06 11:04:17 來源:億速云 閱讀:1593 作者:小新 欄目:MySQL數據庫

小編給大家分享一下MySQL中使用if not exists需要注意什么,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!



環境MySQL 5.6.14
事務隔離級別 讀提交
事務的開啟和結束由JAVA程序控制.

上次報死鎖的過程,抽象如下

  1. delimitr $$

  2. CREATE PROCEDURE `test_proc`(

  3.     pid int

  4. )

  5. begin

  6.     if not exists (select * from t where id=pid) then

  7.         insert into t(id) values(pid);

  8.     end if;

  9.     

  10.     update t set total=total+1 where id=pid;

  11. end $$

  12. delimiter ; 


死鎖原因已經明白了,就是并發情況下,Insert遇到排它鎖,則嘗試加共享鎖。
在最后Update的時候,兩個持有共享鎖的連接,都嘗試申請排它鎖,則導致了死鎖.

但是問題是...怎么會走到了最后一行的Update語句?
另外兩個連接,不是應該在Insert語句時報 Duplicate entry 'xx' for key 'PRIMARY'錯誤嗎?

問題應該出在這種結構里
if not exists (select * from t where id=pid) then
    xxx
end if;

使用 if not exists 模式,真心要注意啊.在這種結構里出現的異常,不會報錯,而是直接跳出IF判斷,繼續執行!!

實驗準備


  1. CREATE TABLE `t` (

  2.   `id` int(11) NOT NULL,

  3.   `total` int(11) NOT NULL DEFAULT '0',

  4.   PRIMARY KEY (`id`)

  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


  6. truncate table t;

  7. drop procedure if exists test_proc;

  8. delimiter $$

  9. CREATE PROCEDURE `test_proc`(

  10.     pid int,

  11.     ptotal int

  12. )

  13. begin

  14.     if not exists (select * from t where id=pid) then

  15.         insert into t(id,total) value(pid,ptotal);

  16.         update t set total=ptotal+1 where id=pid;

  17.     end if;

  18.     select ptotal+1;    

  19. end $$

  20. delimiter ;


打開三個客戶端,分別執行過程
MySQL中使用if not exists需要注意什么

第一個客戶端執行,并沒有提交.
第二,第三客戶端處于阻塞狀態.
等第一個客戶端提交,

第二個客戶端返回 201
第三個客戶端返回 301
且沒有任何的報錯信息.


三個客戶端都提交之后,查看T表信息
只有一個記錄,id為1,total為101

也就是說,第二個,第三個客戶端,在得到主鍵沖突的異常后,沒有報錯,沒有繼續執行IF塊內剩下的語句,而是直接跳出了IF塊,繼續執行IF塊外的語句!!

該報錯的地方不報錯,在大段的存儲過程中,導致死鎖還是小問題,就怕引起數據的錯亂,而不自知.

針對這種情況,如果有主鍵或者唯一約束,我覺得干脆改為如下的方式.
delimiter $$
CREATE PROCEDURE `test_proc`(
    pid int,
    ptotal int
)
begin
    insert into t(id,total) value(pid,ptotal);
    update t set total=ptotal+1 where id=pid;
    select ptotal+1;
end $$
delimiter ;

看完了這篇文章,相信你對“MySQL中使用if not exists需要注意什么”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

札达县| 桐城市| 游戏| 洛宁县| 富蕴县| 上饶市| 洪江市| 江永县| 池州市| 灯塔市| 屯门区| 岑巩县| 乌拉特后旗| 乌拉特中旗| 迁安市| 桃源县| 靖安县| 龙胜| 长岭县| 大城县| 慈利县| 尖扎县| 丽水市| 老河口市| 宜城市| 东城区| 海盐县| 长寿区| 富源县| 体育| 红桥区| 丰城市| 临沧市| 永川市| 南阳市| 玉山县| 林甸县| 福贡县| 鹿邑县| 鄂伦春自治旗| 灌云县|