MySql中存儲引擎myisam和innodb的區別

北風濁酒 發佈 2024-05-10T11:17:20.936223+00:00

1.概述相對其他資料庫而言,MySQL的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。

1.概述

相對其他資料庫而言,MySQL的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。比如,MyISAM和MEMORY存儲引擎採用的是表級鎖(table-level locking);InnoDB存儲引擎既支持行級鎖( row-level locking),也支持表級鎖,但默認情況下是採用行級鎖。

MySQL主要的兩種鎖的特性可大致歸納如下:

表級鎖: 開銷小,加鎖快;不會出現死鎖(因為MyISAM會一次性獲得SQL所需的全部鎖);鎖定粒度大,發生鎖衝突的概率最高,並發度最低。

行級鎖: 開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,並發度也最高。

考慮上述特點,表級鎖使用與並發性不高,以查詢為主,少量更新的應用,比如小型的web應用;而行級鎖適用於高並發環境下,對事務完整性要求較高的系統,如在線事務處理系統。

2.MyISAM鎖細述

(1). 鎖模式

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

(2). 如何加鎖

  當MyISAM在執行查詢語句時,會自動給涉及到表加讀鎖,在執行更新操作時,會加寫鎖。當然用戶也可以用LOCK TABLE 去顯式的加鎖。顯式的加鎖一般是應用於:需要在一個時間點實現多個表的一致性讀取,不然的話,可能讀第一個表時,其他表由於還沒進行讀操作,沒有自動加鎖,可能數據會發生改變。並且顯示加鎖後只能訪問加鎖的表,不能訪問其他表。

(3). 並發插入

  MyISAM存儲引擎有個系統變量 concurrent_insert,專門用來控制並發插入的行為,可以取 0 , 1 , 2。

  0表示不允許並發插入,1表示表中間沒有刪除的行時可以在表末尾插入,2表示總是可以插入。

  一般如果對並發要求比較高的情況下,可以設置為2,總是可以插入,然後定期在資料庫空閒時間對表進行optimize。

(4). 鎖的調度

  需要注意的是,其中讀操作不會阻塞其他用戶對同一表的讀請求,但會阻塞對同一表的寫請求;並且當寫鎖和讀鎖同時被申請時,優先獲得寫鎖,這也這正是表級鎖發生鎖衝突概率最高的原因,因為寫鎖可能會一直阻塞讀鎖,所以不適合有大量寫操作的環境下工作。這一問題可以通過設置low-priority-updates這一啟動參數來降低寫的優先級。

  雖然寫鎖優先於讀鎖獲取,但是長時間的查詢操作也可能會讓寫操作餓死,所以儘量避免一條SQL語句執行所有的查詢,應該進行必要的分解。


3.InnoDB鎖細述

  由於InnoDB支持事務,並默認是使用行級鎖,所以InnoDB的鎖問題和MyISAM鎖問題還是有蠻大差別的。

(1). 鎖模式

  共享鎖(S)和排他鎖(X),分別類似於MyISAM的讀鎖和寫鎖。對於 UPDATE、 DELETE 和 INSERT 語句,InnoDB會自動給涉及數據集加排他鎖(X);對於普通 SELECT 語句,InnoDB不會加任何鎖。

(2). 如何加鎖

  可以顯式的加鎖,用lock in share mode 顯式的加共享鎖,用 for update 顯式的加排他鎖。

  需要注意的是,如果線程A加了共享鎖後,線程B對同一個表加了共享鎖,那麼兩個線程需要進行更新操作時會產生死鎖。所以,進行更新操作時最好加排他鎖。

(3). InnoDB行鎖的實現方式——索引加鎖

  這一點與Oracle不同,所以這也意味著(重要):1. 只有通過索引條件檢索數據時,InnoDB才會使用行級鎖,否則會使用表級鎖。 2. 即使是訪問不同行的記錄,如果使用的是相同的索引鍵,會發生鎖衝突。 3. 如果數據表建有多個索引時,可以通過不同的索引鎖定不同的行。

(4). 間隙鎖

  InnoDB支持事務,為了滿足隔離級別的要求,InnoDB有個間隙鎖,當使用範圍查找時,InnoDB會給滿足key範圍要求,但實際並不存在的記錄加鎖。例如:select * from user where id > 100 for updata 會給ID>100的記錄加排他鎖,滿足這個範圍,但不存在的記錄,會加間隙鎖,這樣可以避免幻讀,避免讀取的時候插入滿足條件的記錄。

(5). 隔離級別與鎖

  一般來說,隔離級別越高,加鎖就越嚴格。這樣,產生鎖衝突的概率就越大,一般實際應用中,通過優化應用邏輯,選用 可提交讀 級別就夠了。對於一些確實需要更高隔離級別的事務,再通過set session transaction isolation level+"級別" 來動態改變滿足需求。


4.死鎖

  MyISAM是沒有死鎖問題的,因為他會一次性獲得所有的鎖。

  InnoDB發生死鎖後一般能自動檢測到,並使一個事務釋放鎖並回退,另一個事務獲得鎖,繼續完成事務。

  在應用中,可以通過如下方式來儘可能的避免死鎖:

    (1) 如果不同的程序會並發的存取多個表,應儘量約定以相同的順序來訪問表,這樣可以大大降低產生死鎖的機會。

    (2) 在程序以批量方式處理數據時,如果事先對數據排序,保證每個線程按固定的順序來處理記錄,也可以大大的降低出現死鎖的可能。

關鍵字: