1. 鎖
提到鎖趴生,一般都是因為存在競爭條件(Race Condition)而導致結果不可預測站辉。比如兩個線程同時修改某個值握巢,最終這個值的結果是什么有多種可能性。如果加入鎖敞曹,在線程訪問修改某個值的時候,可以禁止其他線程同時訪問修改這個值颤诀,這樣就避免了多種結果的可能性掂名。
MySQL Innodb的鎖的最小單位是行鎖,基于索引(Index)實現(xiàn)捶牢,加鎖的時候是在B+樹索引結構的節(jié)點上加鎖鸠珠。所以如果某個字段沒有索引,然后用戶通過這個字段進行查找來更新數(shù)據(jù)的時候就會導致整個表(其實是整個聚類索引的葉子結點)被加鎖秋麸;如果用戶通過聚類索引的字段進行查找渐排,則只對索引查找結果的葉子節(jié)點加鎖;如果用戶通過二級索引字段進行查找灸蟆,則除了對二級索引加鎖驯耻,還會對聚類索引加鎖。
2. 事務
事務具有ACID特性:分別是原子性(atomicity)炒考,一致性(consistency)可缚,隔離性(isolation),和持久性(durability)斋枢。
原子性(atomicity)是指一個事務內(nèi)的操作要不全被commit城看,要不整個rollback。
一致性(consistency)是指系統(tǒng)始終處于一致的狀態(tài)杏慰,事務操作只會使系統(tǒng)從一個狀態(tài)變幻到另一個一致的狀態(tài)测柠。
隔離性(isolation)是指各個事務之間是獨立的,隔離的缘滥,彼此不會相互影響轰胁。
持久性(durability)是指事務提交之后數(shù)據(jù)持久保存在數(shù)據(jù)庫系統(tǒng)中。
3. 數(shù)據(jù)庫的隔離級別
數(shù)據(jù)庫的隔離級別(Isolation level)分為:未提交讀(Uncommit Read)朝扼,提交讀(Commit Read)赃阀,可重復讀(Repeatable Read)和可串行化(Serializable)。
在了解隔離級別之前先來看看InnoDB讀的分類:快照讀(snapshot read)和現(xiàn)讀(current read)擎颖。
一般的SELECT
都是快照讀榛斯,其他的讀都屬于現(xiàn)讀,比如SELECT * FROM tableName FOR SHARE
搂捧⊥运祝快照讀不加鎖,根據(jù)隔離級別的不同讀取策略也不同允跑;現(xiàn)讀會加S鎖(共享鎖)或者X鎖(互斥鎖)王凑,其中SELECT ... FOR SHARE
會加S鎖搪柑,其他情況都是加X鎖。
未提交讀(Uncommit Read)就是快照讀可以讀取事務內(nèi)修改了但是未提交的值索烹,這種情況下就會產(chǎn)生臟讀工碾。一般不會考慮設置為數(shù)據(jù)庫隔離級別。
提交讀(Commit Read)就是快照讀只可以讀取提交之后的數(shù)據(jù)百姓。這樣就消除了臟讀的產(chǎn)生渊额,但是會有幻讀產(chǎn)生的可能性。所謂幻讀就是本來要修改了年齡等于20的用戶的表信息垒拢,事務提交之后發(fā)現(xiàn)有些“沒有修改成功”端圈,因為有線程在上述事務期間插入了年齡為20的新用戶信息,這樣會有一種操作未成功的錯覺子库。是MySQL的默認隔離級別舱权。
可重復讀(Repeatable Read)的隔離級別下除了一般的行鎖,也會同時加上間隙鎖(gap lock)仑嗅。間隙鎖防止了幻讀的產(chǎn)生:上例中age為20的B+樹節(jié)點之間和范圍前后節(jié)點之間也會被加鎖宴倍,導致age為20的新數(shù)據(jù)無法插入。
可串行化(Serializable)的隔離級別下仓技,快照讀不復存在鸵贬,所有的讀都是現(xiàn)讀。讀寫沖突脖捻,導致性能下降阔逼。一般不會考慮設置為數(shù)據(jù)庫隔離級別。
4. 死鎖以及如何避免死鎖
Reference
hedengcheng.com/?p=771