mysql中Innodb 行鎖實現(xiàn)原理
一、Innodb行鎖的實現(xiàn)
【1】Innodb的行鎖是通過給索引的索引項加鎖來實現(xiàn)的
【2】Innodb
按照輔助索引進行數(shù)據(jù)操作時,輔助索引和主鍵索引都將鎖定指定的索引項
【3】通過索引進行數(shù)據(jù)檢索時,Innodb
才使用行級鎖,否則Innodb
將使用表鎖
二、場景分析
環(huán)境: 創(chuàng)建一張表,ID為主鍵,Name為普通字段。下面通過實際場景進行說明。
【1】使用主鍵ID來進行數(shù)據(jù)檢索時,其余行仍然可以操作。
session1 | session2 |
---|---|
mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) | mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) |
mysql> select * from test_lock wehre id = 1 for update; ±-----±-----+ | id | name | | 1 | hua zi | 1 row in set(0.00sec) | |
mysql> select * from test_lock wehre id = 2 for update; ±-----±-----+ | id | name | | 2 | guo zi | 1 row in set(0.00sec) | |
【2】用非索引的字段來進行數(shù)據(jù)檢索時,此時會升級為表鎖,其余列就不能操作。 | |
session1 | session2 |
---- | ---- |
mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) | mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) |
mysql> select * from test_lock wehre name = ‘hua zi’ for update; ±-----±-----+ | id | name | | 1 | hua zi | 1 row in set(0.00sec) | |
mysql> select * from test_lock wehre name = ‘guo zi’ for update; 等待 | |
【3】由于MySQL 的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現(xiàn)鎖沖突的。應(yīng)用設(shè)計的時候要注意這一點。雖然 session_2和session_1訪問的是不同的記錄,但因為使用了相同的索引,所以需要等待鎖。 | |
session1 | session2 |
---- | ---- |
mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) | mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) |
mysql> select * from test_lock wehre id = 1 and name = ‘hua zi’ for update; ±-----±-----+ | id | name | | 1 | hua zi | 1 row in set(0.00sec) | |
mysql> select * from test_lock wehre id = 1 and name = ‘guo zi’ for update; 等待 | |
【4】當表有多個索引的時候,不同的事務(wù)可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB 都會使用行鎖來對數(shù)據(jù)加鎖。 | |
session1 | session2 |
---- | ---- |
mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) | mysql>set autocommit=0; Query OK,0 rows affected(0.00sec) |
mysql> select * from test_lock wehre id = 1 for update; ±-----±-----+ | id | name | | 1 | hua zi | 1 row in set(0.00sec) | |
mysql> select * from test_lock wehre name = ‘guo zi’ for update; ±-----±-----+ | id | name | | 2 | guo zi | 1 row in set(0.00sec) | |
mysql> select * from test_lock wehre name = ‘hua zi’ for update; 等待 |
三、特殊場景
即便在條件中使用了索引字段,但是否使用索引來檢索數(shù)據(jù)是由MySQL
通過判斷不同執(zhí)行計劃的代價來決定的,如果MySQL
認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB
將使用表鎖,而不是行鎖。因此,在分析鎖沖突時,別忘了檢查SQL
的執(zhí)行計劃,以確認是否真正使用了索引。
在下面的例子中,檢索值的數(shù)據(jù)類型與索引字段不同,雖然MySQL
能夠進行數(shù)據(jù)類型轉(zhuǎn)換,但卻不會使用索引,從而導(dǎo)致InnoDB
使用表鎖。通過用explain
檢查兩條SQL
的執(zhí)行計劃,我們可以清楚地看到了這一點。
mysql> alter table test_lock add index name(name); Query OK, 4 rows affected (8.06 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> explain select * from test_lock where name = 1 \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test_lock type: ALL possible_keys: name key: NULL key_len: NULL ref: NULL rows: 4 Extra: Using where 1 row in set (0.00 sec) mysql> explain select * from test_lock where name = '1' \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test_lock type: ref possible_keys: name key: name key_len: 23 ref: const rows: 1 Extra: Using where 1 row in set (0.00 sec)
到此這篇關(guān)于mysql中Innodb 行鎖實現(xiàn)原理的文章就介紹到這了,更多相關(guān)mysql Innodb 行鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL數(shù)據(jù)表損壞的正確修復(fù)方案
修復(fù)以損壞的MySQL數(shù)據(jù)表的實際操作在實際中是我們經(jīng)常用到的,以下的文章主要是介紹正確修復(fù)以損壞的MySQL數(shù)據(jù)表的實際操作步驟,以下就是正文的介紹,希望會給你帶來一些幫助在此方面。2011-01-01LEFT JOIN關(guān)聯(lián)表中ON,WHERE后面跟條件的區(qū)別
本文主要介紹了LEFT JOIN關(guān)聯(lián)表中ON,WHERE后面跟條件的區(qū)別,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01mysql運行net start mysql報服務(wù)名無效的解決辦法
這篇文章主要為大家詳細介紹了mysql運行net start mysql報服務(wù)名無效的解決辦法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01