深入理解mysql各種鎖

鎖的概述

鎖是計算機協調多個進程或線程並訪問某一資源的機制

在數據庫中,除傳統的計算機資源(如cpu、RAM、I/O等)的爭用以外,數據也是一種供許多用戶共享的資源,如果保證數據並發訪問的一致性,有效性是所有數據庫必須解決的一個問題,鎖沖突也是影響數據庫並發訪問性能的一個重要因素,從這個角度來說,鎖對數據庫而言顯得尤其重要,也更加復雜

鎖分類

對數據庫操作的粒度分

表鎖:
	操作時,會鎖定整個表
行鎖:
	操作時,會鎖定當前操作行

對數據操作的類型分

讀鎖(共享鎖):
	針對同一份數據,多個讀操作可以同時進行而不會相互影響
寫鎖(排它鎖):
	當操作沒有完成之前,它會阻斷其他寫鎖和讀鎖

mysql鎖

相對其他數據庫而言,Mysql的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。

不同存儲引擎支持鎖級別

存儲引擎 表級鎖 行級鎖 頁面鎖
MyISAM 支持 不支持 不支持
InnoDB 支持 支持 不支持
MEMORY 支持 不支持 不支持
BDB 支持 不支持 支持

鎖介紹

很難籠統說哪種鎖更好,需要根據特定的應用場景來分析哪種鎖更合適。

鎖類型 特點
表級鎖 偏向MyISAM存儲引擎,開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發送鎖沖突的概率最高,並發度最低。
行級鎖 偏向InnoDB存儲引擎,開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,並發度也最高。
頁面鎖 開銷和加鎖時間介於表鎖和行鎖之間;會出現死鎖;鎖定粒度介於表鎖和行鎖之間,並發度一般。

MyISAM表鎖

如何添加表鎖

MyISAM在執行查詢語句(select)前,會自動給涉的所有表加鎖,在執行更新操作(update、delete、insert等)前,會自動給涉及的表加寫鎖,這個過程並不需要用戶幹預,因此,用戶一般不需要直接使用LOCK TABLE命令給MyISAM表顯示加鎖

加解鎖

加讀鎖:
	lock table table_name read; 
	---解鎖 unlock tables;
加寫鎖:
	lock table table_name write;
	添加寫鎖當前會話可以讀寫操作,別的會話會處於阻塞(等待)狀態
讀鎖限制寫,寫鎖限制讀寫

鎖競爭

1、對MyISAM表的讀操作,不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;
2、對MyISAM的寫操作,則會阻塞其他用戶對表一表的讀和寫操作;
3、MyISAM鎖調度是寫優先。
	不適合作為主表,寫鎖後其他線程大量的更新會使查詢很難得到鎖,可能會造成永遠阻塞。

鎖的使用情況

查看鎖的使用情況
	show open tables;
查看表的鎖定情況
	show status like 'table_locks%';
		Table_locks_immediate:可以獲取表級鎖的次數,每立即獲取鎖,值加1
		Table_locks_waited:不能立即獲取鎖需要等待的次數,每等待一次,值加1,可以判斷比較嚴重的表級鎖爭用情況
	

InnoDB鎖

InnoDB與MyISAM的最大不同有亮點:一是支持事務;二是采用行級鎖

行鎖

共享鎖:
	又稱讀鎖,多個事務可以共享一把鎖,但是隻能讀,不能寫
排它鎖:
	又稱寫鎖,鎖不共用,獲取不到鎖的事務不能進行讀寫操作
如果進行update、delete和insert 語句,innoDB會自動給涉及數據集加排它鎖
對不同的select語句不會添加任何鎖
顯示的給查詢添加鎖
	添加共享鎖:
		select * from table_name where ... Lock IN SHARE MODE
	添加排它鎖:
		select * from table_name where ... FOR UPDATE

鎖升級

索引失效,行鎖升級表鎖
where後面沒索引也升級為表鎖

間隙鎖

InnoDB會對間隙不存在的數據也會加鎖,稱之為間隙鎖

鎖爭用

show status like 'innodb_row_lock%';
	Innodb_row_lock_current_waits當前正在等待鎖的數量
	Innodb_row_lock_time 鎖定的總時長
	Innodb_row_lock_time_avg 鎖定的平均時長
	Innodb_row_lock_time_max 鎖定的最大時長
	Innodb_row_lock_waits 系統啟動到現在總共等待次數

總結

innoDB存儲引擎實現瞭行鎖,雖然鎖定機制的實現方面帶來瞭性能消耗可能比較表鎖會更高些,但是在整體並發處理能力方面要遠優於MyISAM表鎖,當系統並發比較高的時候,InnoDB的整體性能和MyISAM會有比較明顯的優勢

優化建議

盡可能讓所有數據檢索都能通過索引來完成,避免無索引行鎖升級為表鎖
合理設計索引,盡量縮小鎖的范圍
盡可能減少索引條件,及索引范圍,避免間隙鎖
盡量控制事務大小,減少鎖定資源量和時間的長度
盡可能使用低級別事務隔離(需要業務能滿足需求)

到此這篇關於深入理解mysql各種鎖的文章就介紹到這瞭,更多相關mysql鎖內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: