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

MySQL 核心模塊揭秘 | 插入記錄,主鍵索引沖突加什么鎖?

數據庫 MySQL
InnoDB 發現表中已經有一條 <id = 10> 的記錄,現在又要插入一條 <id = 10> 的記錄,可是主鍵索引中不允許存在重復記錄,這可怎么辦才好?

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. 加鎖情況

t1 表中已經有一條 <id = 10> 的記錄,我們執行以下 insert 語句,再插入一條 <id = 10> 的記錄。

begin;
insert into t1(id, i1) values (10, 1010);

因為新插入記錄和表中原有記錄存在主鍵沖突,執行 insert 語句之后,報錯如下:

(1062, "Duplicate entry '10' for key 't1.PRIMARY'")

執行以下 select 語句查詢加鎖情況:

select
   engine_transaction_id, object_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 | 247910
object_name           | t1
lock_type             | RECORD
lock_mode             | S,REC_NOT_GAP
lock_status           | GRANTED
lock_data             | 10

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

3. 原理分析

insert 語句執行過程中,插入記錄到主鍵索引之前,需要先找插入記錄的目標位置。

目標位置為表中主鍵字段值小于等于新插入記錄中主鍵字段值的最后一條記錄之后。

以示例 SQL 為例,插入主鍵字段 <id = 10> 的記錄。

插入記錄到主鍵索引之前,先找到表中 id 小于等于 10 的最后一條記錄,也就是 <id = 10, i1 = 101> 這條記錄。新插入記錄的目標位置就是這條記錄之后。

InnoDB 發現表中已經有一條 <id = 10> 的記錄,現在又要插入一條 <id = 10> 的記錄,可是主鍵索引中不允許存在重復記錄,這可怎么辦才好?

直接報錯嗎?

那樣簡單粗暴就過于武斷了。

InnoDB 還需要對表中 <id = 10> 的記錄驗明正身,確定它是一條有效的記錄。

如果表中 <id = 10> 的記錄已經被其它已提交事務標記刪除,只是還沒有被清理,它就不是有效的記錄了。這種情況下,新記錄可以正常插入,不會報錯。

否則,新記錄和表中已有記錄沖突,不能插入,就可以報錯了。

為了防止其它事務更新或者刪除這條記錄,檢查表中記錄是否有效之前,InnoDB 會對這條記錄加共享普通記錄鎖。

這就是示例 SQL 執行過程中對 <id = 10> 的記錄加共享普通記錄鎖的原因。

如果表中 <id = 10> 的記錄已經被標記刪除,但是刪除這條記錄的事務還沒有提交怎么辦?

那我們看到的加鎖情況就不一樣了。

我們可以模擬下這個場景,創建 2 個 MySQL 連接,分別執行 delete 語句和 insert 語句。

-- 連接 1(事務 1)
begin;
delete from t1 where id = 10;

-- 連接 2(事務 2)
begin;
insert into t1(id, i1) values (10, 1010);

然后執行以下 select 語句查看加鎖情況:

select
   engine_transaction_id, object_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 | 247916
object_name           | t1
lock_type             | RECORD
lock_mode             | S,REC_NOT_GAP
lock_status           | WAITING
lock_data             | 10
***************************[ 2. row ]***************************
engine_transaction_id | 247911
object_name           | t1
lock_type             | RECORD
lock_mode             | X,REC_NOT_GAP
lock_status           | GRANTED
lock_data             | 10

事務 247911 執行刪除操作對 <id = 10> 的記錄加了排他普通記錄鎖。

事務 247916 想要對 <id = 10> 的記錄加共享普通記錄鎖被阻塞,進入等待狀態。

4. 總結

沒有需要總結的內容了。

但是有兩個問題:事務 247911 提交或者回滾之后,加鎖情況是什么樣的?為什么會這樣?

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

2024-10-16 11:11:51

隔離InnoDB死鎖

2024-08-07 14:58:00

MySQL釋放鎖核心模塊

2024-10-30 10:38:08

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核心模塊

2023-06-05 08:15:30

MySQLInnoDB

2024-05-29 10:17:01

2024-03-27 13:33:00

MySQLInnoDB事務

2025-02-26 08:26:38

2022-12-18 16:56:07

索引MySQL

2025-06-04 02:55:00

MySQL意向鎖記錄鎖

2022-03-25 10:38:40

索引MySQL數據庫

2010-10-08 14:32:47

MySQL使用INSE

2023-07-03 08:15:46

MySQLInnoDB

2024-05-20 09:58:27

2024-11-05 10:52:07

2022-10-24 08:02:14

MySQL索引類型

2022-03-10 11:25:51

InnoDB優化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区二区在线免费观看 | 欧美一区二区小视频 | 欧美性猛交一区二区三区精品 | 久久久69 | 免费一区 | 91麻豆蜜桃一区二区三区 | 日韩在线观看网站 | 日本一区二区三区在线观看 | 亚洲人成在线播放 | 成人精品一区 | 欧美精品一区二区在线观看 | 久久中文字幕一区 | 91欧美激情一区二区三区成人 | 理论片午午伦夜理片影院 | 91精品国产高清久久久久久久久 | 欧美日韩大片 | 精品亚洲视频在线 | 亚洲品质自拍视频网站 | 91麻豆产精品久久久久久夏晴子 | 青青久草 | 久久av一区二区三区 | 欧美在线看片 | 亚洲激情一区二区三区 | 91视视频在线观看入口直接观看 | 欧美激情一区二区三区 | 色婷婷国产精品 | 国产精品日日摸夜夜添夜夜av | 日本a∨精品中文字幕在线 亚洲91视频 | 在线观看中文字幕视频 | 欧美精品一区在线 | 天天色综网 | 欧美一级片免费看 | 91久久久久久久久久久 | 96久久久久久 | 国产一级一级毛片 | 国产精品亚洲一区 | 国产精品久久久久久久久久久久久 | 精品国产一区二区三区免费 | 91原创视频在线观看 | 影音先锋成人资源 | 国产一区欧美 |