Carry の Blog Carry の Blog
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carry の Blog

好记性不如烂键盘
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • MySQL8-SOP

  • MySQL实战45讲学习笔记

    • MySQL45讲学习笔记
    • MySQL基础架构
    • MySQL日志系统 (Redo Log 与 Binlog)
    • MySQL字符串字段索引优化
    • MySQL索引原理与优化
    • MySQL锁机制详解
    • MySQL事务与MVCC机制
    • MySQL普通索引与唯一索引的选择
    • MySQL优化器如何选择索引
    • MySQL抖动刷脏页
    • 表空间管理与回收
    • count函数详解
    • 日志索引
    • orderby工作原理
    • 随机排序实现
    • SQL性能差异函数与转换
    • 慢查询分析锁与版本
    • 幻读与间隙锁
    • 加锁规则分析
    • 应急性能优化方法
    • 数据持久化保证
    • 主备一致性原理
    • 高可用架构与切换
    • 备库延迟分析与优化
    • 主备切换GTID
    • 读写分离实践与问题
    • 数据库健康检查
    • 锁与死锁
    • 数据误删恢复
    • Kill命令详解
    • 查询与内存使用分析
    • Join原理与选择
    • 临时表原理与应用
    • 内部临时表详解
    • Memory引擎详解
    • 自增ID详解
    • Insert加锁分析
      • 1. Insert语句的基本加锁机制
        • 1.1 表级锁
        • 1.2 行级锁
      • 2. 不同场景下的加锁行为
        • 2.1 普通INSERT操作
        • 2.2 批量INSERT操作
        • 2.3 INSERT ... SELECT操作
      • 3. 索引对加锁的影响
        • 3.1 主键插入
        • 3.2 唯一键冲突
      • 4. 间隙锁(Gap Lock)分析
        • 4.1 间隙锁的作用
        • 4.2 间隙锁示例
      • 5. 加锁的优化策略
        • 5.1 减少锁竞争
        • 5.2 控制事务大小
        • 5.3 使用适当的隔离级别
      • 6. 常见问题及解决方法
        • 6.1 插入死锁
        • 6.2 插入性能问题
      • 7. 监控和诊断
        • 7.1 查看锁等待情况
        • 7.2 查看事务状态
      • 8. 实际应用建议
        • 8.1 高并发场景
        • 8.2 数据导入场景
        • 8.3 事务控制
      • 9. 总结
    • 表复制方法比较
    • Grant与权限管理
    • 分区表详解
    • SQL语句中的Join问题
    • 自增ID用尽问题
  • 专题系列
  • MySQL实战45讲学习笔记
Carry の Blog
2026-03-04
目录

Insert加锁分析

# Insert加锁分析

# 1. Insert语句的基本加锁机制

在MySQL中,INSERT操作涉及到的锁主要分为以下几类:

# 1.1 表级锁

  • 在某些情况下会对整个表加锁
  • 通常发生在表结构变更或特定存储引擎下

# 1.2 行级锁

  • InnoDB存储引擎默认使用行级锁
  • 对插入的行进行加锁,防止并发冲突

# 2. 不同场景下的加锁行为

# 2.1 普通INSERT操作

INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
1

对于普通的INSERT操作:

  • InnoDB会对新插入的行加排他锁(X锁)
  • 锁的粒度是行级
  • 锁在事务提交后释放

# 2.2 批量INSERT操作

INSERT INTO users (name, email) VALUES 
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
('Charlie', 'charlie@example.com');
1
2
3
4

批量INSERT时:

  • 每一行都会获得相应的行级锁
  • 通常会使用间隙锁(Gap Lock)来防止幻读
  • 锁的范围会根据索引情况有所不同

# 2.3 INSERT ... SELECT操作

INSERT INTO users_backup 
SELECT * FROM users WHERE created_date > '2023-01-01';
1
2

这种操作涉及:

  • 对SELECT查询涉及的行加共享锁(S锁)
  • 对插入的新行加排他锁(X锁)
  • 可能产生更多的锁竞争

# 3. 索引对加锁的影响

# 3.1 主键插入

-- 如果users表有主键id
INSERT INTO users (id, name) VALUES (100, 'David');
1
2
  • 对主键为100的行加锁
  • 如果主键不存在,会加间隙锁防止插入相同主键值

