在Mysql數據庫系統中,不一樣的存儲引擎支持不一樣的鎖機制。好比MyISAM和MEMORY存儲引擎採用的表級鎖,BDB採用的是頁面鎖,也支持表級鎖,InnoDB存儲引擎既支持行級鎖,也支持表級鎖,默認狀況下采用行級鎖。sql
MySQL這3種鎖的特性可大體概括以下:數據庫
模式 | 開鎖、加鎖速度、死鎖、粒度、併發性能 |
---|---|
表級鎖 | 開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。 |
行級鎖 | 開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。 |
頁面鎖 | 開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常。 |
本篇博客將記錄MyISAM儲存引擎中的表級鎖併發
共享讀:MyISAM表的讀操做,不會阻塞其餘用戶對同一個表的讀請求,但會阻塞對同一個表的寫請求.性能
操做命令:優化
//加鎖 lock table 表名 read //解鎖 unlock tables
實戰場景:spa
clientA: lock table roles read; //讀鎖 select * from roles where id = 1; //查詢成功 clientB: select * from roles where id = 1; //查詢成功 update roles set name = 'root'; //卡住,等待鎖釋放 ClientA: unlock tables; //解鎖 clientB: update roles set name = 'root2'; //更新成功
獨佔寫:MyISAM表的寫操做,會阻塞其餘用戶對同一個表的讀和寫操做。3d
操做命令:code
//加鎖 lock table 表名 write //解鎖 unlock tables
實戰場景:blog
clientA: lock table roles write; //寫鎖 select * from roles where id = 1; //查詢成功 update roles set name = 'admin' where id = 1; //更新成功 clientB: select * from roles where id = 1; //卡住,等待鎖釋放 ClientA: unlock tables; //解鎖 clientB: select * from roles where id = 1; //查詢成功
經過檢查table_locks_waited(表鎖等待,沒法當即得到數據)和table_locks_immediate(當即得到鎖地查詢數目)狀態變量分析系統上表鎖爭奪狀況隊列
show status like '%table_lock%'
分析:若是Table_locks_waited 數值比較高,就說明存在着較嚴重的表級鎖爭用狀況 ,性能有問題,併發高,須要優化.
MyISAM存儲引擎的讀和寫鎖是互斥,讀操做是串行的。
那麼,一個進程請求某個MyISAM表的讀鎖,同時另外一個進程也請求同一表的寫鎖,MySQL如何處理呢?答案是寫進程先得到鎖。不只如此,即便讀進程先請求先到鎖等待隊列,寫請求後到,寫鎖也會插到讀請求以前!這是由於MySQL認爲寫請求通常比讀請求重要。這也正是MyISAM表不太適合於有大量更新操做和查詢操做應用的緣由,由於,大量的更新操做會形成查詢操做很難得到讀鎖,從而可能永遠阻塞。這種狀況有時可能會變得很是糟糕!幸虧咱們能夠經過一些設置來調節MyISAM的調度行爲。
雖然上面3種方法都是要麼更新優先,要麼查詢優先的方法,但仍是能夠用其來解決查詢相對重要的應用(如用戶登陸系統)中,讀鎖等待嚴重的問題。
另外,MySQL也提供了一種折中的辦法來調節讀寫衝突,即給系統參數max_write_lock_count設置一個合適的值,當一個表的讀鎖達到這個值後,MySQL變暫時將寫請求的優先級下降,給讀進程必定得到鎖的機會。
參考:《MySQL數據庫鎖機制之MyISAM引擎表鎖和InnoDB行鎖詳解》