紙上得來終覺淺,絕知此事要躬行。mysql
開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。sql
InnoDB 實現瞭如下兩種類型的行鎖。併發
能夠經過如下語句顯示給記錄集加共享鎖或排他鎖 。性能
共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE 排他鎖(X) :SELECT * FROM table_name WHERE ... FOR UPDATE
對於UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X);
對於普通SELECT語句,InnoDB不會加任何鎖;測試
在測試前仍然準備相關測試表和數據,注意表的存儲引擎爲InnoDB:優化
create table test_innodb_lock( id int(11), name varchar(16), sex varchar(1) )engine = innodb default charset=utf8; insert into test_innodb_lock values(11,'100','1'); insert into test_innodb_lock values(3,'3','1'); insert into test_innodb_lock values(4,'400','0'); insert into test_innodb_lock values(5,'500','1'); insert into test_innodb_lock values(6,'600','0'); insert into test_innodb_lock values(7,'700','0'); insert into test_innodb_lock values(8,'800','1'); insert into test_innodb_lock values(9,'900','1'); insert into test_innodb_lock values(1,'200','0'); create index idx_test_innodb_lock_id on test_innodb_lock(id); create index idx_test_innodb_lock_name on test_innodb_lock(name);
建立完成,咱們看一下表結構和表數據,方便後面操做查看:設計
mysql> desc test_innodb_lock; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | MUL | NULL | | | name | varchar(16) | YES | MUL | NULL | | | sex | varchar(1) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> select * from test_innodb_lock; +------+------+------+ | id | name | sex | +------+------+------+ | 11 | 100 | 1 | | 3 | 3 | 1 | | 4 | 400 | 0 | | 5 | 500 | 1 | | 6 | 600 | 0 | | 7 | 700 | 0 | | 8 | 800 | 1 | | 9 | 900 | 1 | | 1 | 200 | 0 | +------+------+------+ 9 rows in set (0.00 sec)
Session-1 | Session-2 |
---|---|
以上, 操做的都是同一行的數據,接下來,演示不一樣行的數據 | |
若是不經過索引條件檢索數據,那麼InnoDB將對錶中的全部記錄加鎖,實際效果跟表鎖同樣。3d
查看當前表的索引 :code
show index from test_innodb_lock ;
接下來咱們看一個例子,當索引失效的時候,行鎖升級爲表鎖的過程:blog
以上兩個客戶端對一行數據進行修改時,因爲執行更新時,name
字段原本爲varchar
類型, 咱們是做爲int
類型使用,存在類型轉換,索引失效,最終行鎖變爲表鎖,致使Session-2更新數據處於等待狀態。
當咱們用範圍條件,而不是使用相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據進行加鎖; 對於鍵值在條件範圍內但並不存在的記錄,叫作 "間隙(GAP)" , InnoDB也會對這個 "間隙" 加鎖,這種鎖機制就是所謂的間隙鎖(Next-Key鎖) 。
下面是一個間隙鎖的案例:
Session-1 | Session-2 |
---|---|
因爲Session-1的插入操做是一個範圍,咱們表中存在id
不連續的狀況,致使在更新時不只會加排它鎖,還會在當前訪問增長間隙鎖,致使Session-2在插入元素時處於等待狀態。
查看行鎖競爭狀況:
show status like 'innodb_row_lock%';
InnoDB存儲引擎因爲實現了行級鎖定,雖然在鎖定機制的實現方面帶來了性能損耗可能比表鎖會更高一些,可是在總體併發處理能力較高。可是,InnoDB的行級鎖也是一把雙刃劍,當咱們使用不當的時候,可能會讓InnoDB的總體性能降低。
優化建議: