<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的樂觀鎖和悲觀鎖

          共 5726字,需瀏覽 12分鐘

           ·

          2021-05-01 20:36

          文章介紹

          對于MySQL中的樂觀鎖和悲觀鎖,可能很多的開發(fā)者還不是很熟悉,并不知道其中具體是如何實(shí)現(xiàn)的。本文就針對這個(gè)問題做一個(gè)實(shí)際案例演示,讓你徹底明白這兩種鎖的區(qū)別。

          相關(guān)文章

          之前針對MySQL中的鎖單獨(dú)分享過一篇文章,對于MySQL鎖還不夠了解的可以仔細(xì)閱讀以下該文。

          1. 一張圖徹底搞懂 MySQL 的鎖機(jī)制[面試題] 

          2. 一張圖徹底搞懂 MySQL 的鎖機(jī)制[更新一]

          鎖分類

          MySQL的中鎖按照范圍主要分為表鎖、行鎖和頁面鎖。其中myisam存儲引擎只支持表鎖,InnoDB不僅僅支持行鎖,在一定程度上也支持表鎖。按照行為可以分為共享鎖(讀鎖)、排他鎖(寫鎖)和意向鎖。按照思想分為樂觀鎖和悲觀鎖。

          今天的文章演示一下實(shí)際中的樂觀鎖和悲觀鎖是如何操作的。

          表結(jié)構(gòu)

          下面的SQL語句是表的結(jié)構(gòu)。

          CREATE TABLE `demo`.`user`  (
          `id` int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
          `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
          `sex` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
          `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
          `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
          `version` int(1) NULL DEFAULT 1 COMMENT '數(shù)據(jù)版本號',
          PRIMARY KEY (`id`) USING BTREE
          ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

          插入模擬數(shù)據(jù)

          BEGIN;
          INSERT INTO `user` VALUES (0000000001, '張三', 0, '[email protected]', '18228937997', 1);
          INSERT INTO `user` VALUES (0000000002, '李四', 0, '[email protected]', '15683202302', 1);
          INSERT INTO `user` VALUES (0000000003, '李四1', 0, '[email protected]', '15683202302', 1);
          INSERT INTO `user` VALUES (0000000004, '李四2', 0, '[email protected]', '15683202302', 1);
          INSERT INTO `user` VALUES (0000000005, '李四3', 0, '[email protected]', '15683202302', 1);
          INSERT INTO `user` VALUES (0000000006, '李四4', 0, '[email protected]', '15683202302', 1);
          INSERT INTO `user` VALUES (0000000007, '李四55', 0, '[email protected]', '15683202302', 1);
          COMMIT;

          表中數(shù)據(jù)。

          mysql [email protected]:demo> select * from user;
          +----+--------+-----+---------------------+-------------+---------+
          | id | name | sex | email | mobile | version |
          +----+--------+-----+---------------------+-------------+---------+
          | 1 | 張三 | 0 | [email protected] | 18228937997 | 2 |
          | 2 | 李四 | 0 | [email protected] | 15683202302 | 1 |
          | 3 | 李四1 | 0 | [email protected] | 15683202302 | 1 |
          | 4 | 李四2 | 0 | [email protected] | 15683202302 | 1 |
          | 5 | 李四3 | 0 | [email protected] | 15683202302 | 1 |
          | 6 | 李四4 | 0 | [email protected] | 15683202302 | 1 |
          | 7 | 李四55 | 0 | [email protected] | 15683202302 | 1 |
          +----+--------+-----+---------------------+-------------+---------+
          7 rows in set
          Time: 0.011s

          悲觀鎖

          悲觀鎖,比較消極的一種鎖處理方式。直接在操作數(shù)據(jù)時(shí),搶占鎖。其他的事務(wù)在進(jìn)行時(shí)就會等待,直到占有鎖的事務(wù)釋放鎖為止。

          這種處理方式能保證數(shù)據(jù)的最大一致性,但是容易導(dǎo)致鎖超時(shí)、并發(fā)程度低等問題。首先我們開啟事務(wù)一,并且對id=1的數(shù)據(jù)進(jìn)行update操作,此時(shí)我們不提交事務(wù)。

          mysql [email protected]:demo> begin;
          Query OK, 0 rows affected
          Time: 0.002s
          mysql [email protected]:demo> update `user` set name = '張三111111'where id = 1;
          Query OK, 1 row affected
          Time: 0.004s

          接著我們開啟事務(wù)二,對id=1的數(shù)據(jù)進(jìn)行update操作,查看此時(shí)會發(fā)生什么情況?

          mysql [email protected]:demo> begin;
          Query OK, 0 rows affected
          Time: 0.002s
          mysql [email protected]:demo> update `user` set sex = 1 where id = 1;

          我們執(zhí)行完update語句之后,就處于等待狀態(tài),SQL語句也不會馬上被執(zhí)行,這是因?yàn)槭聞?wù)一沒有commit,也就沒有釋放id=1的數(shù)據(jù)對應(yīng)的寫鎖。效果如下圖:

          Snipaste_2021-04-30_16-15-56

          通過上面的例子,我們就能比較直觀的感受到悲觀鎖的實(shí)現(xiàn)過程是如何的。

          樂觀鎖

          樂觀鎖認(rèn)為數(shù)據(jù)一般情況下不會造成沖突,只有當(dāng)數(shù)據(jù)去執(zhí)行修改情況時(shí),才會針對數(shù)據(jù)沖突做處理。這里是如何發(fā)現(xiàn)沖突了呢?常規(guī)的方式,都是在數(shù)據(jù)行上加一個(gè)版本號或者時(shí)間戳等字段。(本文使用version作為版本好方式,使用時(shí)間戳方式同理)

          樂觀鎖的實(shí)現(xiàn)原理:

          1. 一個(gè)事務(wù)在讀取數(shù)據(jù)時(shí),將對應(yīng)的版本號字段讀取出來,假設(shè)此時(shí)的版本號是1。

          2. 另外一個(gè)事務(wù)也是執(zhí)行同樣的讀取操作。當(dāng)事務(wù)一提交時(shí),對版本號執(zhí)行+1,此時(shí)該數(shù)據(jù)行的版本號就是2。

          3. 第二個(gè)事務(wù)執(zhí)行修改操作時(shí),針對業(yè)務(wù)數(shù)據(jù)做條件,并默認(rèn)增加一個(gè)版本號作為where條件。此時(shí)修改語句中的版本號字段是不滿足where條件,該事務(wù)執(zhí)行失敗。通過這種方式來達(dá)到鎖的功能。

          Snipaste_2021-04-30_16-47-25

          客戶端一

          mysql [email protected]:demo> select * from user where id = 1;
          +----+------------+-----+---------------------+-------------+---------+
          | id | name | sex | email | mobile | version |
          +----+------------+-----+---------------------+-------------+---------+
          | 1 | 張三111111 | 0 | [email protected] | 18228937997 | 1 |
          +----+------------+-----+---------------------+-------------+---------+
          1 row in set
          Time: 0.012s
          mysql [email protected]:demo> update `user` set name = '事務(wù)一', version = version + 1 where id = 1 and version = 1;
          Query OK, 1 row affected
          Time: 0.008s
          mysql [email protected]:demo> select * from user where id = 1;
          +----+--------+-----+---------------------+-------------+---------+
          | id | name | sex | email | mobile | version |
          +----+--------+-----+---------------------+-------------+---------+
          | 1 | 事務(wù)一 | 1 | [email protected] | 18228937997 | 2 |
          +----+--------+-----+---------------------+-------------+---------+
          1 row in set
          Time: 0.009s

          執(zhí)行update語句的順序應(yīng)該在客戶端二執(zhí)行了select之后,在執(zhí)行。

          客戶端二

          mysql [email protected]:demo> select * from user where id = 1;
          +----+------------+-----+---------------------+-------------+---------+
          | id | name | sex | email | mobile | version |
          +----+------------+-----+---------------------+-------------+---------+
          | 1 | 張三111111 | 1 | [email protected] | 18228937997 | 1 |
          +----+------------+-----+---------------------+-------------+---------+
          1 row in set
          Time: 0.015s
          mysql [email protected]:demo> update `user` set name = '事務(wù)二', version = version + 1 where id = 1 and version = 1;
          Query OK, 0 rows affected
          Time: 0.003s
          mysql [email protected]:demo> select * from user where id = 1;
          +----+--------+-----+---------------------+-------------+---------+
          | id | name | sex | email | mobile | version |
          +----+--------+-----+---------------------+-------------+---------+
          | 1 | 事務(wù)一 | 1 | [email protected] | 18228937997 | 2 |
          +----+--------+-----+---------------------+-------------+---------+
          1 row in set
          Time: 0.012s

          此時(shí)根據(jù)update返回的結(jié)構(gòu),可以看出受影響的行數(shù)為0,同時(shí)select查詢之后,返現(xiàn)數(shù)據(jù)也是事務(wù)一的數(shù)據(jù)。

          推薦閱讀

          1. 一張圖徹底搞懂 MySQL 的鎖機(jī)制[更新一]

          2. 一張圖徹底搞懂 MySQL 的鎖機(jī)制[面試題]

          3. MySQL中的日志文件 你全都了解嗎?

          4. 開發(fā)人員必備的MySQL事務(wù)原理分析與總結(jié)

          5. MySQL函數(shù)sum使用場景解讀



          瀏覽 37
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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最新中文字幕 a级成人黄色毛片 | 天堂欧美城网站网址 | 亚洲三级片免费观看 | 欧美三级韩国三级日本三级在线观看 |