Photo by Lorem Ipsum
818 words
4 minutes
SQL 系列(二):事务与锁详解
SQL 教程
Posts in this series (10)AI 智能总结
SQL 2 事务与锁详解
事务与锁是数据库并发安全、数据一致性的核心,也是面试和开发的重中之重。本文精简讲解 ACID、事务隔离级别、各类锁机制、死锁原理,同时区分三大主流数据库的方言差异与底层实现区别。
一、事务 ACID 四大特性
所有关系型数据库理论特性完全一致,无语法差异,是事务的核心准则:
- 原子性(A):事务要么全部执行成功,要么全部回滚,不可部分执行。
- 一致性(C):事务执行前后,数据库数据完整性、约束规则不被破坏。
- 隔离性(I):多事务并发执行,互相隔离、互不干扰。
- 持久性(D):事务提交后,数据永久落地,宕机不丢失。
通用事务代码
START TRANSACTION; -- 开启事务UPDATE user SET age = 18 WHERE id = 1;COMMIT; -- 提交事务-- ROLLBACK; -- 回滚事务二、四大事务隔离级别
隔离级别解决脏读、不可重复读、幻读并发问题,定义标准通用,仅底层实现、默认级别不同。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交 | 允许 | 允许 | 允许 |
| 读已提交 | 禁止 | 允许 | 允许 |
| 可重复读 | 禁止 | 禁止 | 允许 |
| 串行化 | 禁止 | 禁止 | 禁止 |
数据库方言差异
- MySQL(InnoDB):默认可重复读,依靠 MVCC 解决大部分幻读问题
- Oracle / SQLServer:默认读已提交
三、数据库核心锁机制
1. 锁分类与原理
- 共享锁(S锁):读锁,共享不互斥,多事务可同时加读锁
- 排他锁(X锁):写锁,独占互斥,加写锁后其他事务无法读写
- 行锁:锁定单行数据,粒度小、并发高
- 表锁:锁定整张数据表,粒度大、并发低、开销小
2. 方言核心差异
- MySQL:InnoDB 支持行锁+表锁,行锁基于索引,无索引会降级为表锁
- Oracle:优先行级锁,极少触发表锁,锁粒度更精细
- SQLServer:锁机制最严格,会自动触发锁升级(多行行锁升级为表锁)
通用手动加锁示例(MySQL)
-- 加共享锁SELECT * FROM user WHERE id=1 LOCK IN SHARE MODE;-- 加排他锁SELECT * FROM user WHERE id=1 FOR UPDATE;四、死锁原理与特性
1. 死锁成因
两个及以上事务,互相持有对方需要的锁,且互相等待,无限阻塞,形成死锁。
2. 经典死锁场景
- 事务A持有行1锁,等待行2锁
- 事务B持有行2锁,等待行1锁
- 双方无限等待,程序卡死
3. 数据库方言差异
- MySQL:自带死锁检测机制,自动回滚代价最小的事务
- Oracle:无主动检测,依靠超时机制自动释放锁
- SQLServer:支持死锁监控,可自定义死锁牺牲策略
五、MVCC 核心差异(重点)
MVCC(多版本并发控制)是隔离级别实现的核心,仅 InnoDB、Oracle 支持:
- MySQL:MVCC 基于undo log + 事务ID,实现无锁读,适配可重复读隔离级别
- Oracle:MVCC 基于undo 回滚段,适配读已提交隔离级别
- SQLServer:无原生 MVCC,依靠锁机制实现隔离,并发性能偏弱
SQL 系列(二):事务与锁详解
https://fuwari.vercel.app/posts/sql-series/sql-02-transaction-locks/