1. 程式人生 > >【MySQL】——MySQL中的鎖機制

【MySQL】——MySQL中的鎖機制

概述

相對其他資料庫來說,MySQL的鎖機制比較簡單,不同的儲存引擎支援不同的鎖機制。 MySQL大致可以分為以下3種鎖

  • 表級鎖:操作物件是資料表。MySQL大多數鎖策略都支援,開銷小,加鎖快。不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發度最低。
  • 行級鎖:操作物件是資料表中的一行,開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生所衝突的概率最低,併發度也最高。
  • 頁面鎖:開銷和加鎖時間界定於表鎖和行鎖之間;會出現死鎖;鎖定粒度介於表鎖和行鎖之間,併發度一般。

MyISAM表鎖

MySQL的表鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)。

表鎖相容模式
當前鎖模式/是否相容 None 讀鎖 寫鎖
讀鎖
寫鎖
  • 對MyISAM的讀操作,不會阻塞其他使用者對同一表的讀請求,但是阻塞對同一表的寫操作。

  • 對MyISAM的寫操作,則會阻塞其他使用者對同一表的讀寫操作。

  • MyISAM表的讀操作和寫操作,以及寫操作之間都是序列的。

    併發插入

    MyISAM儲存引擎有一個系統變數concurrent_insert,專門用以控制其併發插入的行為,其值分別可以為0、1或2。

  • 當concurrent_insert設定為0時,不允許併發插入。

  • 當concurrent_insert設定為1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個程序讀表的同時,另一個程序從表尾插入記錄。這也是MySQL的預設設定。

  • 當concurrent_insert設定為2時,無論MyISAM表中有沒有空洞,都允許在表尾併發插入記錄。

只需在加表鎖命令中加入“local”選項,即:lock table tbl_name local read,在滿足MyISAM表併發插入條件的情況下,其他使用者就可以在表尾併發插入記錄,但更新操作會被阻塞,而且加鎖的使用者無法訪問到其他使用者併發插入的記錄。

MyISAM鎖排程

當寫程序和讀程序同時請求同一個MyISAM表的寫鎖和讀鎖時,寫程序會優先獲得鎖。不僅如此,即使讀請求先到鎖等待佇列,寫請求後到,寫鎖也會插到讀鎖請求之前!這是因為MySQL認為寫請求一般比讀請求更重要。這也正是MyISAM表不太適合於有大量更新操作和查詢操作應用的原因,因為大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠阻塞。 通過一下一些設定調節MyISAM的排程行為:

  • 通過指定啟動引數low-priority-updates,使MyISAM引擎預設給予讀請求以優先的權利。

  • 通過執行命令SET LOW_PRIORITY_UPDATES=1,使該連線發出的更新請求優先順序降低。

  • 通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優先順序。

InnoDB鎖問題

InnoDB與MyISAM的最大不同有兩點:1、支援事務(TRANSACTION)2、採用了行級鎖

事務(Transaction)及其ACID屬性

事務是有一組SQL語句組成的邏輯處理單元,事務由4個屬性通常我們也成為ACID屬性。

  • 原子性(Atomicity):事務是一個原子操作,其對資料的修改,要麼全部執行,要麼全部不執行。

  • 一致性(Consistency):事務的一致性指的是在一個事務執行之前和執行之後資料庫都必須處於一致性狀態。如果事務成功地完成,那麼系統中所有變化將正確地應用,系統處於有效狀態。如果在事務中出現錯誤,那麼系統中的所有變化將自動地回滾,系統返回到原始狀態。

  • 隔離性(Isolation):隔離性指併發的事務是相互隔離的。即一個事務內部的操作及正在操作的資料必須封鎖起來,不被其他企圖進行修改的事務看到。

  • 永續性(Durability):是指一個事務一旦被提交,它對資料庫中的資料的改變時永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。即一旦一個事務提交。DBMS(Database Management System)保證它對資料庫中資料的改變應該是永久性的,永續性通過資料庫備份和恢復來保證。

併發事務帶來的問題

相對於序列處理來說,併發事務處理能大大增加資料庫資源的利用率,提高資料庫系統的事務吞吐量,從而可以支援可以支援更多的使用者。但併發事務處理也會帶來一些問題,主要包括以下幾種情況。

  • 更新丟失(Lost Update):當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生丟失更新問題——最後的更新覆蓋了其他事務所做的更新。例如,兩個編輯人員製作了同一文件的電子副本。每個編輯人員獨立地更改其副本,然後儲存更改後的副本,這樣就覆蓋了原始文件。最後儲存其更改儲存其更改副本的編輯人員覆蓋另一個編輯人員所做的修改。如果在一個編輯人員完成並提交事務之前,另一個編輯人員不能訪問同一檔案,則可避免此問題

  • 髒讀(Dirty Reads):一個事務正在對一條記錄做修改,在這個事務並提交前,這條記錄的資料就處於不一致狀態;這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“髒”的資料,並據此做進一步的處理,就會產生未提交的資料依賴關係。這種現象被形象地叫做“髒讀”。

  • 不可重複讀(Non-Repeatable Reads):一個事務在讀取某些資料已經發生了改變、或某些記錄已經被刪除了!這種現象叫做“不可重複讀”。

  • 幻讀(Phantom Reads):一個事務按相同的查詢條件重新讀取以前檢索過的資料,卻發現其他事務插入了滿足其查詢條件的新資料,這種現象就稱為“幻讀”。

事務的隔離級別

詳見上篇部落格

InnoDB的行鎖模式及加鎖方式

InnoDB實現了以下兩種型別的行鎖

  • 讀鎖:也加共享鎖、S鎖。若事務T對資料物件A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S 鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。

  • 寫鎖:又稱排他鎖、X鎖。若事務T對資料物件A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。