818 words
4 minutes
SQL 系列(二):事务与锁详解

AI 智能总结

SQL 2 事务与锁详解#

事务与锁是数据库并发安全、数据一致性的核心,也是面试和开发的重中之重。本文精简讲解 ACID、事务隔离级别、各类锁机制、死锁原理,同时区分三大主流数据库的方言差异与底层实现区别。

一、事务 ACID 四大特性#

所有关系型数据库理论特性完全一致,无语法差异,是事务的核心准则:

  1. 原子性(A):事务要么全部执行成功,要么全部回滚,不可部分执行。
  2. 一致性(C):事务执行前后,数据库数据完整性、约束规则不被破坏。
  3. 隔离性(I):多事务并发执行,互相隔离、互不干扰。
  4. 持久性(D):事务提交后,数据永久落地,宕机不丢失。

通用事务代码

START TRANSACTION; -- 开启事务
UPDATE user SET age = 18 WHERE id = 1;
COMMIT; -- 提交事务
-- ROLLBACK; -- 回滚事务

二、四大事务隔离级别#

隔离级别解决脏读、不可重复读、幻读并发问题,定义标准通用,仅底层实现、默认级别不同。

隔离级别脏读不可重复读幻读
读未提交允许允许允许
读已提交禁止允许允许
可重复读禁止禁止允许
串行化禁止禁止禁止

数据库方言差异#

  1. MySQL(InnoDB):默认可重复读,依靠 MVCC 解决大部分幻读问题
  2. 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 支持:

  1. MySQL:MVCC 基于undo log + 事务ID,实现无锁读,适配可重复读隔离级别
  2. Oracle:MVCC 基于undo 回滚段,适配读已提交隔离级别
  3. SQLServer:无原生 MVCC,依靠锁机制实现隔离,并发性能偏弱
SQL 系列(二):事务与锁详解
https://fuwari.vercel.app/posts/sql-series/sql-02-transaction-locks/
Author
Zero02
Published at
2025-04-08
License
CC BY-NC-SA 4.0