??? 鎖機制是數據庫系統區別于文件系統的一個關鍵特性,他可以確保用戶能以一致的方式讀取和修改數據。
??? 為了保證一致性,必須有鎖的介入。MySQL操作緩沖池中的LRU列表,刪除、添加、移動LRU列表中的元素等地方也都適用鎖,從而允許對多種不同資源的并發訪問。
??? 打個比方,我們到淘寶上買一件商品,商品只有一件庫存,這個時候如果還有另一個人買,那么如何解決是你買到還是另一個人買到的問題?
??? 這里肯定要用到事物,我們先從庫存表中取出物品數量,然后插入訂單,付款后插入付款表信息,然后更新商品數量。在這個過程中,使用鎖可以 對有限的資源進行保護 ,解決隔離和并發的矛盾。???
MySQL的鎖管理機制:
- Meta-data元數據鎖:在table cache緩存里實現的,為DDL(Data Definition Language)提供隔離操作。一種特別的meta-data元數據類型,叫 Name Lock 。(SQL層)
- 表級table-level數據鎖(SQL層)
- 存儲引擎特有機制 — row locks行鎖,page locks頁鎖,table locks表級 ,版本控制(在引擎中實現)
- 全局讀鎖 — FLUSH TABLES WITH READ LOCK(SQL層)
上張圖:
?
MySQL的鎖執行流程:
- 計算語句使用到的所有表
- 在每個表:打開open表 — 從table cache緩存里得到TABLE對象,并在此表加上meta-data元數據鎖
- 等待全局讀鎖后改變數據
- 在每個表:鎖lock表 — 在表加上table-level數據鎖
- 執行語句:調用:handler::write_row()/read_rnd()/read_index(),等;隱式地調用引擎級engine-level鎖機制
- 在每個表:釋放表的數據鎖
- 在每個表:釋放表的DDL鎖并把表放回table cache緩存里
- DDL語句也是一樣,沒有典型的執行計劃。
?
MySQL三種鎖地級別:頁級、表級、行級。
三種鎖地特性:
??? 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。
??? 行級鎖:開銷稍大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高。
??? 頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般。
???
??? 在執行SQL語句時,會實現存儲引擎內部鎖,比如InnoDB存儲引擎的“行鎖”(MyISAM存儲引擎只支持表鎖,而InnoDB存儲引擎支持行鎖。實際上, 行鎖并不總是會增加開銷 ,只有當實現本身增加開銷時,行鎖才會增加開銷)。
?
表鎖:
手動增加表鎖:
lock table XXX read(write);
釋放表鎖:
unlock tables;
?
表級鎖性能監控:
show status like ‘table%’;
如果Table_locks_waited的值比較高,則說明存在著比較嚴重的表鎖爭用情況。
?
表級鎖的鎖模式:表共享讀鎖(Table Read Lock)和 表獨占寫鎖(Table Write Lock)
??? MyISAM在執行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執行更新操作(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖。
??? 所以對MyISAM表進行操作,會有以下情況:
???????? a、對MyISAM表的讀操作(加讀鎖),不會阻塞其他進程對同一表的讀請求,但會阻塞對同一表的寫請求。只有當讀鎖釋放后,才會執行其它進程的寫操作。
??????? b、對MyISAM表的寫操作(加寫鎖),會阻塞其他進程對同一表的讀和寫操作,只有當寫鎖釋放后,才會執行其它進程的讀寫操作。
??? 簡而言之,就是讀鎖會阻塞寫,但是不會堵塞讀。而寫鎖則會把讀和寫都堵塞。
?
關于表鎖并發插入
?
??? 原則上數據表有一個讀鎖時,其它進程無法對此表進行更新操作,但在一定條件下,MyISAM表也支持查詢和插入操作的并發進行。
??? MyISAM存儲引擎有一個系統變量
concurrent_insert
,專門用以控制其并發插入的行為,其值分別可以為0、1或2。
??????? a、當concurrent_insert設置為0時,不允許并發插入。
??????? b、
當concurrent_insert設置為1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄。這也是MySQL的默認設置。
??????? c、當concurrent_insert設置為2時,無論MyISAM表中有沒有空洞,都允許在表尾并發插入記錄。
?
表鎖地優化:
??? 使用表級鎖定在鎖定實現的過程中比實現行級鎖定或頁級鎖定所帶來的附加成本要小,鎖定本身所消耗的資源也是最少的。但是由于鎖定的顆粒度比較大,所以造成鎖定資源的爭用情況也會比其他的鎖定級別都要多,從而在較大程度上會降低并發處理能力。所以表鎖優化, 最關鍵的是如何讓其提高并發度 。由于鎖定級別是不可能改變的了,所以首先需要盡可能地鎖定的時間變短,然后就是讓可能并發進行的操作盡可能地并發。
1.縮短鎖定時間:
??? 1)盡量減少大的復雜的Query,將復雜的Query分拆成幾個小的Query分步進行;
??? 2)盡可能地建立足夠高效的索引,讓數據檢索更迅速;
??? 3)盡量讓MyISAM存儲引擎的表至存放必要的信息,控制字段類型;
??? 4)利用合理的機會優化MyISAM表數據文件。
??? 2、分離能并行的操作
2.合理利用上面提到的concurrent_insert
3.合理利用讀寫優先級:
??? MyISAM的表級鎖定對于讀和寫是有不同優先級設定的, 默認 情況下是寫優先級要大于讀 。所以,可以根據系統環境的差異決定讀與寫的優先級。如果系統是一個以讀為主,而且要優先保證查詢性能的話,可以通過設置系統參數選項low_priority_updates=1,將寫的優先級設置為比讀低,即告訴MyISAM盡量優先處理讀請求。當然,如果系統需要優先保證數據寫入的性能的話,則不用設置low_priority_updates參數了。
?
??? 以上筆記參考網絡資料以及《MySQL技術內幕:InnoDB存儲引擎》,如有謬誤請 指正 。
??? 下一次整理一下行鎖的筆記~
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
