成人免费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

2022-03-25 10:38:40

索引MySQL數據庫

2025-06-04 02:55:00

MySQL意向鎖記錄鎖

2024-05-20 09:58:27

2010-10-08 14:32:47

MySQL使用INSE

2023-07-03 08:15:46

MySQLInnoDB

2024-11-05 10:52:07

2022-10-24 08:02:14

MySQL索引類型

2022-03-10 11:25:51

InnoDB優化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲黄色高清视频 | 国产一区中文 | 国产精品99久久久久久动医院 | 国产男女猛烈无遮掩视频免费网站 | 天天综合永久入口 | 国产成人在线视频 | 中文字幕在线一区 | 国产精品久久 | av一区在线观看 | 国产成人精品一区二区 | 国产一区二区三区免费观看视频 | 成人欧美一区二区三区在线观看 | 久在线| 最新国产在线 | 成人免费小视频 | 亚洲一区二区免费视频 | 精品一区二区免费视频 | 精品久久国产 | 国产在线精品一区二区 | 一级高清免费毛片 | 国产乱一区二区三区视频 | 日韩精品一区二区三区在线播放 | 久久中文字幕一区 | 一区二区三区四区日韩 | 久久久久久久久久久久亚洲 | 亚洲精品久久久9婷婷中文字幕 | 日本在线免费 | 久久久.com| 一区二区三区影院 | av手机免费在线观看 | 国产日韩精品一区二区三区 | 亚洲三区视频 | 老司机精品福利视频 | 一区二区视频 | 国产一区中文字幕 | 欧美日韩在线一区二区 | 欧美a级成人淫片免费看 | 国产一极毛片 | 久草资源 | 国产在线播放av | 日韩伦理电影免费在线观看 |