数据库锁机制:表锁、行锁(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 用什么锁? 主要用表锁(共享锁/排他锁)

一句话记忆

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


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

相关推荐
ClouGence3 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
先吃饱再说20 小时前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
Nturmoils20 小时前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
Databend1 天前
Agent 轨迹分析与归因的数据工程实践
大数据·数据库·agent
这个DBA有点耶1 天前
SQL改写进阶:标量子查询的“隐形代价”与消除实战
数据库·mysql·架构
smallyoung1 天前
数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南
数据库·mysql·postgresql
parade岁月1 天前
MySQL JOIN解析:朴实无华但食之有味
数据库·后端
用户3169353811831 天前
MySQL服务无法启动问题解决全记录
数据库
vivo互联网技术1 天前
从 10 分钟到 1 秒:ES 深度分页任意跳页的三轮优化实战
服务器·数据库·redis·elasticsearch·深度分页
倔强的石头_2 天前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库