MySQL鎖機制

鎖是計算機協調多個進程或線程併發訪問某一資源的機制,不同的數據庫的鎖機制大同小異。由於數據庫資源是一種供許多用戶共享的資源,所以如何保證數據併發訪問的一致性、有效性是所有數據庫必須解決的一個問題,鎖衝突也是影響數據庫併發訪問性能的一個重要因素。瞭解鎖機制不僅可以使我們更有效的開發利用數據庫資源,也使我們能夠更好地維護數據庫,從而提高數據庫的性能。
     MySQL的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。
例如,MyISAM和MEMORY存儲引擎採用的是表級鎖(table-level-locking);BDB存儲引擎採用的是頁面鎖(page- level-locking),同時也支持表級鎖;InnoDB存儲引擎既支持行級鎖,也支持表級鎖,默認情況下是採用行級鎖。
     上述三種鎖的特性可大致歸納如下:
1) 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。
2) 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
3) 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。
     三種鎖各有各的特點,若僅從鎖的角度來說,表級鎖更適合於以查詢爲主,只有少量按索引條件更新數據的應用,如WEB應用;行級鎖更適合於有大量按索引條件併發更新少量不同數據,同時又有併發查詢的應用,如一些在線事務處理(OLTP)系統。
     MySQL表級鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)。什麼意思呢,就是說對MyISAM表進行讀操作時,它不會阻塞其他用戶對同一表的讀請求,但會阻塞 對同一表的寫操作;而對MyISAM表的寫操作,則會阻塞其他用戶對同一表的讀和寫操作。
     MyISAM表的讀和寫是串行的,即在進行讀操作時不能進行寫操作,反之也是一樣。但在一定條件下MyISAM表也支持查詢和插入的操作的併發進行,其機制是通過控制一個系統變量(concurrent_insert)來進行的,當其值設置爲0時,不允許併發插入;當其值設置爲1 時,如果MyISAM表中沒有空洞(即表中沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄;當其值設置爲2時,無論 MyISAM表中有沒有空洞,都允許在表尾併發插入記錄。
     MyISAM鎖調度是如何實現的呢,這也是一個很關鍵的問題。例如,當一個進程請求某個MyISAM表的讀鎖,同時另一個進程也請求同一表的寫鎖,此時MySQL將會如優先處理進程呢?通過研究表明,寫進程將先獲得鎖(即使讀請求先到鎖等待隊列)。但這也造成一個很大的缺陷,即大量的寫操作會造成查詢操作很難獲得讀鎖,從而可能造成永遠阻塞。所幸我們可以通過一些設置來調節MyISAM的調度行爲。我們可通過指定參數low-priority- updates,使MyISAM默認引擎給予讀請求以優先的權利,設置其值爲1(set low_priority_updates=1),使優先級降低。
     InnoDB鎖與MyISAM鎖的最大不同在於:一是支持事務(TRANCSACTION),二是採用了行級鎖。我們知道事務是由一組SQL語句組成的邏輯處理單元,其有四個屬性(簡稱ACID屬性),分別爲:
原子性(Atomicity):事務是一個原子操作單元,其對數據的修改,要麼全部執行,要麼全都不執行;
一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態;
隔離性(Isolation):數據庫系統提供一定的隔離機制,保證事務在不受外部併發操作影響的“獨立”環境執行;
持久性(Durable):事務完成之後,它對於數據的修改是永久性的,即使出現系統故障也能夠保持。
InnoDB有兩種模式的行鎖:
1)共享鎖:允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。
    ( Select * from table_name where ......lock in share mode)
2)排他鎖:允許獲得排他鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和  排他寫鎖。(select * from table_name where.....for update)
     爲了允許行鎖和表鎖共存,實現多粒度鎖機制;同時還有兩種內部使用的意向鎖(都是表鎖),分別爲意向共享鎖和意向排他鎖。
    InnoDB行鎖是通過給索引項加鎖來實現的,即只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則將使用表鎖!

 

另外:插入,更新性能優化的幾個重要參數

bulk_insert_buffer_size

批量插入緩存大小, 這個參數是針對MyISAM存儲引擎來說的.適用於在一次性插入100-1000+條記錄時, 提高效率.默認值是8M.可以針對數據量的大小,翻倍增加.

concurrent_insert

併發插入, 當表沒有空洞(刪除過記錄), 在某進程獲取讀鎖的情況下,其他進程可以在表尾部進行插入.
值可以設0不允許併發插入,1當表沒有空洞時,執行併發插入,2.不管是否有空洞都執行併發插入.
默認是1.針對表的刪除頻率來設置.

delay_key_write

針對MyISAM存儲引擎,延遲更新索引.意思是說,update記錄時,先將數據up到磁盤,但不up索引,將索引存在內存裏,當表關閉時,將內存索引,寫到磁盤. 值爲 0不開啓, 1開啓. 默認開啓.

delayed_insert_limit, delayed_insert_timeout, delayed_queue_size
延遲插入, 將數據先交給內存隊列, 然後慢慢地插入.但是這些配置,不是所有的存儲引擎都支持, 目前來看, 常用的InnoDB不支持, MyISAM支持. 根據實際情況調大, 一般默認夠用了

 

補充:對於對同一條數據庫記錄進行update+和update-1的操作,對服務器端來說沒有同時的操作,所有的操作都是有先後之分,先來的任務會獲得排他鎖,在釋放該排他鎖以前,其他的用戶無法對該條記錄進行更新或刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章