記錄一下MySql update會鎖定哪些范圍的數(shù)據(jù)

1毯欣、背景

在項目中来累,我們經(jīng)常使用到update語句领猾,那么update語句會鎖定表中的那些記錄呢少孝?此處我們通過一些簡單的案例來模擬下钱磅。此處是我自己的一個理解褪迟,如果那個地方理解錯了心俗,歡迎指出

2狠持、前置知識

2.1 數(shù)據(jù)庫的隔離級別

mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

2.2 數(shù)據(jù)庫版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.28    |
+-----------+
1 row in set (0.00 sec)

2.3 數(shù)據(jù)庫的存儲引擎

mysql> show variables like '%storage_engine%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| default_storage_engine          | InnoDB    |
| default_tmp_storage_engine      | InnoDB    |
| disabled_storage_engines        |           |
| internal_tmp_mem_storage_engine | TempTable |
+---------------------------------+-----------+
4 rows in set (0.01 sec)

2.4 鎖是加在記錄上還是索引上

鎖是加在索引上,那如果表中沒有建立索引,是否就是加在表上的呢?其實(shí)不是,也是加在索引的,會存在一個默認(rèn)的。

Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking

參考鏈接: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-intention-locks

2.5 update...where加鎖的基本單位是

UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters
此處可以理解加鎖的單位是: next-key

2.6 行級鎖

2.6.1 Record Locks

記錄鎖超歌,即只會鎖定一條記錄禀综。其實(shí)是鎖定這條記錄的索引覆旭。
A record lock is a lock on an index record. For example, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; prevents any other transaction from inserting, updating, or deleting rows where the value of t.c1 is 10.

2.6.2 Gap Locks

間隙鎖福扬,間隙鎖是在索引記錄之間的間隙上的鎖汽烦,即鎖定一個區(qū)間。前開后開區(qū)間死姚,不包括記錄本身戳护。

間隙鎖如果是使用單列唯一索引值進(jìn)行更新的話,是會退化Record Lock顷级。

間隙鎖的目的

  1. 防止新的數(shù)據(jù)插入到間隙中
  2. 防止已經(jīng)存在的數(shù)據(jù)被更新到間隙中。

Gap locking is not needed for statements that lock rows using a unique index to search > for a unique row. (This does not include the case that the search condition includes only > some columns of a multiple-column unique index; in that case, gap locking does occur.)

2.6.3 Next-Key Locks

Next-Key Lock 是索引記錄上記錄鎖索引記錄之前間隙上的間隙鎖的組合。也是鎖定一個區(qū)間,前開后閉區(qū)間潮瓶。包括記錄本身。

如果索引值包括 1,5,10,30描焰,那么next key 鎖可能涵蓋如下區(qū)間

