1. mysql鎖基礎(chǔ)
知識(shí)點(diǎn)范圍:
鎖等待現(xiàn)象
表級(jí)鎖:鎖住一張表的數(shù)據(jù) =》 myisam ,innodb
頁(yè)級(jí)鎖:是鎖一頁(yè)的數(shù)據(jù)
行級(jí)鎖:鎖住一行的數(shù)據(jù) =》 innodb
1.1
- InnoDB 存儲(chǔ)引擎既支持行級(jí)鎖,也支持表級(jí)鎖,默認(rèn)情況下使用行級(jí)鎖。
- 所謂表級(jí)鎖,它直接鎖住的是一個(gè)表,開銷小,加鎖快,不會(huì)出現(xiàn)死鎖的情況,鎖定粒度大,發(fā)生鎖,沖突的概率更高,并發(fā)度最低。
- 所謂行級(jí)鎖,它直接鎖住的是一條記錄,開銷大,加鎖慢,發(fā)生鎖沖突的概率較低,并發(fā)度很高。
- 所謂頁(yè)級(jí)鎖,它是鎖住的一個(gè)頁(yè)面,在 InnoDB 中一個(gè)頁(yè)面為16KB,它的開銷介于表級(jí)鎖和行級(jí)鎖中間,也可能會(huì)出現(xiàn)死鎖,鎖定粒度也介于表級(jí)鎖和行級(jí) 鎖中間,并發(fā)度也介于表級(jí)鎖和行級(jí)鎖中間。
僅僅從鎖的角度來(lái)說(shuō),表級(jí)鎖更加適合于以查詢?yōu)橹鞯膽?yīng)用,只有少量按照索引條件更新數(shù)據(jù)的應(yīng)用,比如大多數(shù)的 web 應(yīng)用。
行級(jí)鎖更適合大量按照索引條件并發(fā)更新少量不同的數(shù)據(jù),同時(shí)還有并發(fā)查詢的應(yīng)用,比如一些在線事務(wù)處理系統(tǒng),即 OLTP。
下面介紹innodb引擎的鎖
innodb鎖
1.InnoDB 與 MyISAM 的相當(dāng)大的兩點(diǎn)不同在于: (1) 支持事務(wù) (2) 采用行級(jí)鎖
2.行級(jí)鎖本身與表級(jí)鎖的實(shí)現(xiàn)差別就很大,而事務(wù)的引入也帶來(lái)了很多新問(wèn)題,尤其是事務(wù)的隔離性,與鎖機(jī)制息息相關(guān)。
3.對(duì)于事務(wù)的基本操作,對(duì)于不同隔離級(jí)別可能引發(fā)的問(wèn)題,像臟讀、不可重復(fù)讀等問(wèn)題。
4.數(shù)據(jù)庫(kù)實(shí)現(xiàn)事務(wù)隔離的方式,基本可以分為兩種:
(1) 在操縱數(shù)據(jù)之前,先對(duì)其加鎖,防止其他事務(wù)對(duì)數(shù)據(jù)進(jìn)行修改。這就需要各個(gè)事務(wù)串行操作才 可以實(shí)現(xiàn)。
(2) 不加任何鎖,通過(guò)生成一系列特定請(qǐng)求時(shí)間點(diǎn)的一致性數(shù)據(jù)快照,并通過(guò)這個(gè)快照來(lái)提供一致 性讀取。
5.上面的第二種方式就是數(shù)據(jù)多版本并發(fā)控制,也就是多版本數(shù)據(jù)庫(kù),一般簡(jiǎn)稱為 MVCC 或者 MCC,它是 Multi Version Concurrency Control 的簡(jiǎn)寫。
6.數(shù)據(jù)庫(kù)的事務(wù)隔離越嚴(yán)格,并發(fā)的副作用就越小,當(dāng)然付出的代價(jià)也就越大,因?yàn)槭聞?wù)隔離機(jī)制實(shí)質(zhì)上是使得事務(wù)在一定程度上”串行化”,這與并行是矛盾 的。
innodb鎖的類型
1.InnoDB 實(shí)現(xiàn)了下面兩種類型的鎖:
- (1)共享鎖(S):允許一個(gè)事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖。
- (2)排他鎖(X):允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)獲得相同數(shù)據(jù)集的共享讀鎖和排他寫 鎖。
- 這里有個(gè)鎖兼容和沖突的概念,如果在加一個(gè)鎖的時(shí)候,另一個(gè)鎖可以加上去,那么就是鎖兼容。如 果加上一個(gè)鎖之后,拒絕其他的鎖加上,那么就是鎖沖 突。
- 我們可以使用如下語(yǔ)句來(lái)顯式的給數(shù)據(jù)集加鎖:
(1)共享鎖(S):select * from t1 where ... lock in share mode; (2)排他鎖(X):select * from t1 where ... for update;
- 我們可以用 select ...in share mode 來(lái)獲得共享鎖,主要用在數(shù)據(jù)依存關(guān)系時(shí)來(lái)確認(rèn)某行記錄是否存 在,并確認(rèn)沒有人對(duì)這個(gè)記錄進(jìn)行 update 或者 delete 操 作。
- 我們可以使用 select... for update 來(lái)獲得排他鎖,它會(huì)拒絕其他事務(wù)在其上加其他鎖。
注解:排它鎖加鎖語(yǔ)法:
--給`user`表id為1的數(shù)據(jù)加排它鎖
start transaction--開啟事務(wù)
select * from `user` where id=1 for update;--給id為1的數(shù)據(jù)加排它鎖
commit;--提交事務(wù)
rollback;--回滾事務(wù)
注解:共享鎖加鎖語(yǔ)法:
start transaction--開啟事務(wù)
select * from `user` where id=1 lock in share mode;--給id為1的數(shù)據(jù)加共享鎖
commit;--提交事務(wù)
rollback;--回滾事務(wù)
(重點(diǎn))注解:當(dāng)事務(wù)給一行數(shù)據(jù)加共享鎖,那么其他事務(wù)可以加共享鎖,但不能加排它鎖。
即:能讀不能寫,可以與共享鎖一起使用,但不能與排它鎖一起使用;
小結(jié):個(gè)人理解解釋
1.1 排它鎖:數(shù)據(jù)在用的時(shí)候,排它鎖是不能被查詢到的,只能上一個(gè)查詢完畢,提交完事物,才能進(jìn)行查詢下一個(gè)。排它鎖跟共享鎖不能一起使用。
1.2 共享鎖:可以進(jìn)行多個(gè)用戶共享數(shù)據(jù),排它鎖跟共享鎖也不能一起使用。
begin 會(huì)自動(dòng)開啟事物
對(duì)于update,insert,alter等寫操作,MySQL會(huì)自動(dòng)加上排它鎖。
當(dāng)前讀?。阂话阒傅氖羌渔i的select
快照讀取:一般指的是沒加鎖的普通查詢
下面我們來(lái)解釋另外鎖:樂觀鎖與悲觀鎖的解釋。
悲觀鎖:悲觀鎖,不管是什么鎖,只要是上了鎖都屬于悲觀鎖。
樂觀鎖:共享鎖就是樂觀鎖—MVCC
悲觀鎖,樂觀鎖:是一個(gè)概念,是一種思想。因?yàn)橹灰桥潘i,跟共享鎖,就叫悲觀,跟樂觀鎖。
在來(lái)看MySQL的死鎖
1.死鎖怎么產(chǎn)生的:
- 所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作 用,它們都將無(wú)法推進(jìn)下去.此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為 死鎖進(jìn)程。表級(jí)鎖不會(huì)產(chǎn)生死鎖.所以解決死鎖主要還是針對(duì)于最常用的InnoDB。
- 死鎖的關(guān)鍵在于:兩個(gè)(或以上)的Session加鎖的順序不一致。 那么對(duì)應(yīng)的解決死鎖問(wèn)題的關(guān)鍵就是:讓不同的session加鎖有次序。
個(gè)人理解
1.1 死鎖現(xiàn)象:在鎖等待的時(shí)候,我們稱為:死鎖
死鎖:一般是在事物1在執(zhí)行,事物2在等待。
鎖等待的時(shí)間是:wait timeout =120 設(shè)置的是鎖等待時(shí)間,鎖等待時(shí)間結(jié)束之后有一個(gè)失敗,一個(gè)成功。
mysql的選擇與事物的大小有關(guān)系,soloct舍小保大。
模糊查詢的查詢,范圍查詢,會(huì)導(dǎo)致死鎖。
說(shuō)明了事物與事物產(chǎn)生的死鎖
2.盡可能的避免事務(wù)死鎖
- 1)以固定的順序訪問(wèn)表和行。比如對(duì)第2節(jié)兩個(gè)job批量更新的情形,簡(jiǎn)單方法是對(duì)id列表先排序,后執(zhí) 行,這樣就避免了交叉等待鎖的情形;又比如對(duì)于3.1節(jié)的情形,將兩個(gè)事務(wù)的sql順序調(diào)整為一致,也能避 免死鎖。
- 2)大事務(wù)拆小。大事務(wù)更傾向于死鎖,如果業(yè)務(wù)允許,將大事務(wù)拆小。
- 3)在同一個(gè)事務(wù)中,盡可能做到一次鎖定所需要的所有資源,減少死鎖概率。
- 4)降低隔離級(jí)別(默認(rèn)事物隔離級(jí)別)。如果業(yè)務(wù)允許,將隔離級(jí)別調(diào)低也是較好的選擇,比如將隔離級(jí)別從RR調(diào)整為RC,可以避免掉很多因?yàn)間ap鎖造成的死鎖。
- 5)為表添加合理的索引??梢钥吹饺绻蛔咚饕龑?huì)為表的每一行記錄添加上鎖,死鎖的概率大大增大。
間隙鎖與行鎖升級(jí)為表鎖
1.1 間隙鎖:當(dāng)我們使用范圍查詢,而不是等式查詢,并請(qǐng)求或者排它鎖的時(shí)候
間隙鎖的危害會(huì)產(chǎn)生死鎖:如果在查詢中通過(guò)范圍去查詢,鎖鎖住的范圍會(huì)是所有索引的鍵值。即使這個(gè)數(shù)據(jù)不存在
什么情況下行鎖升級(jí)成表鎖
1.1 鎖去鎖住數(shù)據(jù)=》是與索引有一點(diǎn)的關(guān)聯(lián)
1.2 主鍵與唯一索引幾乎為0
1.3 普通索引:很大幾率會(huì)數(shù)據(jù)出現(xiàn)重復(fù)。
1.4:在不加索引的字段(除主鍵以及唯一索引之外)上進(jìn)行數(shù)據(jù)的加鎖,會(huì)升級(jí)為表鎖。
在加了索引之后加鎖會(huì)根據(jù)普通索引的基礎(chǔ)上去進(jìn)行加鎖。
而一旦索引失效,有會(huì)升級(jí)會(huì)表鎖。
- 會(huì)盡可能是索引字段進(jìn)行加鎖
- 盡可能使用等式而不是范圍性的查詢。
不只是排它鎖,共享鎖也是一樣的道理