成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL 核心模塊揭秘—主鍵索引范圍查詢加什么鎖?

數據庫 其他數據庫
InnoDB 把這條記錄返回給 server 層之后,server 層判斷這條記錄不匹配 where 條件,會通知 InnoDB 釋放這條記錄上剛剛加的共享普通記錄鎖。

1. 準備工作

創建測試表:

CREATE TABLE `t1` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `i1` int DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_i1` (`i1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

插入測試數據:

INSERT INTO `t1` (`id`, `i1`) VALUES
(10, 101), (20, 201), (30, 301), (40, 401);

2. 可重復讀

把事務隔離級別設置為 REPEATABLE-READ(如已設置,忽略此步驟):

SET transaction_isolation = 'REPEATABLE-READ';

-- 確認設置成功
SHOW VARIABLES like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+

執行以下 select 語句:

begin;
select * from t1 ignore index(idx_i1)
where id >= 10 and id < 30 for share;

查看加鎖情況:

select
   engine_transaction_id, object_name, index_name,
   lock_type, lock_mode, lock_status, lock_data
 from performance_schema.data_locks
 where object_name = 't1'
 and lock_type = 'RECORD'\G

***************************[ 1. row ]***************************
engine_transaction_id | 281479856983976
object_name           | t1
index_name            | PRIMARY
lock_type             | RECORD
lock_mode             | S,REC_NOT_GAP
lock_status           | GRANTED
lock_data             | 10
***************************[ 2. row ]***************************
engine_transaction_id | 281479856983976
object_name           | t1
index_name            | PRIMARY
lock_type             | RECORD
lock_mode             | S
lock_status           | GRANTED
lock_data             | 20
***************************[ 3. row ]***************************
engine_transaction_id | 281479856983976
object_name           | t1
index_name            | PRIMARY
lock_type             | RECORD
lock_mode             | S,GAP
lock_status           | GRANTED
lock_data             | 30

lock_data = 10、lock_mode = S,REC_NOT_GAP 表示對主鍵索引中 <id = 10> 的記錄加了共享普通記錄鎖。

沒有按照默認行為加共享 Next-Key 鎖,是因為示例 SQL 使用主鍵索引進行范圍掃描,從 <id = 10> 的記錄開始,不關心它前面的記錄。

示例 SQL 并不在意其它事務往 <id = 10> 的記錄前面插入什么記錄,不需要鎖住它前面的間隙,加普通記錄鎖就可以了。

如果有其它事務往 <id = 10> 的記錄前面的間隙插入記錄,示例 SQL 還能保證可重復讀嗎?

這個是沒問題的。

因為其它事務往 <id = 10> 的記錄前面的間隙插入記錄,這些記錄的 id 字段值一定小于 10,在示例 SQL 的 where 條件覆蓋范圍之外,不影響示例 SQL 的可重復讀。

其它事務要往 t1 表中插入記錄,id 大于等于 10、小于等于 19 的記錄都會插入到 <id = 10> 和 <id = 20> 之間的間隙。這個間隙不歸 <id = 10> 的記錄上的鎖管轄。

當然了,因為存在主鍵索引,t1 表中 <id = 10> 的記錄刪除之前,其它事務想要再插入 <id = 10> 的記錄是不可能的。

lock_data = 20、lock_mode = S 表示對主鍵索引中 <id = 20> 的記錄加了共享 Next-Key 鎖,這是可重復讀隔離級別下的默認行為,不多解釋。

lock_data = 30、lock_mode = S,GAP 表示對主鍵索引中 <id = 30> 的記錄加了共享間隙鎖。

沒有按照默認行為加共享 Next-Key 鎖,是因為 <id = 30> 的記錄位于示例 SQL 的 where 條件覆蓋范圍之外。

示例 SQL 不關心 <id = 30> 的記錄本身,只需要保證其它事務不能往這條記錄前面的間隙插入記錄,加共享間隙加就滿足需求了。

3. 讀已提交

把事務隔離級別設置為 READ-COMMITTED(如已設置,忽略此步驟):

SET transaction_isolation = 'READ-COMMITTED';

-- 確認設置成功
SHOW VARIABLES like 'transaction_isolation';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+

執行以下 select 語句:

begin;
select * from t1 ignore index(idx_i1)
where id >= 10 and id < 30 for share;

查看加鎖情況:

select
   engine_transaction_id, object_name, index_name,
   lock_type, lock_mode, lock_status, lock_data
 from performance_schema.data_locks
 where object_name = 't1'
 and lock_type = 'RECORD'\G

