根據(jù)加鎖范圍帖烘,mysql中的鎖的大致可以分為全局鎖亮曹,表鎖,行鎖秘症。
全局鎖
全局鎖就是對(duì)整個(gè)數(shù)據(jù)庫實(shí)例加鎖照卦。通過flush table with read lock命令,將堆數(shù)據(jù)庫加讀鎖乡摹。數(shù)據(jù)庫編程只讀狀態(tài)役耕,常用來作為數(shù)據(jù)庫備份的時(shí)候使用。但是趟卸,在事務(wù)引擎中蹄葱,并不是通過加全局鎖來備份的氏义,我們都知道在innodb引擎的RR隔離級(jí)別下锄列,在導(dǎo)數(shù)據(jù)之前會(huì)開啟一個(gè)事務(wù),由于MVCC的支持惯悠,數(shù)據(jù)庫還是可以進(jìn)行更新操作的邻邮。那為什還需要用全局鎖來備份呢?原因是只有事務(wù)引擎才支持克婶。
通過官方提供的邏輯備份工具mysqldump筒严,使用參數(shù)-single-transaction。
表鎖
- 表鎖通過命令lock tables ... T read/write可以提供表的讀/寫鎖情萤。
- 元數(shù)據(jù)鎖(meta data lock):MDL不需要顯示的使用鸭蛙,在訪問一個(gè)表的時(shí)候會(huì)自己加上。
如何安全的給小表加字段筋岛?
由于有MDL娶视,加入我們給小表加字段,加入之前已經(jīng)有訪問表的操作了,此時(shí)加字段操作將會(huì)堵塞肪获,直到之前的訪問結(jié)束寝凌,同時(shí)由于加字段操作堵塞了,之后的操作也會(huì)堵塞孝赫。導(dǎo)致系統(tǒng)不可讀寫较木。
- 方法一:加入有一個(gè)訪問表的長事務(wù),那么不加字段青柄,或者結(jié)束長事務(wù)伐债。
- 方法二:給加字段一個(gè)等待時(shí)間,在等待時(shí)間能沒有完成結(jié)束刹前。
行鎖
并不是所有的引擎都支持行鎖泳赋,MyISAM不支持行鎖,innodb則支持喇喉。mysql中的兩階段鎖祖今。當(dāng)我們開啟事務(wù)的時(shí)候,當(dāng)我們對(duì)一行數(shù)據(jù)進(jìn)行修改的時(shí)候拣技,在另一事務(wù)中千诬,我們還可不可以再修改這一行數(shù)據(jù)呢?答案是不可以膏斤,因?yàn)槭聞?wù)1會(huì)觸發(fā)行鎖徐绑,事務(wù)2的修改操作將會(huì)堵塞直到事務(wù)1提交,行鎖才釋放莫辨。所以在innodb引擎中行鎖并不是使用完就釋放的傲茄,得事務(wù)提交之后才釋放。
死鎖和死鎖檢測
當(dāng)出現(xiàn)資源的循環(huán)依賴的時(shí)候沮榜,就容易造成死鎖盘榨。
解決方法:
- 設(shè)置超時(shí)時(shí)間,通過設(shè)置innodb_lock_wait_timeout蟆融,默認(rèn)50s草巡。
- 開啟死鎖檢測,通過設(shè)置參數(shù)innodb_deadlock_detect=on型酥。
弊端:
設(shè)置超時(shí)時(shí)間并不是一個(gè)好辦法山憨,因?yàn)樵趯?shí)際中很難設(shè)置出合適的時(shí)間。死鎖檢測也并不是一個(gè)很好的辦法弥喉,假如對(duì)于一個(gè)熱點(diǎn)數(shù)據(jù)更新操作郁竟,每次都需要判斷是否死鎖,這將是一個(gè)很耗費(fèi)cpu的事情由境,會(huì)造成我們的數(shù)據(jù)庫cpu達(dá)到了100%但是每秒處理的事務(wù)卻很少棚亩。
怎么解決熱點(diǎn)數(shù)據(jù)更新導(dǎo)致的性能問題?
對(duì)于熱點(diǎn)數(shù)據(jù),最好的處理方法就是分流蔑舞,或者消息隊(duì)列拒担。分流指的是將處理分到多行中處理,降低某一行的并發(fā)量攻询,消息隊(duì)列的處理方式就是將操作保存到小實(shí)習(xí)隊(duì)列中排隊(duì)處理从撼。