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

一句话记忆

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


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

相关推荐
东风破1371 小时前
DM达梦数据库安全、审计功能学习记录
数据库·学习·oracle·dm达梦数据库
JAVA学习通1 小时前
《大营销平台系统设计实现》 - 营销服务 第10节:不超卖库存规则实现
java·数据库·oracle·责任链模式·codex
ZC跨境爬虫1 小时前
跟着 MDN 学CSS day_7:(层叠优先级与继承)
前端·css·数据库·ui·html
YOU OU1 小时前
MyBatis 操作数据库(入门)
数据库·mybatis
电商API_180079052471 小时前
反向海淘是什么?现状如何?未来趋势如何?
数据库·人工智能·笔记·性能优化·数据挖掘·网络爬虫
MRSM_011 小时前
Redis 缓存、队列、排行榜的核心用法
数据库·redis·缓存
Trouvaille ~1 小时前
【Redis篇】Redis 安装与启动:快速搭建一个 Redis 环境
数据库·redis·后端·ubuntu·缓存·环境搭建·安装教程
fengxin_rou1 小时前
【Feed 高并发架构实战】:雪花 ID + 三级缓存 + 计数旁路设计详解
数据库·redis·缓存·架构·事务·并发
廿一夏10 小时前
MySql存储引擎与索引
数据库·sql·mysql