***************************[ 1. row ]***************************
engine_transaction_id | 281479856983976
object_name           | t1
index_name            | PRIMARY
lock_type             | RECORD
lock_mode             | S,REC_NOT_GAP
lock_status           | GRANTED
lock_data             | 10
***************************[ 2. row ]***************************
engine_transaction_id | 281479856983976
object_name           | t1
index_name            | PRIMARY
lock_type             | RECORD
lock_mode             | S,REC_NOT_GAP
lock_status           | GRANTED
lock_data             | 20

lock_data = 10、lock_mode = S,REC_NOT_GAP 表示對主鍵索引中 <id = 10> 的記錄加了共享普通記錄鎖,這是讀已提交隔離級別的默認行為,不多解釋。

lock_data = 20、lock_mode = S,REC_NOT_GAP 表示對主鍵索引中 <id = 20> 的記錄加了共享普通記錄鎖,這是讀已提交隔離級別的默認行為,不多解釋。

可重復讀隔離級別對主鍵索引中 <id = 30> 的記錄加了鎖,讀已提交隔離級別為什么沒有對主鍵索引中 <id = 30> 的記錄加鎖呢?

其實讀已提交隔離級別下,InnoDB 從主鍵索引中讀取 <id = 30> 的記錄之后,也會加共享普通記錄鎖。

InnoDB 把這條記錄返回給 server 層之后,server 層判斷這條記錄不匹配 where 條件,會通知 InnoDB 釋放這條記錄上剛剛加的共享普通記錄鎖。

我們最終看到的結果就是示例 SQL 沒有對主鍵索引中 <id = 30> 的記錄加鎖。

這種加了鎖又釋放的方式,一般情況下沒什么影響,但是如果因為這種方式造成了死鎖,我們不了解這個邏輯,就會有點摸不著頭腦了。

4. 總結

可重復讀隔離級別下,對某條記錄加了鎖,要等到事務提交或者回滾時才釋放。

讀已提交隔離級別下,對某條記錄加了鎖,如果 server 層或者 InnoDB 發現記錄不匹配 where 條件,會馬上釋放鎖。

責任編輯:武曉燕 來源: 愛可生開源社區
相關推薦

2024-09-04 08:44:18

MySQL核心模塊

2024-08-07 14:58:00

MySQL釋放鎖核心模塊

2024-08-28 08:50:11

MySQL核心模塊

2024-04-03 08:20:53

MySQL核心模塊

2024-06-05 11:49:33

2024-05-15 09:05:42

MySQL核心模塊

2024-10-30 10:38:08

2024-05-29 10:17:01

2024-03-27 13:33:00

MySQLInnoDB事務

2022-12-18 16:56:07

索引MySQL

2025-02-26 08:26:38

2012-09-20 10:13:04

MongoDB

2010-10-21 14:54:32

查詢SQL Serve

2022-03-25 10:38:40

索引MySQL數據庫

2024-05-20 09:58:27

2010-09-28 11:07:37

SQL索引

2021-06-06 13:03:53

MySQL普通索引

2024-11-05 10:52:07

2023-06-05 08:15:30

MySQLInnoDB

2022-09-08 13:56:49

MySQL事務記錄鎖
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品久久久久久久久久久久 | 欧美一区二区在线观看 | 国产成人免费视频 | 亚洲狠狠丁香婷婷综合久久久 | 91精品国产91久久综合桃花 | 精品免费国产视频 | 精品视频久久久久久 | 国产成人免费网站 | 精品国产一区二区久久 | 日韩国产在线 | 8x国产精品视频一区二区 | 中文字幕一二三 | 久久精品二区 | 成人在线视频看看 | 91精品久久久久久久久中文字幕 | 国产成人精品午夜 | 亚洲精品美女在线观看 | 国产精品乱码一区二三区小蝌蚪 | 激情六月丁香 | 久久99精品久久久久久 | 人人做人人澡人人爽欧美 | 一二区成人影院电影网 | 大象视频一区二区 | 成人夜晚看av | 免费观看成人鲁鲁鲁鲁鲁视频 | 国产一区二区三区四区五区加勒比 | 欧美一区二区三区在线观看视频 | 日本国产高清 | 欧美日韩a| 中文字幕av网站 | 黄色av观看 | 自拍偷拍在线视频 | 久久国产精品久久久久久 | 久久精品在线免费视频 | 国产精品久久久久久久久污网站 | 亚洲精品欧美 | 日韩在线欧美 | 成人av网站在线观看 | 成人国产精品免费观看视频 | 久久网国产 | 三级特黄特色视频 |