mysql中的鎖機制之悲觀鎖和樂觀鎖

一、悲觀鎖?

悲觀鎖顧名思義就是很悲觀,悲觀鎖認爲數據隨時就有可能會被外界進行修改,因此悲觀鎖一上來就會把數據給加上鎖。悲觀鎖通常都是依靠關係型數據庫提供的鎖機制,然而事實上關係型數據庫中的行鎖,表鎖不管是讀寫鎖都是悲觀鎖。數據庫

二、樂觀鎖?

樂觀鎖顧名思義,就是很樂觀,每次本身操做數據的時候認爲沒有人會來修改它,因此不會去對數據進行加鎖。可是在更新的時候會去判斷在此期間數據有沒有被修改,須要用戶本身去實現樂觀鎖。樂觀鎖不會發生併發搶佔資源,只有在提交操做的時候檢查是否違反數據完整性。服務器

2.一、爲何要使用樂觀鎖呢?

①、對於讀操做遠多於寫操做的時候,大多數都是讀取,這時候一個更新操做加鎖會阻塞全部讀取,下降了吞吐量併發

②、最後還要釋放鎖,鎖是須要一些開銷的,咱們只要想辦法解決極少許的更新操做的同步問題測試

③、換句話說,若是讀寫比例差距不是很是大或者你的系統沒有響應不及時,吞吐量瓶頸問題,那就不要去使用樂觀鎖,它增長了複雜度,也帶來了額外的風險spa

2.二、樂觀鎖的實現方式

前期準備工做(準備數據表和測試數據):code

CREATE TABLE `employee`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `dep_id` int(11) NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `salary` decimal(10, 2) NULL DEFAULT NULL,
  `cus_id` int(11) NULL DEFAULT NULL,
  `version` int(11) NULL DEFAULT NULL COMMENT '用來給樂觀鎖進行標識的字段',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_name_age`(`name`, `age`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
 
 
-- 插入測試數據
INSERT INTO `employee` VALUES (1, '李白', 1, 10, 1000.00, 1, 1);
INSERT INTO `employee` VALUES (2, '韓信', 1, 20, 2000.00, 1, 1);
INSERT INTO `employee` VALUES (3, '露娜', 1, 20, 2500.00, 1, 1);
INSERT INTO `employee` VALUES (4, '公孫離', 4, 20, 3000.00, 1, 1);
INSERT INTO `employee` VALUES (5, '虞姬', 4, 40, 3500.00, 2, 1);
INSERT INTO `employee` VALUES (6, '孫尚香', 6, 20, 5000.00, 1, 1);
INSERT INTO `employee` VALUES (7, '馬可波羅', 6, 50, 5000.00, 1, 1);
INSERT INTO `employee` VALUES (8, '后羿', 30, 35, 4000.00, 1, 1);

2.2.一、版本號的實現方式:blog

①、就是給數據增長一個版本標識,在數據表上增長一個version字段事務

②、每次更新把這個字段加1ci

③、讀取數據的時候把version讀出來,更新的時候比較version資源

④、若是仍是開始讀取的version就能夠更新了

⑤、若是如今的version比老的version大,說明有其餘事務更新了該數據,並增長了版本號

⑥、這時候獲得一個沒法更新的通知,用戶自行根據這個通知來決定怎麼處理,好比從新開始一遍

版本號的方式實現樂觀鎖示例:

-- 先獲取version字段的值,這裏version字段的值目前是:1
SELECT version FROM employee WHERE id = 1;
 
-- 更新該條數據的時候作數據驗證,更新成功後將version字段的值累加1,更新條件除了id還要加上version=上面取出來的值 才能進行更新
UPDATE employee SET `name` = '李白大魔王',version = version + 1 WHERE id = 1 AND version = 1;

示例截圖:

2.2.二、時間戳的實現方式:

①、和上面的版本號基本同樣,只是經過時間戳來判斷而已,注意時間戳要使用數據庫服務器的時間戳不能是業務系統的時間

②、一樣是在須要樂觀鎖控制的table(表)中增長一個字段,字段名稱無所謂

③、字段類型使用時間戳, 和上面的version相似,也是在更新提交的時候檢查當前數據庫中數據的時間戳和本身更新前取到的時間戳進行對比

④、若是一致則OK 執行更新操做,不然就是版本衝突

相關文章
相關標籤/搜索