兰必鑫 發表於 2025-9-2 20:33:00

数据库的锁级别

<p>锁是数据库保证&nbsp;<strong>并发一致性&nbsp;</strong>的重要手段,不同锁级别决定了锁的粒度和范围,从而影响并发性能与数据安全性。锁级别从粗到细:<strong>全局锁 → 表级锁 → 页级锁 → 行级锁,粒度越细,并发度越高,但开销越大</strong>。</p>
<h3>一、按锁的粒度划分(从粗到细)</h3>
<p><strong>1、全局锁(Global Lock)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 定义</strong>:对整个数据库实例加锁,限制所有表的读写操作。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 适用场景</strong>:全库逻辑备份(如 MySQL 的&nbsp;<code>FLUSH TABLES WITH READ LOCK</code>),确保备份期间数据不被修改,保证备份一致性。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 特点</strong>:</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>①</strong>&nbsp;加锁期间,整个库处于只读状态,所有更新、插入、删除操作都会被阻塞。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>②</strong>&nbsp;粒度最粗,并发影响最大,一般仅在特殊场景(如全库备份)短期使用。</p>
<p><strong>2、表级锁(Table-level Lock)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 定义</strong>:对整张表加锁,控制对表的并发访问。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 常见类型</strong>:</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① 表共享锁(Table Shared Lock,读锁 S)</strong>: 持有读锁时,所有事务可读取表数据,但不能修改,且其他事务也可加读锁,但不能加写锁。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② 表排他锁(Table Exclusive Lock,写锁 X)</strong>:持有写锁时,只有当前事务可读写表数据,其他事务既不能读也不能写(需等待锁释放)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;③ 意向锁(Intention Lock)</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(a)</strong> 数据库自动添加,用于表级锁和行级锁的协调(如 MySQL InnoDB)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(b)</strong> 意向共享锁(IS):事务 <strong>打算&nbsp;</strong>对表中某些行加读锁。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(c)</strong> 意向排他锁(IX):事务&nbsp;<strong>打算</strong> 对表中某些行加写锁。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(d)</strong> 作用:提前声明锁意图,避免表级锁和行级锁的冲突检查效率过低。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;④ 自增锁(Auto-increment Lock)</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(a)</strong> 针对自增列(如&nbsp;<code>AUTO_INCREMENT</code>)的特殊锁,保证插入时自增值唯一。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(b)</strong> MySQL 可通过&nbsp;<code>innodb_autoinc_lock_mode</code>&nbsp;调整锁粒度(0: 全表锁; 1:&nbsp;连续值批量锁;2:无锁,依赖二进制日志确保一致性)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 适用场景</strong>:</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① </strong>&nbsp;表结构修改(如&nbsp;<code>ALTER TABLE</code>)、全表扫描或大量数据更新(避免行锁竞争)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② </strong>非事务引擎(如 MySQL MyISAM)默认使用表级锁。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4) 特点</strong>:开销小、加锁快,适合表级操作,但 <strong>并发度低</strong>(<strong>容易阻塞</strong>)。</p>
<p><strong>3、行级锁(Row-level Lock)</strong></p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (1) 定义</strong>:对表中单行数据加锁,是粒度最细的锁,并发度最高。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 常见类型(以 MySQL InnoDB 为例)</strong>:</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① 行共享锁(Row Shared Lock,S)</strong>:事务对某行加读锁,允许其他事务读该行,但不能修改(需等锁释放)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② 行排他锁(Row Exclusive Lock,X)</strong>:事务对某行加写锁,其他事务既不能读(需等锁释放)也不能写该行。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;③ 间隙锁(Gap Lock)</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(a)</strong>&nbsp;锁定索引记录之间的 "间隙"(如&nbsp;<code>WHERE id BETWEEN 5 AND 10</code>,锁定 5~10 之间的空白区域),防止其他事务插入数据导致 "幻读"。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(b)</strong> 仅在 InnoDB 的&nbsp;<strong>可重复读(RR)隔离级别</strong>&nbsp;下生效。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;④ 临键锁(Next-key Lock)</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(a)</strong>&nbsp;行锁 + 间隙锁的组合,锁定索引记录本身及前面的间隙(如索引值为 10 的行,锁定 (-∞,10] 范围)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>(b)</strong>&nbsp;InnoDB 默认的行级锁类型,用于平衡并发和一致性。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;⑤ 记录锁(Record Lock)</strong>:仅锁定单行记录(不包含间隙),在&nbsp;<strong>读已提交(RC)隔离级别</strong>&nbsp;或条件命中唯一索引时生效。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 适用场景</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>① </strong>高并发的单行或少量行操作(如用户余额更新、订单状态修改)。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>② </strong>事务引擎(如 InnoDB、PostgreSQL)的核心锁机制。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4) 特点</strong>:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>① </strong>开销大、加锁慢(需定位具体行),但并发度高,适合精细化控制。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>② </strong>可能引发死锁(多个事务互相等待对方释放行锁)。</p>
<p><strong>4、页级锁(Page-level Lock)</strong></p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (1) 定义</strong>:对数据页(数据库存储的基本单位,如 InnoDB 一页默认 16KB)加锁,粒度介于表级和行级之间。</p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (2) 适用场景</strong>:部分数据库(如 MySQL BDB 引擎、SQL Server)支持,平衡并发和开销。</p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (3) 特点</strong>:加锁速度快于行锁,并发度高于表锁,但可能出现 "页内无关行被锁定"&nbsp;的浪费。</p>
<h3>二、按锁的功能 / 模式划分</h3>
<p><strong>1、共享锁(Shared Lock,S 锁)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 作用</strong>:允许事务读取数据,多个事务可同时持有同一资源的 S 锁。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 兼容性</strong>:与 S 锁兼容,与 X 锁互斥(读锁和写锁不能同时存在)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 示例</strong>:<code>SELECT ... LOCK IN SHARE MODE</code>(MySQL InnoDB 手动加读锁)。</p>
<p><strong>2、排他锁(Exclusive Lock,X 锁)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 作用</strong>:允许事务修改数据,仅当前事务可持有,阻止其他事务读写。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 兼容性</strong>:与所有锁(S 锁、X 锁)互斥。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 示例</strong>:<code>SELECT ... FOR UPDATE</code>(MySQL InnoDB 手动加写锁),或&nbsp;<code>UPDATE</code>/<code>DELETE</code>&nbsp;语句自动加 X 锁。</p>
<p><strong>3、乐观锁(Optimistic Lock)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 定义</strong>:非数据库原生锁,通过 "版本号" 或 "时间戳" 实现并发控制,假设冲突概率低,仅在提交时检查是否有冲突。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 实现方式</strong>:表中增加&nbsp;<code>version</code>&nbsp;字段,更新时&nbsp;<code>WHERE version = 原版本</code>,若失败则重试。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 适用场景</strong>:读多写少、冲突少的场景(如商品库存查询)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4) 特点</strong>:无锁等待,性能高,但需应用层实现,不适合高冲突场景。</p>
<p><strong>4、悲观锁(Pessimistic Lock)</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) 定义</strong>:数据库原生锁机制,假设冲突概率高,操作前先加锁,确保独占资源。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) 示例</strong>:<strong>行级锁、表级锁均属于悲观锁</strong>。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3) 适用场景</strong>:写多读少、冲突频繁的场景(如秒杀库存扣减)。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4) 特点</strong>:保证一致性,但可能导致锁等待和死锁。</p>
<h3>三、不同数据库的锁机制差异</h3>
<p><strong>1、MySQL</strong>:</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1) </strong>InnoDB 支持行级锁(Next-key Lock 为主)、表级锁(意向锁、自增锁)、全局锁。</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2) </strong>MyISAM 仅支持表级锁(读锁 / 写锁),不支持事务。</p>
<p><strong>2、PostgreSQL</strong>:支持行级锁(共享 / 排他)、表级锁、页级锁,且有 "咨询锁"(应用层自定义锁)。</p>
<p><strong>3、Oracle</strong>:以行级锁为主,通过 "回滚段" 实现多版本并发控制(MVCC),锁机制更灵活。</p>
<p><strong>4、SQL Server</strong>:支持表级锁、页级锁、行级锁,可通过&nbsp;<strong><code>SET TRANSACTION ISOLATION LEVEL</code></strong>&nbsp;调整锁行为。</p>
<p style="text-align: right"><span style="color: rgba(53, 152, 219, 1)">不断成长,走出舒适区,实现自我增值。-- 烟沙九洲</span></p><br><br>
来源:https://www.cnblogs.com/yanshajiuzhou/p/19070679
頁: [1]
查看完整版本: 数据库的锁级别