数据库锁机制:表锁、行锁(Oracle 默认)、共享锁、排他锁、乐观锁、悲观锁、死锁、Hive 中的锁

数据库锁机制是控制并发访问数据的关键技术。


本文系统介绍了锁的概念、分类和应用场景:

1)锁通过限制并发访问确保数据一致性,类比厕所门锁机制;

2)按粒度分为表锁(适合批量操作)、行锁(适合高并发)和页锁;

3)按模式分为共享锁(读锁)、排他锁(写锁)和意向锁;

4)对比了悲观锁(先加锁)和乐观锁(后检查)的实现差异;

5)分析了死锁成因及解决方案;

6)特别说明Hive采用表锁的设计考量。


不同数据库根据应用场景选择适合的锁机制,如OLTP系统多用行锁,数据仓库倾向表锁。


数据库锁机制详解


一、什么是锁?

一句话理解 :锁就是控制多人同时访问同一数据的机制。


生活类比

text

复制代码
公共厕所:
- 有人进去了 → 锁上门(加锁)
- 其他人 → 只能等待(阻塞)
- 里面的人出来 → 打开锁(释放锁)
- 下一个人 → 才能进去

如果不锁门:两个人同时进去...尴尬!

二、为什么需要锁?

问题场景

假设银行账户:余额 1000 元

时间 操作A(取钱500) 操作B(取钱800) 结果
10:00:00 读取余额=1000
10:00:01 读取余额=1000
10:00:02 计算 1000-500=500
10:00:03 计算 1000-800=200
10:00:04 写入余额=500
10:00:05 写入余额=200
10:00:06 ❌ 最终余额=200(多取了300!)

没有锁:两个操作互相干扰,数据错误!

有锁

text

复制代码
操作A:读取余额 → 加锁 → 处理 → 写回 → 释放锁
                    ↓
操作B:等待...等待...等待... → 读取新余额 → 处理 → 写回

三、锁的分类

3.1 按粒度分类

锁粒度 锁的范围 并发度 开销 适用场景
表锁 整张表 全表操作(如 ALTER TABLE)
行锁 某一行 OLTP 系统(如银行、电商)
页锁 某一页数据 中等 中等 某些数据库(如 SQL Server)

3.2 按模式分类

锁模式 英文 符号 含义
共享锁 Shared Lock S 读锁,多个事务可同时读,不能写
排他锁 Exclusive Lock X 写锁,只能一个事务读写,其他不能
意向锁 Intention Lock IS/IX 表示"准备加更细的锁",提高效率

3.3 兼容性矩阵

共享锁(S) 排他锁(X)
共享锁(S) ✅ 兼容(可同时读) ❌ 不兼容
排他锁(X) ❌ 不兼容 ❌ 不兼容

四、行锁 vs 表锁 详解

4.1 表锁

sql

复制代码
-- MySQL
LOCK TABLES emp READ;   -- 加表锁(共享锁)
SELECT * FROM emp;      -- 可以读
UPDATE emp SET sal=5000; -- ❌ 不能写(会阻塞)

UNLOCK TABLES;          -- 解锁

特点

  • 锁定整张表,简单粗暴

  • 适合批量操作(数据仓库、ETL)

  • Hive 主要使用表锁

4.2 行锁

sql

复制代码
-- MySQL InnoDB
BEGIN;
SELECT * FROM emp WHERE empno=7369 FOR UPDATE;  -- 只锁这一行
UPDATE emp SET sal=5000 WHERE empno=7369;
COMMIT;  -- 释放锁

特点

  • 只锁影响的行,其他行不受影响

  • 适合高并发 OLTP(银行、电商)

  • Oracle/MySQL InnoDB 默认使用行锁


五、乐观锁 vs 悲观锁

这是思想层面的分类,不是具体的锁实现。

类型 思想 做法 适用场景
悲观锁 "肯定有人跟我抢" 先加锁,再操作 并发高的场景
乐观锁 "应该没人跟我抢" 先操作,提交时检查 并发低的场景

5.1 悲观锁示例

sql

复制代码
-- MySQL 悲观锁
BEGIN;
SELECT * FROM products WHERE id=1 FOR UPDATE;  -- 加锁
UPDATE products SET stock=stock-1 WHERE id=1;
COMMIT;  -- 释放锁

5.2 乐观锁示例

sql

复制代码
-- 用版本号实现乐观锁
-- 1. 读取数据 + 版本号
SELECT stock, version FROM products WHERE id=1;  -- stock=10, version=5

-- 2. 更新时检查版本号
UPDATE products 
SET stock=9, version=6 
WHERE id=1 AND version=5;  -- 版本号匹配才更新

-- 3. 如果更新行数=0,说明被别人改过,重试

六、死锁

6.1 什么是死锁?