# 3.2 唯一键冲突

-- 如果name字段有唯一索引
INSERT INTO users (name, email) VALUES ('Alice', 'alice2@example.com');
1
2
  • 检查name字段的唯一性约束
  • 如果冲突,会加锁阻止插入
  • 可能需要等待其他事务释放相关锁

# 4. 间隙锁(Gap Lock)分析

# 4.1 间隙锁的作用

间隙锁主要用于防止幻读:

  • 锁定索引记录之间的间隙
  • 防止其他事务在这个间隙中插入新的记录

# 4.2 间隙锁示例

-- 假设users表的id索引为 1, 5, 10, 15
INSERT INTO users (id, name) VALUES (7, 'Eve');
1
2
  • 会对(id=5, id=10)的间隙加锁
  • 防止其他事务插入id=7的记录

# 5. 加锁的优化策略

# 5.1 减少锁竞争

-- 1. 合理设计索引
CREATE INDEX idx_email ON users(email);

-- 2. 批量操作时注意顺序
-- 按照主键顺序插入可以减少锁竞争
1
2
3
4
5

# 5.2 控制事务大小

-- 避免长时间持有锁
BEGIN;
INSERT INTO users VALUES (1, 'Alice');
INSERT INTO users VALUES (2, 'Bob'); 
-- 不要在这里执行过多操作
COMMIT;
1
2
3
4
5
6

# 5.3 使用适当的隔离级别

-- 在允许的情况下使用读已提交隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
1
2

# 6. 常见问题及解决方法

# 6.1 插入死锁

-- 死锁场景示例
-- 事务A:
BEGIN;
INSERT INTO users VALUES (1, 'Alice');
-- 等待事务B释放锁
INSERT INTO users VALUES (2, 'Bob');

-- 事务B:
BEGIN;
INSERT INTO users VALUES (2, 'Charlie');
-- 等待事务A释放锁
INSERT INTO users VALUES (1, 'David');
1
2
3
4
5
6
7
8
9
10
11
12

解决方法:

  • 保持一致的锁定顺序
  • 缩短事务持续时间
  • 使用死锁检测机制

# 6.2 插入性能问题

-- 优化前:逐条插入
INSERT INTO users VALUES (1, 'Alice');
INSERT INTO users VALUES (2, 'Bob');
INSERT INTO users VALUES (3, 'Charlie');

-- 优化后:批量插入
INSERT INTO users VALUES 
(1, 'Alice'),
(2, 'Bob'),
(3, 'Charlie');
1
2
3
4
5
6
7
8
9
10

# 7. 监控和诊断

# 7.1 查看锁等待情况

-- 查看当前等待的锁
SELECT * FROM performance_schema.data_lock_waits;

-- 查看锁信息
SELECT * FROM performance_schema.data_locks;
1
2
3
4
5

# 7.2 查看事务状态

-- 查看当前活跃事务
SHOW ENGINE INNODB STATUS\G
1
2

# 8. 实际应用建议

# 8.1 高并发场景

  • 使用批量插入减少锁次数
  • 合理控制事务大小
  • 避免在高并发场景下使用长事务

# 8.2 数据导入场景

  • 导入前关闭自动提交
  • 使用批量插入语句
  • 考虑使用LOAD DATA INFILE语句

# 8.3 事务控制

-- 合理使用事务
START TRANSACTION;
INSERT INTO users VALUES (1, 'Alice');
INSERT INTO users VALUES (2, 'Bob');
COMMIT;
1
2
3
4
5

# 9. 总结

INSERT操作的加锁机制是MySQL并发控制的重要组成部分:

  1. 理解不同场景下的锁行为有助于避免死锁和性能问题
  2. 合理设计索引可以减少锁竞争
  3. 批量操作比逐条插入更高效
  4. 监控锁等待情况有助于及时发现并发问题
  5. 根据具体业务场景选择合适的隔离级别和事务控制策略
上次更新: 3/4/2026

← 自增ID详解 表复制方法比较→

最近更新
01
表空间管理与回收
03-04
02
MySQL抖动刷脏页
03-04
03
count函数详解
03-04
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式