(negative infinity, 1]
(1, 115
(5, 10]
(10, 30]
(30, positive infinity)

negative infinity指的是負(fù)無窮。positive infinity指的是正無窮靡努。

2.6.4 測試鎖表的表結(jié)構(gòu)

create table test_record_lock
(
    id   int         not null comment '主鍵',
    age  int         null comment '年齡,普通索引',
    name varchar(10) null comment '姓名隧期,無索引',
    constraint test_record_lock_pk
        primary key (id)
)
    comment '測試記錄鎖';

create index test_record_lock_age_index
    on test_record_lock (age);

2.6.5 表中的測試數(shù)據(jù)

mysql> select * from test_record_lock;
+----+------+--------+
| id | age  | name   |
+----+------+--------+
|  1 |   10 | 張三   |
|  5 |   20 | 李四   |
|  8 |   25 | 王五   |
+----+------+--------+
3 rows in set (0.00 sec)

2.7 查看數(shù)據(jù)庫中當(dāng)前的鎖

select * from performance_schema.data_locks;

字段解釋:

字段 解釋
lock_type TABLE 鎖是加在表上
RECORD 鎖加在記錄上
lock_mode IX 意向排他鎖
X或者S next-key lock
鎖定記錄本身和記錄之前的間隙
X,REC_NOT_GAP Record Lock 只鎖記錄自身
S,REC_NOT_GAP Record Lock 只鎖記錄自身
X,GAP gap lock
X,INSERT_INTENTION 插入意向鎖
lock_data 具體的某個數(shù)字 表示主鍵的值
值,值 第一個值:普通索引的值
第二個值:主鍵值

疑問:X,GAP是否可以理解成X鎖退化成了GAP鎖。

3个榕、測試數(shù)據(jù)加鎖

3.1 唯一索引測試

此處適用單個字段的唯一索引篡石,不適合多個字段的唯一索引

3.1.1 等值更新-記錄存在

01-唯一索引-等值更新-值存在.jpg

解釋:

  1. 加next-key lock,那么鎖定的記錄范圍為 (1,5]西采。
  2. 因為是唯一索引凰萨,且查詢的值存在,next-key lock退化成record lock,即最終只鎖定了id=5的這一行數(shù)據(jù)胖眷。其余的數(shù)據(jù)不影響武通。

3.1.2 等值查詢-記錄不存在-01

02-唯一索引-等值更新-值不存在01.jpg

解釋:

  1. 加next-key lock,那么鎖定的記錄范圍為 (5,8]珊搀。
  2. 因為是唯一索引冶忱,且查詢的值不存在,next-key lock退化成gap境析,即最終鎖定的數(shù)據(jù)范圍為(5,8)囚枪。其余的數(shù)據(jù)不影響。

3.1.3 等值更新-記錄不存在-02

03-唯一索引-等值更新-值不存在02.jpg

3.1.4 范圍更新

1劳淆、小于或等于最大臨界值
04-唯一索引-范圍更新-<=邊界值.jpg

此時可以發(fā)現(xiàn)表中掃描到的記錄都加上了next key lock(鎖加在索引上)

2链沼、大于或等于最小臨界值
mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> update test_record_lock set name = 'aaa' where id >= 1;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select LOCK_TYPE,INDEX_NAME,LOCK_MODE,LOCK_DATA from performance_schema.data_locks;
+-----------+------------+---------------+------------------------+
| LOCK_TYPE | INDEX_NAME | LOCK_MODE     | LOCK_DATA              |
+-----------+------------+---------------+------------------------+
| TABLE     | NULL       | IX            | NULL                   |
| RECORD    | PRIMARY    | X,REC_NOT_GAP | 1                      |
| RECORD    | PRIMARY    | X             | supremum pseudo-record |
| RECORD    | PRIMARY    | X             | 8                      |
| RECORD    | PRIMARY    | X             | 5                      |
+-----------+------------+---------------+------------------------+
5 rows in set (0.01 sec)

此時只可向表中插入比最小臨界值小的記錄。

3沛鸵、正常范圍
05-唯一索引-范圍更新-03.jpg

3.2 普通索引測試

3.2.1 等值更新-記錄存在
06-普通索引-等值存在修改.jpg

解釋:

  1. 先對普通索引age加上next-key lock括勺,鎖定的范圍是(10,20]
  2. next-key lock還會鎖住本記錄,因此在id索引的值等于5上加了Record Lock
  3. 因為是普通索引并且值還存在谒臼,因此還會對本記錄的下一個區(qū)間增加間隙鎖 Gap Lock朝刊,鎖定的范圍為 (20,25)
3.2.2 等值更新-記錄不存在
07-普通索引-更新值值不存在.jpg

解釋:

  1. 獲取next-key lock 鎖定的范圍為 (10,20]
  2. 因為需要更新的記錄不存在,next-key lock退化成 gap lock蜈缤,所以鎖定的范圍為(10,20)
  3. 因為是普通索引且記錄不存在拾氓,所以不需要再次查找下一個區(qū)間。
3.2.3 范圍更新
08-普通索引-范圍更新.jpg

解釋:

  1. 普通索引的范圍更新底哥,next-key-lock不回退化成 gap lock咙鞍。

3.3 無索引更新

09-無索引更新.jpg

從上圖中可知,無索引更新數(shù)據(jù)表危險趾徽,需要謹(jǐn)慎處理续滋。無索引更新,會導(dǎo)致全表掃描孵奶,導(dǎo)致將掃描到的所有記錄都加上next-key lock疲酌。

3、參考鏈接

1了袁、https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-intention-locks
2朗恳、https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市载绿,隨后出現(xiàn)的幾起案子粥诫,更是在濱河造成了極大的恐慌,老刑警劉巖崭庸,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀浆,死亡現(xiàn)場離奇詭異谊囚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)执赡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門镰踏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搀玖,你說我怎么就攤上這事余境。” “怎么了灌诅?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長含末。 經(jīng)常有香客問我猜拾,道長,這世上最難降的妖魔是什么佣盒? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任挎袜,我火速辦了婚禮,結(jié)果婚禮上肥惭,老公的妹妹穿的比我還像新娘盯仪。我一直安慰自己,他們只是感情好蜜葱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布全景。 她就那樣靜靜地躺著,像睡著了一般牵囤。 火紅的嫁衣襯著肌膚如雪爸黄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天揭鳞,我揣著相機(jī)與錄音炕贵,去河邊找鬼。 笑死野崇,一個胖子當(dāng)著我的面吹牛称开,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乓梨,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鳖轰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了督禽?” 一聲冷哼從身側(cè)響起脆霎,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狈惫,沒想到半個月后睛蛛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹦马,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年忆肾,在試婚紗的時候發(fā)現(xiàn)自己被綠了荸频。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡客冈,死狀恐怖旭从,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情场仲,我是刑警寧澤和悦,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站渠缕,受9級特大地震影響鸽素,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜亦鳞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一馍忽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧燕差,春花似錦遭笋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刹帕,卻和暖如春吵血,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偷溺。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工蹋辅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挫掏。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓侦另,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尉共。 傳聞我的和親對象是個殘疾皇子褒傅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容