mysql鎖相關(guān)知識
按操作分類:
共享鎖:
也叫讀鎖。針對同一數(shù)據(jù),多個事務(wù)讀取操作可以同時加鎖互不影響,但是不能修改數(shù)據(jù)。
innodb 共享鎖:
sql+ lock in share mode;例 select * from student lock in share mode;
當(dāng)開啟共享鎖的時候,當(dāng)前事務(wù)可以查詢數(shù)據(jù)、修改數(shù)據(jù),并且可以更換鎖的類型;其他事務(wù)可以對該行進行共享鎖查詢,但是不能加排他鎖查詢,也不能修改數(shù)據(jù)。
myisam 讀鎖:
加鎖:lock table 表名 read;解鎖:unlock tables;
可以多個會話同時對一個表添加讀鎖,但是不能修改數(shù)據(jù)以及添加寫鎖。同一個會話添加讀鎖后也不能修改當(dāng)前表的數(shù)據(jù),
排他鎖:
也叫做寫鎖。當(dāng)前操作沒完成時,會阻斷其他操作的加鎖讀取和修改數(shù)據(jù)。
innodb 排他鎖:
sql+for update 例 select * from student for update;
當(dāng)開啟排他鎖時,當(dāng)前事務(wù)可以查找數(shù)據(jù)和修改數(shù)據(jù),也可以修改鎖的類型,但是即便從排他鎖變成共享鎖,其他事務(wù)也不能加鎖查詢,本質(zhì)上還是排他鎖,其他事務(wù)只能查詢數(shù)據(jù),不能加鎖也不能修改數(shù)據(jù)。
myisam 寫鎖:
lock table 表名 write ;解鎖:unlock tables;
當(dāng)前會話可以查詢和修改數(shù)據(jù),其他會話不能查詢和修改數(shù)據(jù)
按粒度分類:
表級鎖:
鎖住整個表,開銷小,加鎖快,鎖粒度大,發(fā)生鎖沖突概率高,并發(fā)力度低,不會出現(xiàn)死鎖現(xiàn)象。
myisam存儲引擎支持的就是表鎖,innodb存儲引擎也支持表鎖,但是默認(rèn)的是行鎖
行級鎖:
鎖住當(dāng)前行,開銷大,加鎖慢,鎖粒度小,發(fā)生鎖沖突概率低,并發(fā)度高,會出現(xiàn)死鎖現(xiàn)象。
innodb存儲引擎默認(rèn)支持行鎖,但是需要用索引當(dāng)作檢索條件才能施加行鎖(命中數(shù)據(jù)增加行鎖,如果不命中數(shù)據(jù)則增加間隙鎖(RR隔離級別)),否則會從行鎖升級為表鎖(RR級別會升級成表鎖,RC級別不會,因為在RR級別上要保證可重復(fù)讀,所以在遍歷掃描數(shù)據(jù)的時候,為了防止掃描過的數(shù)據(jù)被其他數(shù)據(jù)修改或間隙被插入數(shù)據(jù),從而導(dǎo)致數(shù)據(jù)不一致,索引mysql就把所有掃描過的數(shù)據(jù)和間隙都加上鎖)
意向鎖:
意向鎖主要是針對表鎖的,主要是為了提高加表鎖的效率,是mysql自己加的鎖,當(dāng)事務(wù)給表的數(shù)據(jù)行加了共享鎖或者排他鎖的時候,同時會給表設(shè)置一個表示,代表這張表已經(jīng)加了行鎖,其他事務(wù)想要加表鎖的時候,就不必要逐行判斷有沒有行鎖可能對表鎖造成沖突,直接讀取這個標(biāo)記就知道該不該枷鎖,而這個標(biāo)記就是意向鎖
按照使用方式:
悲觀鎖:
對數(shù)據(jù)被外界修改保持保守狀態(tài),認(rèn)為數(shù)據(jù)隨時會被修改,整個數(shù)據(jù)處理過程中需要將數(shù)據(jù)加鎖,悲觀鎖一般都是依靠關(guān)系型數(shù)據(jù)庫提供的鎖機制,我們之前學(xué)過的鎖(共享鎖,排他鎖,讀鎖,寫鎖)都是悲觀鎖;用于寫多讀少
樂觀鎖:
每次自己操作數(shù)據(jù)的時候認(rèn)為沒有人會修改他,所以不去加鎖,但是在更新的時候去判斷再次期間數(shù)據(jù)有沒有被修改,需要用戶自己去實現(xiàn),不會發(fā)生搶占資源,只有在提交操作的時候檢查是否違反數(shù)據(jù)完整性;用于讀多寫少
方式:給數(shù)據(jù)表添加一個version列,每次 更新后都將這個列的值加一,讀取數(shù)據(jù)時,將版本號取出來,在執(zhí)行更新的時候,比較版本號,如果相同則執(zhí)行,如果不相同說明這條數(shù)據(jù)已經(jīng)發(fā)生變化了,用戶自行根據(jù)這個通知來決定怎么處理,比如重新更新一次或者放棄更新。
事務(wù)與鎖狀態(tài)信息查看
-- 查看事務(wù)時間超過60秒的事務(wù)
select * from INFORMATION_SCHEMA.INNODB_TRX WHERE TIMESTAMPDIFF(SECOND ,trx_started,NOW()) > '60';
-- 查看鎖
select * from INFORMATION_SCHEMA.INNODB_LOCKS;
-- 查看鎖等待
select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
-- 釋放鎖,trx_mysql_thread_id可以從INNODB_TRX表里查看到
kill trx_mysql_thread_id;
-- 查看最近一次死鎖信息
show engine innodb status;
大事務(wù)的影響
1、并發(fā)情況下,容易造成數(shù)據(jù)庫連接池被撐爆
2、鎖定的數(shù)據(jù)過多,容易造成大量阻塞和鎖超時
3、執(zhí)行時間長,容易造成主從延遲
4、回滾所需要的時間比較長
5、undo log 膨脹
6、容易導(dǎo)致死鎖
事務(wù)優(yōu)化實踐原則
1、對于RC事務(wù)級別,可以將查詢等數(shù)據(jù)準(zhǔn)備操作放到事務(wù)外進行
2、事務(wù)中避免進行遠程調(diào)用,遠程調(diào)用要設(shè)置超時時間,防止事務(wù)等待太久
3、一次事務(wù)避免處理太多數(shù)據(jù),可以拆分成多個事務(wù)分次處理
4、更新等涉及加鎖的操作盡可能放在事務(wù)靠后的位置(因為更新操作是已經(jīng)存在的數(shù)據(jù),有可能其他事務(wù)還會使用這條記錄,那么會造成等待)
5、能異步處理的盡可能異步處理
6、對于簡單的業(yè)務(wù),應(yīng)用業(yè)務(wù)代碼來保證數(shù)據(jù)準(zhǔn)確性,不通過事務(wù)