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

一句话记忆

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


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

相关推荐
倔强的石头_7 分钟前
MongoDB迁移的新选项:在金仓KES上,用SQL管理文档数据
数据库
loulanyue_15 分钟前
AI Agent记忆从不是向量库:Oracle拆解读写分离与记忆晋升门,终结无脑存聊天的伪智能——读Wojtek Pluta演讲
数据库·人工智能·oracle
曼岛_26 分钟前
[图解密码学]第5章 对称加密基础
java·数据库·密码学
Decay__33 分钟前
17_MySQL 监控体系构建 —— mysqld_exporter + Prometheus + Grafana 全栈实战
运维·数据库·sql·mysql·架构
ss27340 分钟前
不用向量库,我用 MySQL 跑通了蔬菜 RAG--基于 RuoYi-AI 的蔬菜种植知识库 + 智能咨询系统,普通开发机就能跑
数据库·人工智能·智慧农业·ruoyi·知识库·rag
Franciz小测测1 小时前
MySQL 增量备份实践:文件都在,为什么仍可能恢复失败?
数据库·mysql·binlog
2401_891409264 小时前
量化数据13:港股分钟K线、Level2逐笔Tick、十档盘口和港股通历史数据的批量提取
数据库
w-w0w-w10 小时前
SQL注入
网络·数据库·sql
tianyuanwo10 小时前
NetBox 数据库详解:当“关系型数据库”被装进一个网络运维的领域模型里
运维·数据库·netbox
一条泥憨鱼10 小时前
【计算机网络】短连接、长连接与连接池:从 TCP 握手到池化复用的完整链路
网络·数据库·网络协议·tcp/ip·计算机网络