<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          聊聊MySQL中的死鎖

          共 6746字,需瀏覽 14分鐘

           ·

          2023-11-10 00:33

          歡迎關(guān)注微信公眾號:互聯(lián)網(wǎng)全棧架構(gòu)

          死鎖是指兩個或者多個事務(wù)互相持有對方所需的資源,從而導(dǎo)致它們都無法繼續(xù)執(zhí)行的情況。下圖是一個死鎖的示例,事務(wù)1鎖住了id=1的數(shù)據(jù)(比如更新id=1的數(shù)據(jù)記錄),同時請求鎖住id=2的數(shù)據(jù),但事務(wù)2持有id=2的鎖,同時又請求id=1的鎖,這樣就造成了相互等待對方釋放鎖的情況,從而產(chǎn)生了死鎖:

          上圖是死鎖產(chǎn)生的示例說明,我們用實際的SQL來演示死鎖的產(chǎn)生,首先創(chuàng)建一個測試表,它只有兩個字段,id和數(shù)量,id為自增類型,然后向表中插入兩條數(shù)據(jù):

          CREATE TABLE `t_test` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `quantity` int(2) DEFAULT NULL,
            PRIMARY KEY (`id`)
          ) ENGINE
          =InnoDB DEFAULT CHARSET=utf8mb4;
          INSERT INTO `t_test` VALUES ('1''1');
          INSERT INTO `t_test` VALUES ('2''2');

          如果有兩個事務(wù)更新表中id等于1和2的數(shù)據(jù),但更新的順序相反,像下面這樣,就會出現(xiàn)死鎖:

          最后,事務(wù)2提示死鎖的錯誤,而事務(wù)1則執(zhí)行成功,當(dāng)然,在事務(wù)的最后需要加上COMMIT語句。查詢表中的數(shù)據(jù)進(jìn)行確認(rèn),發(fā)現(xiàn)id=1的數(shù)量更新為了101,而id=2的數(shù)量更新成了102。

          另外,由于sql執(zhí)行較快,直接執(zhí)行上面兩個事務(wù)中的sql可能不會產(chǎn)生死鎖的情況,我們可以稍做修改,也就在UPDATE語句后面加上SLEEP函數(shù),SLEEP會讓當(dāng)前進(jìn)程暫停執(zhí)行指定的時間(單位為秒)。分別在兩個事務(wù)中執(zhí)行下面的語句,稍等幾秒鐘,就可以看到出現(xiàn)死鎖:

          # 事務(wù)1
          START TRANSACTION;
          UPDATE t_test SET quantity=101 WHERE id = 1;
          SELECT SLEEP(10) FROM dual;
          UPDATE t_test SET quantity=102 WHERE id = 2;
          COMMIT;
          # 事務(wù)2
          START TRANSACTION;
          UPDATE t_test SET quantity=201 WHERE id = 2;
          SELECT SLEEP(10) FROM dual;
          UPDATE t_test SET quantity=202 WHERE id = 1;
          COMMIT;
          在MySQL中,死鎖檢測的選項默認(rèn)是開啟的:innodb_deadlock_detect,如果InnoDB檢測到死鎖,則會把其中一個或者多個事務(wù)進(jìn)行回滾,以這種方式來解決死鎖,InnoDB會嘗試回滾較小的事務(wù)。可以通過執(zhí)行以下命令來查看死鎖的檢測情況:  
          SHOW ENGINE INNODB STATUS;
          比如以上兩個事務(wù)執(zhí)行以后,再執(zhí)行上面的命令,就會看到以下的結(jié)果(只摘取死鎖檢測的部分),通過這種方式可以較為清晰的看到死鎖的產(chǎn)生過程:
           ------------------------
           LATEST DETECTED DEADLOCK
           ------------------------
           2023-11-08 15:57:23 0x4df8
           *** (1) TRANSACTION:
           TRANSACTION 350231, ACTIVE 12 sec starting index read
           mysql tables in use 1, locked 1
           LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
           MySQL thread id 3, OS thread handle 19044, query id 339 localhost ::1 root updating
           UPDATE t_test SET quantity
          =102 WHERE id = 2
           *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
           RECORD LOCKS space id 743 page no 3 n bits 72 index PRIMARY of table `test`.`t_test` trx id 350231 lock_mode X locks rec but not gap waiting
           Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
            0: len 4; hex 80000002; asc     ;;
            1: len 6; hex 000000055818; asc     X ;;
            2: len 7; hex 2f000001401cb2; asc /   @  ;;
            3: len 4; hex 800000c9; asc     ;;
           
           *** (2) TRANSACTION:
           TRANSACTION 350232, ACTIVE 10 sec starting index read, thread declared inside InnoDB 5000
           mysql tables in use 1, locked 1
           3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
           MySQL thread id 5, OS thread handle 19960, query id 340 localhost 127.0.0.1 root updating
           UPDATE t_test SET quantity
          =202 WHERE id = 1
           *** (2HOLDS THE LOCK(S):
           RECORD LOCKS space id 743 page no 3 n bits 72 index PRIMARY of table `test`.`t_test` trx id 350232 lock_mode X locks rec but not gap
           Record lock, heap no 3 PHYSICAL RECORD: n_fields 4
          ; compact format; info bits 0
            0: len 4; hex 80000002; asc     ;;
            1: len 6; hex 000000055818; asc     X ;;
            2: len 7; hex 2f000001401cb2; asc /   @  ;;
            3: len 4; hex 800000c9; asc     ;;
           
           *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
           RECORD LOCKS space id 743 page no 3 n bits 72 index PRIMARY of table `test`.`t_test` trx id 350232 lock_mode X locks rec but not gap waiting
           Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
            0: len 4; hex 80000001; asc     ;;
            1: len 6; hex 000000055817; asc     X ;;
            2: len 7; hex 2e0000018d1edf; asc .      ;;
            3: len 4; hex 80000065; asc    e;;
           
           *** WE ROLL BACK TRANSACTION (2)
          從上面可以看出,MySQL可以檢測到死鎖,并通過回滾事務(wù)的方式來打破這種循環(huán)等待,但無論如何,在代碼中還是需要盡量減少或者避免死鎖的發(fā)生,可以嘗試通過以下方法來達(dá)到這樣的目的:
            • 讓事務(wù)盡可能的小且短;
            • 合理設(shè)置事務(wù)隔離級別;
            • 合理設(shè)置鎖等待超時時間;
            • 確定好事務(wù)操作的順序;
            • 創(chuàng)建合適的索引,減少加鎖的情況。

          以上就是關(guān)于MySQL中的死鎖介紹。在實際編碼中,死鎖也是較為常見的一種錯誤,如果對于它不了解,那么碰到這種異常的時候就會顯得手足無措,希望本文有所幫助。
          都看到這里了,請幫忙一鍵三連啊,也就是點擊文末的在看、點贊、分享,這樣會讓我的文章讓更多人看到,也會大大地激勵我進(jìn)行更多的輸出,謝謝!
          鳴謝:
          https://dev.mysql.com/doc/refman/5.7/en/

          推薦閱讀:

          越俎代庖:應(yīng)用廣泛的代理模式

          MySQL整數(shù)類型的長度到底是什么含義?

          漫談MySQL中的事務(wù)

          臭名昭著,怙惡不悛的OOM,到底是什么?

          俯拾皆是的Java注解,你真的get了嗎?

          “八面玲瓏”的ZooKeeper入門介紹

          責(zé)無旁貸:超酷的責(zé)任鏈模式

          聚沙成塔:聊聊建造者模式

          公司裁員,碼農(nóng)竟然成了“幫兇”?(劇情杜撰)

          瀏覽 169
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩精品电影网 | 永久免费无码中文字幕 | 国产免费高清视频 | 特级aV毛片在线 | 99视频在线播放观看精品 |