两个事务互相等待对方释放锁,谁也动不了。

text

复制代码
事务A:锁住了行1,等待行2
事务B:锁住了行2,等待行1
结果:两个都卡死!

6.2 死锁示例

sql

复制代码
-- 事务A
BEGIN;
UPDATE accounts SET balance=balance-100 WHERE id=1;  -- 锁住行1
UPDATE accounts SET balance=balance+100 WHERE id=2;  -- 等待行2

-- 事务B(同时执行)
BEGIN;
UPDATE accounts SET balance=balance-50 WHERE id=2;   -- 锁住行2
UPDATE accounts SET balance=balance+50 WHERE id=1;   -- 等待行1

-- 死锁!两个事务互相等待

6.3 如何避免死锁?

方法 说明
固定访问顺序 总是先更新 id 小的,再更新 id 大的
减少事务时间 尽快 COMMIT,不要有用户交互
使用超时 设置锁等待超时,超时后自动放弃
死锁检测 数据库自动检测,杀掉其中一个事务

七、Hive 中的锁

7.1 Hive 锁的特点

特点 说明
表级锁 Hive 主要使用表锁,不支持行锁
共享锁(S) 读取表时加,多个读操作可并发
排他锁(X) 写入表时加,阻塞其他读写
自动加锁 执行 SQL 时自动加,不需要手动

7.2 Hive 锁示例

sql

复制代码
-- 读操作 → 加共享锁
SELECT * FROM emp;  -- 自动加共享锁,允许其他读,禁止写

-- 写操作 → 加排他锁
INSERT INTO emp VALUES(9999,'张三','CLERK',...);  -- 自动加排他锁,阻塞其他操作

-- 查看锁
SHOW LOCKS;

-- 手动解锁(某些情况需要)
UNLOCK TABLE emp;

7.3 为什么 Hive 用表锁?

原因 说明
设计定位 数据仓库,不是高并发 OLTP
批量操作 每次处理大量数据,行锁意义不大
简单可靠 表锁简单,死锁概率低
HDFS 特性 HDFS 不支持行级修改

八、课堂笔记相关理解

你的课堂笔记中提到:

小文件过多导致跑批任务慢

这与锁的关系:

阶段 锁情况 说明
读取阶段 共享锁 多个任务可以同时读
写入阶段 排他锁 写任务会阻塞其他操作
合并文件 排他锁 小文件合并时需要独占表,导致其他任务等待

九、各数据库锁机制对比

数据库 默认锁粒度 支持行锁 死锁检测 适用场景
MySQL(InnoDB) 行锁 OLTP(高并发)
MySQL(MyISAM) 表锁 只读/低并发
Oracle 行锁 OLTP
PostgreSQL 行锁 OLTP
Hive 表锁 数据仓库
HBase 行锁 实时读写

十、总结

问题 答案
锁是什么? 控制多人同时访问同一数据的机制
为什么需要锁? 防止数据不一致(如银行取钱)
行锁 vs 表锁 行锁并发高,表锁简单
共享锁 vs 排他锁 共享锁可同时读,排他锁独占
乐观锁 vs 悲观锁 乐观锁假设没人抢,悲观锁假设有人抢
死锁 两个事务互相等待对方释放锁
Hive 用什么锁? 主要用表锁(共享锁/排他锁)

一句话记忆

锁就像厕所门锁:进去就锁上,别人得等;出来再打开,下一个才能进。


目的就是防止两个人同时用同一个数据搞乱账。

相关推荐
AOwhisky2 分钟前
学习自测与解析:Redis系列第一期与第二期核心知识点详解
运维·数据库·redis·学习·云计算
kishu_iOS&AI19 分钟前
LLM —— Milvmus向量数据库
数据库·人工智能·milvus
名不经传的养虾人23 分钟前
从0到1:企业级AI项目迭代日记 Vol.46|三个检索源、缓存限流、深度整合——联网检索一日冲刺
数据库·人工智能·agent·ai编程·ai工作流·企业ai
BugShare29 分钟前
Mac 上原生开发的开源免费、尽享丝滑数据库工具
数据库·macos·开源
Java爱好狂.29 分钟前
阿里1658页2026最新Java面试题总结(含答案)
数据库·redis·程序员·java面试·java面试题·java编程·java八股文
jieyucx44 分钟前
《Go 数据库编程开篇:彻底打通 database/sql 与 MySQL 驱动的连接池调优密码》
数据库·sql·golang
白露与泡影1 小时前
深入理解MySQL事务隔离级别:MVCC机制与Next-Key Lock如何解决幻读问题?
数据库·mysql
Gong-Yu1 小时前
MySQL数据库运维——性能优化进阶2️⃣
运维·数据库·mysql·性能优化
吴声子夜歌1 小时前
SQL经典实例——概述
数据库·sql