本篇文章給大家?guī)?lái)了關(guān)于mysql中共享鎖和排他鎖的相關(guān)知識(shí),希望對(duì)大家有幫助。
共享鎖(Shared Lock)
共享鎖、S鎖、讀鎖 ,都是他的叫法。
而我,喜歡叫他 共享讀鎖 。
A shared (S) lock permits the transaction that holds the lock to read 。
共享鎖允許持有該鎖的事務(wù)讀取。
這里的共享是, 讀讀共享 。
也就是說(shuō), 無(wú)論是 行級(jí)或是表級(jí) , 如果 對(duì)某數(shù)據(jù) 上了 共享讀鎖 ,其他事務(wù)可以繼續(xù) 讀(也就是允許持有共享讀鎖), 但是 不能寫(xiě),也就是 讀寫(xiě)互斥。
順便介紹一下如何 加 共享鎖(共享讀鎖) :
上表級(jí)共享鎖,也就是表級(jí)共享讀鎖:
select * from table(表) lock in share mode ;
上行級(jí)共享鎖,也就是行級(jí)共享讀鎖:
select * from table(表)where id = 10 lock in share mode ;
在這啰唆一點(diǎn), 注意了,在InnoDB 下, 不是你想用行鎖就用行鎖的,行鎖的觸發(fā)條件我們?cè)俅位仡櫹拢ㄩ_(kāi)篇有提到):
排他鎖(Exclusive Lock)
排他鎖 、寫(xiě)鎖、X鎖 ,都是他的叫法。
而我,喜歡叫他 獨(dú)占寫(xiě)鎖。
An exclusive (X) lock permits the transaction that holds the lock to update or delete。
獨(dú)占(X)鎖允許持有鎖的事務(wù)更新或刪除。
獨(dú)占 ,這個(gè)詞。 打過(guò)籃球沒(méi),以前初中打籃球不懂事,拿著球就不傳。同學(xué)就說(shuō)我,你好獨(dú)啊。
是的,我很獨(dú)。 就跟這個(gè)獨(dú)占寫(xiě)鎖 (排他鎖) 一樣,很獨(dú)。
當(dāng)事務(wù)對(duì)某數(shù)據(jù)加上了 獨(dú)占寫(xiě)鎖 (排他鎖) ,只有當(dāng)前事務(wù)能夠?qū)@數(shù)據(jù)執(zhí)行修改或刪除操作。
其他事務(wù),不能讀,不能寫(xiě) 。 因?yàn)?這個(gè)鎖 很獨(dú), 必須等這個(gè)很獨(dú) 的鎖 使用完了(釋放),其他事務(wù)才有機(jī)可乘。
所以,獨(dú)占寫(xiě)鎖 (排他鎖) 是,讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥的。
順便介紹一下如何 加 排他鎖(獨(dú)占寫(xiě)鎖) :
上表級(jí)排他鎖,也就是表級(jí)獨(dú)占寫(xiě)鎖:
select * from table for update ;
上行級(jí)排他鎖,也就是行級(jí)獨(dú)占寫(xiě)鎖:
select * from table where id =10 for update ;
在這我再再啰唆一點(diǎn), 注意了,在InnoDB 下, 不是你想用行鎖就用行鎖的,行鎖的觸發(fā)條件我們?cè)俅位仡櫹拢ㄩ_(kāi)篇有提到):
上面的sql能上行級(jí)排他鎖,是因?yàn)槊辛怂饕?id 是 索引。
也許看到這里,你對(duì) 共享鎖 & 排他鎖還只是云里霧里 ,大致知道個(gè)什么讀讀共享、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥啥的。
所以,我們需要再次 從上帝視角再看一次 這兩個(gè)鎖 ,
紅色 事務(wù)操作一
藍(lán)色 事務(wù)操作二
共享鎖(共享讀鎖) | 排他鎖(獨(dú)占寫(xiě)鎖) | |
共享鎖(共享讀鎖) | 可以,兼容,一起讀 | 不可以,不兼容,想寫(xiě)得等共享鎖沒(méi)了 |
排他鎖(獨(dú)占寫(xiě)鎖) | 不可以,不兼容,上了排他鎖,別人啥都不能動(dòng) | 不可以,不兼容,上了排他鎖,別人啥都不能動(dòng) |
那么如果你看到這里,還是對(duì) 共享鎖 & 排他鎖還只是云里霧里。
那我只有動(dòng)手了!
實(shí)戰(zhàn)介紹,演示 所謂的讀讀共享、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥 。
在演示讀讀共享、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥前, 我必須點(diǎn)明一點(diǎn)!
在這篇文章里面,我介紹了一些上 共享鎖(共享讀鎖)、排他鎖(獨(dú)占寫(xiě)鎖)的方式 。 但是 可以看到寫(xiě)的查詢sql 都是后面加了東西的 , lock in share mode ,for update …. 等。
所以我想點(diǎn)明的一點(diǎn)是,
如果是使用 普通的查詢 ,是 什么鎖都沒(méi)上的!
就好像平時(shí)我們經(jīng)常寫(xiě)的
select * from table ;
select * from table where age=18;
select語(yǔ)句默認(rèn)不會(huì)加任何鎖類型
select語(yǔ)句默認(rèn)不會(huì)加任何鎖類型
select語(yǔ)句默認(rèn)不會(huì)加任何鎖類型
而排他鎖,除了 select …. for update ,InnoDB引擎 默認(rèn)的修改 、插入、刪除(update,insert,delete)都是會(huì)給操作的相關(guān)數(shù)據(jù) 加 排他鎖的 .
廢話不多說(shuō),我們上才藝:
準(zhǔn)備一些用于測(cè)試的數(shù)據(jù)。
建表:
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `age` int(11) NULL DEFAULT NULL, `sex` tinyint(1) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
搞點(diǎn)模擬數(shù)據(jù):
(id主鍵索引)
第一個(gè)小實(shí)踐:
我們不廢話,我們直接上共享讀鎖, 看看是不是能 符合剛才我們的理論 讀讀共享,讀寫(xiě)互斥!
1. 我們先給id=3這數(shù)據(jù)上個(gè) 共享讀鎖:
2.基于當(dāng)前狀況, 我們?cè)賵?zhí)行一下查詢語(yǔ)句,也是使用共享讀鎖的:
3.那么也是基于當(dāng)前情況,我們?cè)賵?zhí)行一下使用排他寫(xiě)鎖的查詢語(yǔ)句,可以發(fā)現(xiàn) 讀寫(xiě)互斥了:
4.驗(yàn)證下,我們查看當(dāng)前是否存在事務(wù)在等待鎖:
可以從結(jié)果中看出 事務(wù)請(qǐng)求id 34847在等待鎖:
我們?cè)俨樵円幌?,那些事?wù)在使用鎖,
可以從結(jié)果看出,34844事務(wù)在使用S鎖,也就是共享讀鎖;
而34847事務(wù) 在使用 X鎖, 也就是排他寫(xiě)鎖(但是由于共享讀鎖先上了,所以讀寫(xiě)互斥了),所以造成了34847事務(wù) 在等待鎖。
5.那么如果我們一直不 COMMIT 共享讀鎖, 34847事務(wù) 會(huì)永無(wú)止息地等待鎖嗎? 那么肯定是不可能允許這種一直等待的場(chǎng)景的:
所以mysql會(huì)有個(gè)等待鎖資源超時(shí)的機(jī)制,這種情況就會(huì)直接返回查詢失敗的結(jié)果。
根據(jù)第一個(gè)小實(shí)踐,我們得出一個(gè)很明顯的結(jié)論:
當(dāng)某數(shù)據(jù)上了 共享讀鎖 S 時(shí), 只允許其他事務(wù)上共享讀鎖 S, 因?yàn)樽x讀共享;
不允許其他事務(wù)上 獨(dú)占寫(xiě)鎖 X(除非把這個(gè)共享讀鎖S 釋放掉),因?yàn)樽x寫(xiě)互斥。
第二個(gè)小實(shí)踐:
1.我們直接給某行數(shù)據(jù)上個(gè)排他寫(xiě)鎖 X (注意我們的事務(wù)是沒(méi)有執(zhí)行COMMIT的) :
2. 我們接下來(lái)去 通過(guò)共享讀鎖去獲取數(shù)據(jù),看看會(huì)發(fā)生什么?
這就是 獨(dú)占寫(xiě)鎖 X 的 讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥 (寫(xiě)寫(xiě)互斥的場(chǎng)景就不展示了).
再驗(yàn)證下,我們看下是不是存在事務(wù)在等待鎖資源:
3.那么如果獨(dú)占寫(xiě)鎖一直不釋放,其余事務(wù)時(shí)一直等待嗎?
也是一樣,會(huì)等待超時(shí)返回查詢失?。?br />
補(bǔ)充一個(gè)小實(shí)踐:
1. 還是一樣,先給某個(gè)數(shù)據(jù)上 獨(dú)占寫(xiě)鎖,不COMMIT:
2. 執(zhí)行普通的查詢,select :
可以看到,普通的select語(yǔ)句能正常獲取,為什么? 因?yàn)榍懊嫖覀兲岬搅耍?/p>
所以我必須再啰唆一下,所謂的 讀讀共享,讀寫(xiě)互斥,寫(xiě)寫(xiě)互斥 ,都是對(duì)于鎖資源來(lái)說(shuō)的,如果你都沒(méi)有鎖資源競(jìng)爭(zhēng),那肯定不存在什么互斥什么互斥了。
推薦學(xué)習(xí):mysql視頻教程