久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL樂觀鎖和悲觀鎖如何實現

165次閱讀
沒有評論

共計 5203 個字符,預計需要花費 14 分鐘才能閱讀完成。

這篇文章主要介紹了 MySQL 樂觀鎖和悲觀鎖如何實現的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇 MySQL 樂觀鎖和悲觀鎖如何實現文章都會有所收獲,下面我們一起來看看吧。

鎖分類

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

表結構

下面的 SQL 語句是表的結構:

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  數據版本號 ,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

插入模擬數據:

BEGIN;
INSERT INTO `user` VALUES (0000000001,  張三 , 0,  18228937997@163.com ,  18228937997 , 1);
INSERT INTO `user` VALUES (0000000002,  李四 , 0,  1005349393@163.com ,  15683202302 , 1);
INSERT INTO `user` VALUES (0000000003,  李四 1 , 0,  1005349393@163.com ,  15683202302 , 1);
INSERT INTO `user` VALUES (0000000004,  李四 2 , 0,  1005349393@163.com ,  15683202302 , 1);
INSERT INTO `user` VALUES (0000000005,  李四 3 , 0,  1005349393@163.com ,  15683202302 , 1);
INSERT INTO `user` VALUES (0000000006,  李四 4 , 0,  1005349393@163.com ,  15683202302 , 1);
INSERT INTO `user` VALUES (0000000007,  李四 55 , 0,  1005349393@163.com ,  15683202302 , 1);
COMMIT;

表中數據。

mysql root@127.0.0.1:demo  select * from user;
+----+--------+-----+---------------------+-------------+---------+
| id | name | sex | email | mobile | version |
+----+--------+-----+---------------------+-------------+---------+
| 1 |  張三  | 0 | 18228937997@163.com | 18228937997 | 2 |
| 2 |  李四  | 0 | 1005349393@163.com | 15683202302 | 1 |
| 3 |  李四 1  | 0 | 1005349393@163.com | 15683202302 | 1 |
| 4 |  李四 2  | 0 | 1005349393@163.com | 15683202302 | 1 |
| 5 |  李四 3  | 0 | 1005349393@163.com | 15683202302 | 1 |
| 6 |  李四 4  | 0 | 1005349393@163.com | 15683202302 | 1 |
| 7 |  李四 55 | 0 | 1005349393@163.com | 15683202302 | 1 |
+----+--------+-----+---------------------+-------------+---------+
7 rows in set
Time: 0.011s

悲觀鎖

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

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

mysql root@127.0.0.1:demo  begin;
Query OK, 0 rows affected
Time: 0.002s
mysql root@127.0.0.1:demo  update `user` set name =  張三 111111 where id = 1;
Query OK, 1 row affected
Time: 0.004s

接著我們開啟事務二,對 id= 1 的數據進行 update 操作,查看此時會發生什么情況?

mysql root@127.0.0.1:demo  begin;
Query OK, 0 rows affected
Time: 0.002s
mysql root@127.0.0.1:demo  update `user` set sex = 1 where id = 1;

我們執行完 update 語句之后,就處于等待狀態,SQL 語句也不會馬上被執行,這是因為事務一沒有 commit,也就沒有釋放 id= 1 的數據對應的寫鎖。

效果如下圖:

樂觀鎖

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

樂觀鎖的實現原理:

一個事務在讀取數據時,將對應的版本號字段讀取出來,假設此時的版本號是 1。

另外一個事務也是執行同樣的讀取操作。當事務一提交時,對版本號執行 +1,此時該數據行的版本號就是 2。

第二個事務執行修改操作時,針對業務數據做條件,并默認增加一個版本號作為 where 條件。此時修改語句中的版本號字段是不滿足 where 條件,該事務執行失敗。通過這種方式來達到鎖的功能。

客戶端一:

mysql root@127.0.0.1:demo  select * from user where id = 1;
+----+------------+-----+---------------------+-------------+---------+
| id | name | sex | email | mobile | version |
+----+------------+-----+---------------------+-------------+---------+
| 1 |  張三 111111 | 0 | 18228937997@163.com | 18228937997 | 1 |
+----+------------+-----+---------------------+-------------+---------+
1 row in set
Time: 0.012s
mysql root@127.0.0.1:demo  update `user` set name =  事務一 , version = version + 1 where id = 1 and version = 1;
Query OK, 1 row affected
Time: 0.008s
mysql root@127.0.0.1:demo  select * from user where id = 1;
+----+--------+-----+---------------------+-------------+---------+
| id | name | sex | email | mobile | version |
+----+--------+-----+---------------------+-------------+---------+
| 1 |  事務一  | 1 | 18228937997@163.com | 18228937997 | 2 |
+----+--------+-----+---------------------+-------------+---------+
1 row in set
Time: 0.009s

執行 update 語句的順序應該在客戶端二執行了 select 之后,在執行。

客戶端二:

mysql root@127.0.0.1:demo  select * from user where id = 1;
+----+------------+-----+---------------------+-------------+---------+
| id | name | sex | email | mobile | version |
+----+------------+-----+---------------------+-------------+---------+
| 1 |  張三 111111 | 1 | 18228937997@163.com | 18228937997 | 1 |
+----+------------+-----+---------------------+-------------+---------+
1 row in set
Time: 0.015s
mysql root@127.0.0.1:demo  update `user` set name =  事務二 , version = version + 1 where id = 1 and version = 1;
Query OK, 0 rows affected
Time: 0.003s
mysql root@127.0.0.1:demo  select * from user where id = 1;
+----+--------+-----+---------------------+-------------+---------+
| id | name | sex | email | mobile | version |
+----+--------+-----+---------------------+-------------+---------+
| 1 |  事務一  | 1 | 18228937997@163.com | 18228937997 | 2 |
+----+--------+-----+---------------------+-------------+---------+
1 row in set
Time: 0.012s

此時根據 update 返回的結構,可以看出受影響的行數為 0,同時 select 查詢之后,返現數據也是事務一的數據。

適用場景

悲觀鎖:比較適合寫入操作比較頻繁的場景,如果出現大量的讀取操作,每次讀取的時候都會進行加鎖,這樣會增加大量的鎖的開銷,降低了系統的吞吐量。

樂觀鎖:比較適合讀取操作比較頻繁的場景,如果出現大量的寫入操作,數據發生沖突的可能性就會增大,為了保證數據的一致性,應用層需要不斷的重新獲取數據,這樣會增加大量的查詢操作,降低了系統的吞吐量。

關于“MySQL 樂觀鎖和悲觀鎖如何實現”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“MySQL 樂觀鎖和悲觀鎖如何實現”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-13發表,共計5203字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 盘锦市| 汽车| 葵青区| 沐川县| 房产| 上杭县| 蒙自县| 涿鹿县| 桑日县| 民县| 张掖市| 慈利县| 习水县| 襄汾县| 长岛县| 潜山县| 巢湖市| 蒙自县| 将乐县| 阜城县| 丰都县| 方城县| 湖州市| 河津市| 上林县| 阆中市| 中山市| 泊头市| 松桃| 遂川县| 潞西市| 凉城县| 枣阳市| 莎车县| 方正县| 亚东县| 莱西市| 无锡市| 安平县| 桃园县| 尤溪县|