当前位置: 首页 > news >正文

MySQL锁

MySQL 锁(Lock)是数据库保证并发操作时数据一致性的核心机制,通过控制多个事务对资源的访问顺序,避免出现脏读、数据冲突等问题。合理理解和使用锁机制,对提升数据库并发性能至关重要。

锁级别 锁类型 描述 适用场景 存储引擎支持
全局锁 FTWRL 锁定整个数据库实例 全库备份 所有引擎
表级锁 表锁 锁定整张表 批量操作 所有引擎
元数据锁 保护表结构 DDL操作 MySQL 5.5+
行级锁 记录锁 锁定索引记录 精确更新 InnoDB
间隙锁 锁定索引间隙 防止幻读 InnoDB
临键锁 记录锁+间隙锁 范围查询 InnoDB
意向锁 IS锁 意向共享锁 行级S锁前 InnoDB
IX锁 意向排他锁 行级X锁前 InnoDB

1、全局锁

1.1 FLUSH TABLES WITH READ LOCK (FTWRL)

-- 加全局读锁
FLUSH TABLES WITH READ LOCK;-- 解锁
UNLOCK TABLES;

特点:

  • 整个数据库处于只读状态
  • 阻塞所有写操作和DDL操作
  • 常用于全库逻辑备份

1.2 备份替代方案


-- InnoDB引擎使用--single-transaction参数
mysqldump --single-transaction -u root -p database > backup.sql-- 其他引擎使用锁表备份
LOCK TABLES table1 READ, table2 READ;
-- 备份操作...
UNLOCK TABLES;

2、表级锁

特点:

  • 锁定整个表
  • 实现简单,开销小
  • 并发度低,容易成为瓶颈
  • MyISAM 存储引擎主要使用表级锁

2.1 显式表锁

-- 加读锁(表共享读锁)对指定表加了读锁,不会影响其他客户端的读,但是会阻塞其他客户端的写。
LOCK TABLES orders READ;-- 加写锁(表独占写锁)对指定表加了写锁,会阻塞其他客户端的读和写。
LOCK TABLES orders WRITE;-- 解锁
UNLOCK TABLES;

2.2 元数据锁 (MDL)

meta data lock, 元数据锁,简写MDL。

  • MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。
  • MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。
  • 为了避免DML与DDL冲突,保证读写的正确性。这里的元数据,大家可以简单理解为就是一张表的表结构。 也就是说,某一张表涉及到未提交的事务时,是不能够修改这张表的表结构的。

自动加锁机制:

  • 访问表时自动加 MDL 读锁
  • 修改表结构时加 MDL 写锁

问题场景

-- 会话1
START TRANSACTION;
SELECT * FROM orders; -- 加MDL读锁-- 会话2
ALTER TABLE orders ADD COLUMN new_col INT; -- 阻塞,等待MDL写锁-- 会话3
SELECT * FROM orders; -- 阻塞,等待MDL读锁

3、行级锁 (InnoDB)

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。

InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。

3.1 记录锁 (Record Lock)

锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。

  • 锁定索引项,非记录本身
  • 主键索引:直接锁定主键记录
  • 二级索引:锁定二级索引+主键索引
-- 锁定索引记录
SELECT * FROM accounts WHERE id = 100 FOR UPDATE;
  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。

  • 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

兼容性

  • 共享锁:共享锁兼容,排他锁冲突
  • 排他锁:共享锁冲突,排他锁冲突

常见的SQL语句,在执行时,所加的行锁如下:

SQL 行锁类型 说明
INSERT ... 排他锁 自动加锁
UPDATE ... 排他锁 自动加锁
DELETE ... 排他锁 自动加锁
SELECT (正常) 不加任何 铺
SELECT ... LOCK IN SH 共享锁 需要手动在SELECT之后加LOCK IN SHARE MODE
SELECT ... FOR UPDATE 排他锁 需要手动在SELECT之后加FOR UPDATE

3.2 间隙锁 (Gap Lock)

锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。

  • 锁定索引记录之间的间隙
  • 防止其他事务在范围内插入新记录
  • 只在 REPEATABLE READ 隔离级别生效
-- 锁定范围间隙
SELECT * FROM accounts 
WHERE balance BETWEEN 1000 AND 5000 
FOR UPDATE;

3.3 临键锁 (Next-Key Lock)

行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。

  • 记录锁 + 间隙锁组合
  • InnoDB 默认行锁算法
  • 解决幻读问题
-- 锁定记录和间隙
SELECT * FROM accounts  WHERE age > 30 FOR UPDATE;

4、意向锁 (Intention Lock)

表级锁,用于标记 “某个事务将要对表中的行加锁”,减少表锁和行锁的冲突检查开销。

  • 意向共享锁(IS): 由语句select ... lock in share mode添加。与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。

  • 意向排他锁(IX): 由insert、update、delete、select...for update添加 。与表锁共享锁(read)及排他锁(write)都互斥,意向锁之间不会互斥。

一旦事务提交了,意向共享锁、意向排他锁,都会自动释放。

兼容性:意向锁之间互不冲突
意向共享锁(IS):排他锁冲突,共享锁兼容
意向排他锁(IX):排他锁冲突,共享锁冲突

5、锁的实战应用

5.1 账户转账事务

START TRANSACTION;-- 锁定转入账户
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;-- 锁定转出账户
SELECT * FROM accounts WHERE id = 2 FOR UPDATE;-- 执行转账
UPDATE accounts SET balance = balance - 100 WHERE id = 2;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;COMMIT;

5.2 防止超卖

START TRANSACTION;-- 锁定商品库存
SELECT stock FROM products WHERE id = 100 FOR UPDATE;-- 检查库存
IF stock > 0 THENUPDATE products SET stock = stock - 1 WHERE id = 100;INSERT INTO orders (product_id, quantity) VALUES (100, 1);
END IF;COMMIT;
http://www.hskmm.com/?act=detail&tid=119

相关文章:

  • 异步电机的无速度传感器的矢量控制
  • 打包好dist文件 本地如何测?
  • 日期函数(mysql和oracle)
  • 图灵因果测试是由本框架(ECT-OS-JiuHuaShan)定义的下一代智能评估范式
  • QOJ 5357 芒果冰加了空气
  • AI智能体(Agent)开发实战:工业级项目案例驱动课
  • 易路联合智享会权威发布,2025《AI技术如何重构人才获取全链路》
  • java 开发中VO、PO、DO、DTO、BO、QO、DAO、POJO
  • Typora--Markdown语法
  • Perfetto数据流架构故障分析:带你研究 trace 为何丢失
  • 记一次 .NET 某中医药附属医院门诊系统 崩溃分析
  • 个人使用IDEA经验总结
  • JDK 24软件介绍
  • 【LangChain 核心模块 01】
  • 数据跨境学习笔记
  • NOIP 模拟赛十三
  • PageHelper
  • MathType7 功能分析
  • 低版本 Linux【16.04】如何安装 claude code
  • Redis数据持久化方案与集群部署
  • 什么,以太网能传CAN报文?
  • 物业管理小程序系统介绍
  • 阿里云文件上传oss存储
  • 快照同步思想
  • Windows-系统自动切换IPv4地址
  • 目录导航
  • sql嵌套查询
  • archlinux gnome48 顶部托盘选择
  • AT_agc014_f [AGC014F] Strange Sorting
  • JS常用函数