mysql中innodb引擎的行鎖

2021-09-06 19:57:22 字數 3176 閱讀 4420

一、資料庫引擎

mysql常用的資料庫引擎也就是myisam和innodb兩種,相比較起myisam而言innodb支援了事務、外來鍵等功能,具有更好的併發性支援,所以在大併發的情況的下我們一般選擇的是innodb來作為我們的資料庫儲存引擎,而myisam相較innodb的執行效能上會有更好的表現,(畢竟myisam是mysql自帶的引擎,而innodb是由別人寫的)。mysql鎖級別包括三種:表鎖(對整個表加鎖)、頁鎖(介於表鎖和行鎖之間)、行鎖(對具體行加鎖),對於myisam預設採用的是表鎖,而對於innodb預設採用的是行鎖,

innodb的行鎖是通過共享鎖和排他鎖實現的,具體參考mysql鎖機制之共享鎖和排它鎖,

共享鎖:select * from table_name where .....lock in share mode

排他鎖:select * from table_name where .....for update

由於mysql事務預設是自動提交的,如果要測試鎖機制,記得把事務自動提交關閉

set autocommit=0

二、資料庫事務

事務具有acid的特性,也就是原子性、永續性、隔離性和一致性,mysql中innodb支援事務,而myisam不支援,採用事務對於業務邏輯和併發都有很大的幫助,但是採用事務也會導致相應的問題,

1、丟失更新:兩個事務同時對同一行進行修改,會有乙個事務的更新被覆蓋。(寫寫)

2、髒讀:乙個事務對一行記錄進行讀取,另乙個事務同時對這行記錄進行修改,如果寫事務中途失敗回滾,而讀事務卻讀取到寫事務修改的值,這樣就造成了髒讀。(讀寫)

3、不可重複讀:乙個事務對一行記錄進行兩次讀取,另乙個事務同時對這一行進行修改,這個會導致第一次讀取的記錄和第二次讀取的記錄不一致,出現了不可重複讀。(讀寫讀)

4、幻讀:乙個事務對錶進行兩次讀取,另乙個事務同時進行插入操作,這回導致第二次讀取出現 了第一次沒有出現的記錄,也就是幻讀。

解決辦法也就是設定事務的隔離級別:讀未提交(read-uncommitted)、讀提交(read-committed)、可重複讀(read-reapted)、序列化(serializable)。

事務的隔離級別越高,那麼出現事務也就越安全,但是加鎖機制也就越複雜,效能消耗越大。

mysql預設採用的是可重複讀的級別

select @@tx_isolation 可以檢視

三、innodb的行鎖

innodb預設採用的是行鎖,但是採用行鎖必須要查詢條件為索引列,如果查詢條件不是為索引列,那麼mysql會採用表鎖機制。接下來就來做一下驗證。

1、建乙個簡單的表:

create table test(

a int null,

b  int  null,

index  a_index  (a)  using btree

)engine=innodb;

這個表有兩列a和b,都是int型別,其中a是建了索引,

插入四行:

insert into test(a,b) values(1,2);

insert into test(a,b) values(3,4);

insert into test(a,b) values(3,6);

insert into test(a,b) values(8,2);

2、 開啟兩個session:

session1

sessio2

set autocommit=0

set autocommit=0

select * from test where b=4  for update;

正確查詢出結果

select * from test where b =6 for update;

查詢被鎖死,處於等待狀態

commit

表鎖被釋放,查詢出結果,commit

select * from test where a =1 for update;

正確查詢出結果

select * from test where a=8 for update;

正確查詢出結果,a是索引列,where條件使用索引列,預設採用行鎖機制。

commit

commit       

...... for update  是加排它鎖。接下來驗證事務是否採用行鎖。

session1

session2

set autocommit=0

set autocommit=0

start transaction

start transaction

update test set a=10 where b=4  for update;

正確更新

update test set a=20 where b=6  for update;

更新等待,出現表鎖,

commit

鎖被釋放,正確更新,commit

update test set b=10 where a=10  for update;

正確更新

update test set b=20 where a=20  for update;

正確更新,a是索引列,where條件使用索引列,預設採用行鎖機制,不同行不會被鎖死

commit

commit

innodb的行鎖在查詢條件為索引列的情況下才採用,所以查詢條件盡量採用索引列。

間隙鎖innodb中面對between...and....這種區間查詢的時候採用的是間隙鎖機制,

update test set a=.... where b between x and y    那麼從[x,y]這個區間都會加上行鎖。

四、總結

1、在開發過程中盡量降低事務的粗粒度,避免過多的查詢和更新和插入操作堆在一起,從而造成長時間的鎖等待。

影響程式執行效率。

2、查詢條件盡量採用索引列,從而使mysql採用行鎖,而不是表鎖。

3、使用區間查詢的時候注意區間範圍,避免鎖住其他不必要鎖住的行。

4、合理的採用事務的隔離級別,事務隔離級別越高,效能越低,鎖機制越複雜,發生的死鎖的概率越大,

有時候降低事務的隔離級別也是解決死鎖的有效方式。

MySql中InnoDB引擎索引

mysql中innodb引擎的索引分兩類,一類是一級索引 主鍵的同義詞 一類是二級索引 非主鍵的索引 兩類索引都使用b tree形式組織,但一級索引的葉子節點包含所以對應的整行資訊,所有的查詢最終都是通過一級索引完成,二級索引只包含二級索引對應的一級索引。所以直接使用一級索引比用二級索引快,因為少了...

Mysql中InnoDB引擎的鎖

鎖這種機制的作用 對共享資源併發訪問的管理,保證資料的完整性和一致性。在資料庫中,lock與latch都可以被稱為 鎖 但是兩者的含義是完全不同的。lock針對的物件是事務,它用來鎖定資料庫中的物件,如表 頁 行。一般lock的物件僅在事務commit或者rollback後進行釋放,並且lock是有...

MySql中啟用InnoDB資料引擎

1.mysql支援的資料引擎列表如下 2.其中預設的是myisam資料引擎,可惜此引擎不支援事務處理,我們需要將預設的資料引擎改為innodb。3.innodb和berkeleydb支援事務處理,可惜預設的情況下都是被disable的。所有的引擎裡面,innodb效能最強大,算是商業級的。4.啟動i...