资讯动态

MySQL中的锁详解

发布时间:2026/9/10 0:38:42 来源:尧图企业网站定制
在 MySQL 中锁机制是保证数据一致性和事务隔离性的基石。特别是对于默认的 InnoDB 存储引擎理解各种锁的运作原理对于构建高并发应用至关重要。以下是关于 MySQL 中各类锁的详细教程一、按锁粒度划分锁粒度决定了锁的影响范围。粒度越小并发度越高但锁管理的开销也就越大。1. 全局锁Global Lock定义锁定整个 MySQL 实例是粒度最大的锁。作用保证整个实例的数据一致性防止数据被修改。实现与场景通过FLUSH TABLES WITH READ LOCK (FTWRL)命令加锁。主要用于全库逻辑备份避免备份过程中数据被修改。加锁后所有库的所有表都只能读写操作增删改、DDL全部被阻塞。解锁使用UNLOCK TABLES。2. 表级锁Table-Level Lock定义锁定整张表开销小、加锁快但并发度低。常见类型表读锁READ / 共享锁 S 锁加锁后自己和其他会话都能读表但所有会话都不能写表。适用于只读操作如批量查询。表写锁WRITE / 排他锁 X 锁加锁后只有自己能读写表其他会话既不能读也不能写。适用于批量修改表数据。元数据锁MDL隐式加锁无需手动干预。保护表结构元数据不被修改。DDL 操作会加 MDL 写锁DML / 查询加 MDL 读锁。意向锁Intention Locks表级的“标记锁”由 InnoDB 自动管理。分为意向共享锁IS和意向排他锁IX用于表示“某个事务准备给表中的某些行加锁”避免行锁和表锁冲突。3. 行级锁Row-Level Lock定义锁定表中的单行数据粒度最小并发度最高是 InnoDB 引擎特有的优势MyISAM 不支持。核心类型行共享锁S 锁事务对行加 S 锁后其他事务可加 S 锁共享读但不能加 X 锁排他写。通过SELECT ... LOCK IN SHARE MODE加锁。行排他锁X 锁事务对行加 X 锁后其他事务既不能加 S 锁也不能加 X 锁保证修改/删除时数据独占。通过SELECT ... FOR UPDATE或普通的UPDATE/DELETE/INSERT语句自动加锁。间隙锁Gap Lock锁定索引记录之间的“间隙”不包含记录本身防止插入新数据主要用来解决“幻读”问题。临键锁Next-Key Lock行锁 间隙锁的组合锁定“记录 记录前的间隙”左开右闭区间。这是 InnoDB 在可重复读RR隔离级别下默认的行锁方式。插入意向锁Insert Intention Lock多个事务插入同一间隙时的“意向锁”互不阻塞用于提升并发插入效率。自增锁AUTO-INC Lock针对自增列的表级锁保证自增 ID 连续唯一。二、按锁功能划分1. 共享锁Shared Lock, S 锁又称为读锁。当事务对数据加了 S 锁其他事务可以再加 S 锁读数据但不能加 X 锁修改数据。实现了“读读不阻塞读写阻塞”。2. 排他锁Exclusive Lock, X 锁又称为写锁。当事务对数据加了 X 锁其他事务不能加任何锁既不能读也不能写。实现了“写写阻塞读写阻塞”。三、行级锁的算法实现与死锁InnoDB 的行级锁是通过索引来实现的。如果查询语句没有使用索引InnoDB 会退化为表级锁锁住整个表。其核心算法包括记录锁Record Lock精准锁住某一条索引记录。例如WHERE id 1只会锁住 id1 的这一行。间隙锁Gap Lock锁住两个索引记录之间的间隙不锁住记录本身只防止其他事务在这个间隙里插入新数据。临键锁Next-Key LockInnoDB RR 级别下的默认行锁算法临键锁 记录锁 间隙锁。例如表中有 id1、5、10 三条记录临键锁会把索引分成 (-∞,1]、(1,5]、(5,10]、(10,∞] 四个区间当你查询WHERE id 5时InnoDB 会锁住 (-∞,1]、(1,5] 两个区间彻底杜绝了其他事务插入符合条件的数据从根本上解决了幻读问题。死锁Deadlock与最佳实践行级锁虽然提升了并发度但也带来了死锁的风险。当两个或多个事务互相等待对方释放锁时就会形成死锁。死锁示例事务 A 先更新 id1 再更新 id2事务 B 先更新 id2 再更新 id1。如果两者同时进行就会互相等待对方释放锁导致死锁。解决方案按固定顺序访问资源。例如在业务代码中都按照 id 从小到大的顺序去更新数据。两阶段锁协议2PLInnoDB 遵循此协议锁的操作分为加锁阶段和解锁阶段。直到事务提交COMMIT或回滚ROLLBACK时才会一次性释放所有在该事务中获取的锁。因此为了减少锁冲突应尽量将最可能引起冲突的写操作如SELECT … FOR UPDATE放在事务的后面执行以缩短排他锁的持有时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价