1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        糾正互聯網上關于MySQL普通字段的行鎖和表鎖的實驗

        共 7548字,需瀏覽 16分鐘

         ·

        2023-07-17 16:34

        0fb9477fcd789679849284b146d013ee.webp


        以上圖片是截取B站某up主的視頻,我們通過實驗驗證這句話的正確性.




                
                  CREATE TABLE `t_order` (
                
                
                    `id` int NOT NULL,
                
                
                    `t_no` varchar(64) DEFAULT NULL,
                
                
                    `t_name` varchar(64) DEFAULT NULL,
                
                
                    PRIMARY KEY (`id`),
                
                
                    KEY `idx_t_no` (`t_no`)
                
                
                  )?ENGINE=InnoDB
                
              


        表中包含主鍵(id),普通索引(t_no),以及沒有索引的字段(t_name)



        f73fdd318f3b9021055cc50538cdf3be.webp

        表中數據

        382b1a8f14dfefc26d93c88856b35d71.webp



        f73fdd318f3b9021055cc50538cdf3be.webp

        數據庫版本 5.7.37

        121822ba16be94384d65e471d2a0b0ae.webp



        f73fdd318f3b9021055cc50538cdf3be.webp

        事務隔離級別RR

        2c4026a34c48d1a5333734cc4a61d171.webp



        開啟事務,執(zhí)行普通字段的更新操作


        d543086d391040146f622da80f3e6186.webp


        begin 表示開啟事務
        update t_order set t_no=‘N00A’ where t_name=‘A’; 中的t_name字段是一個普通字段



        通過 show engine innodb status 命令查詢事務的鎖情況,輸出信息如下



                
                  
                    ------------
                  
                
                
                  
                    TRANSACTIONS
                  
                
                
                  
                    ------------
                  
                
                
                  Trx id counter 518176
                
                
                  Purge done for trx's n:o < 518175 undo n:o < 0 state: running but idle
                
                
                  
                    
        2 lock struct(s), heap size 1136, 5 row lock(s), undo log entries 1 MySQL thread id 3, OS thread handle 140556094682880, query id 52 localhost root // 在表上加了一個意向排他鎖 TABLE LOCK table `db0`.`t_order` trx id 518175 lock mode IX // 在主鍵索引上加了Next-Key鎖,具體在哪些主鍵上加了Next-Key鎖呢? 看下面 RECORD LOCKS space id 51 page no 3 n bits 72 index PRIMARY of table `db0`.`t_order` trx id 518175 lock_mode X // 在正無窮上加了Next-Key鎖 Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;; // 在id=1上加了Next-Key鎖 Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000001; asc ;; 1: len 6; hex 00000007e81f; asc ;; 2: len 7; hex 38000002040b10; asc 8 ;; 3: len 4; hex 4e303041; asc N00A;; 4: len 1; hex 41; asc A;; // 在id=2上加了Next-Key鎖 Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000002; asc ;; 1: len 6; hex 00000007e814; asc ;; 2: len 7; hex b1000001250110; asc % ;; 3: len 4; hex 4e303032; asc N002;; 4: len 1; hex 42; asc B;; // 在id=3上加了Next-Key鎖 Record lock, heap no 4 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000003; asc ;; 1: len 6; hex 00000007e819; asc ;; 2: len 7; hex b4000001280110; asc ( ;; 3: len 4; hex 4e303033; asc N003;; 4: len 1; hex 43; asc C;; // 在id=4上加了Next-Key鎖 Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000004; asc ;; 1: len 6; hex 00000007e81a; asc ;; 2: len 7; hex b5000001290110; asc ) ;; 3: len 4; hex 4e303034; asc N004;; 4: len 1; hex 42; asc B;;



        ?解讀以上數據?

        【1】TABLE LOCK table db0.t_order trx id 518175 lock mode IX
        表示在表上加了一個意向排他鎖,因為事務在獲取行級排他鎖之前,必須先獲取表級意向排他鎖


        【2】RECORD LOCKS space id 51 page no 3 n bits 72 index PRIMARY of table db0.t_order trx id 518175 lock_mode X
        表示在主鍵索引上需要加Next-Key鎖


        【3】Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
        0: len 8; hex 73757072656d756d; asc supremum;;

        表示在主鍵上的正無窮上加了一把Next-Key鎖. 主鍵上的最大值存儲在heap no = 1, 主鍵上的最小值存儲在heap no = 0,業(yè)務數據是從heap no = 2開始存儲


        【4】分別在表的每個主鍵值上加了Next-Key鎖




        綜上,相當于在 (負無窮,1] (1,2] (2,3] (3,4] (4,正無窮) 都加了行級鎖,形式上等效于表鎖,但是它并不是表鎖,它依然是行級鎖. 如果加的是一把表鎖,反而開銷會小很多, 我們的實驗數據只有4條,就加了4個行級鎖,如果表里有10萬條數據,那么就會加10萬個行級鎖,開銷是相當大的.



        因此網絡上,關于 普通字段檢索數據的時候將使用表鎖 這個觀點是不正確的,且不嚴謹. 之所以不嚴謹,是因為它并沒有使用表鎖,它依然是行級鎖,只是這個行級鎖將(負無窮,正無窮)都鎖住了. 之所以說它不正確,是因為我們的實驗是基于RR隔離級別,如果把隔離級別改成RC,再把上面的操作執(zhí)行一次



        f73fdd318f3b9021055cc50538cdf3be.webp

        將隔離級別改成RC

        60fb3505b7c2d8e9a342682310bc9d9e.webp




        開啟事務,執(zhí)行更新操作


        b68128fd48b5ed338da6af2aaed4ad47.webp



        通過 show engine innodb status 命令查詢事務的鎖情況


                
                  
                    ------------
                  
                
                
                  
                    TRANSACTIONS
                  
                
                
                  
                    ------------
                  
                
                
                  Trx id counter 518182
                
                
                  Purge done for trx's n:o < 518182 undo n:o < 0 state: running but idle
                
                
                  2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1
                
                
                  MySQL thread id 3, OS thread handle 140556094682880, query id 62 localhost root
                
                
                  // 在表上加了一個意向排他鎖
                
                
                  TABLE LOCK table `db0`.`t_order` trx id 518177 lock mode IX
                
                
                  // 在主鍵索引上加了行級鎖,具體在哪些主鍵上加了行級鎖呢? 看下面
                
                
                  RECORD LOCKS space id 51 page no 3 n bits 72 index PRIMARY of table `db0`.`t_order` trx id 518177 lock_mode X locks rec
                
                
                  but not gap
                
                
                  // 在id=1上加了行級鎖
                
                
                  Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
                
                
                   0: len 4; hex 80000001; asc     ;;
                
                
                   1: len 6; hex 00000007e821; asc      !;;
                
                
                   2: len 7; hex 39000001db0e66; asc 9     f;;
                
                
                   3: len 4; hex 4e303041; asc N00A;;
                
                
                   4: len 1; hex 41; asc A;;
                
                
                  
                    



        ?解讀以上數據?

        【1】TABLE LOCK table db0.t_order trx id 518177 lock mode IX
        表示在表上加了一個意向排他鎖,因為事務在獲取行級排他鎖之前,必須先獲取表級意向排他鎖


        【2】RECORD LOCKS space id 51 page no 3 n bits 72 index PRIMARY of table db0.t_order trx id 518177 lock_mode X locks rec but not gap
        表示在主鍵索引上需要加行級鎖


        【3】在表的id=1的主鍵上加了行級鎖



        綜上,在RC隔離級別下,它只是在對應記錄的主鍵上加了行級鎖,并沒有表鎖,也沒有將(負無窮,正無窮)整個范圍加鎖.


        在實際生產中,大多數選擇RC隔離級別.






        結論:普通字段作為WHERE條件的更新操作1.如果是RR隔離級別,會將主鍵的(負無窮,正無窮)加Next-Key鎖
        2.如果是RC隔離級別,會將對應記錄的主鍵上加行級鎖





        網絡上有許多技術言論,大家聽之信之,認為就是這樣,應該是這樣, 然而它與實際的情況還有許多距離,需要我們親自去探秘.




        瀏覽 81
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产伦子伦一级A片视 | 中文无码字幕在线 | 岛国一级特黄毛片视频 | 张柏芝裸体下面毛毛片 | 男人操女人逼网站 | 精品国精品自拍自在线 | 青青草视频播放 | 暴操嫩逼 | 大乳boobs巨大吃奶光头 | 在线sese |