跳转到内容

事务隔离级别

来自代码酷
Admin留言 | 贡献2025年5月12日 (一) 00:24的版本 (Page update by admin bot)

事务隔离级别

事务隔离级别(Transaction Isolation Levels)是数据库管理系统(DBMS)中用于控制事务并发执行时相互影响程度的重要机制。它定义了多个事务同时访问数据库时,一个事务对其他事务的可见性规则,从而在数据一致性和并发性能之间取得平衡。

概述

在数据库系统中,多个事务并发执行可能导致以下问题(称为并发问题):

  • 脏读(Dirty Read):事务A读取了事务B未提交的修改。
  • 不可重复读(Non-repeatable Read):事务A多次读取同一数据,期间事务B修改了该数据,导致事务A前后读取结果不一致。
  • 幻读(Phantom Read):事务A多次执行同一查询,期间事务B插入或删除了符合查询条件的记录,导致事务A前后结果集不一致。

事务隔离级别通过限制这些现象的发生来保证数据一致性。SQL标准定义了4种隔离级别,按隔离强度从低到高排列如下:

四种标准隔离级别

1. 读未提交(Read Uncommitted)

  • 最低隔离级别
  • 允许事务读取其他事务未提交的修改(脏读)
  • 可能出现所有并发问题
  • 性能最高,但数据一致性最差

2. 读已提交(Read Committed)

  • 只允许读取已提交的数据(避免脏读)
  • 仍可能出现不可重复读和幻读
  • 是许多数据库的默认级别(如Oracle、PostgreSQL)

3. 可重复读(Repeatable Read)

  • 确保同一事务中多次读取同一数据结果一致(避免不可重复读)
  • 仍可能出现幻读
  • 是MySQL InnoDB的默认级别

4. 串行化(Serializable)

  • 最高隔离级别
  • 通过完全锁定相关数据避免所有并发问题
  • 性能最差,但数据一致性最强

graph LR A[读未提交] -->|允许脏读| B[读已提交] B -->|避免脏读| C[可重复读] C -->|避免不可重复读| D[串行化] D -->|避免幻读| E[最高一致性]

隔离级别对比表

隔离级别 脏读 不可重复读 幻读 并发性能
读未提交 可能 可能 可能 最高
读已提交 不可能 可能 可能
可重复读 不可能 不可能 可能
串行化 不可能 不可能 不可能

代码示例

以下是在MySQL中设置和查询事务隔离级别的示例:

-- 查询当前会话的隔离级别
SELECT @@transaction_isolation;

-- 设置全局隔离级别(需要管理员权限)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 设置当前会话的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 事务示例
START TRANSACTION;
-- 在此执行SQL操作
COMMIT;

实际案例

场景:银行转账系统

考虑两个并发事务: 1. 事务A:查询账户余额(1000元) 2. 事务B:从该账户转账200元(更新余额为800元)

在不同隔离级别下的表现:

  • 读未提交
 - 事务A可能在事务B提交前读取到800元(脏读)
 
  • 读已提交
 - 事务A不会读到未提交的修改
 - 但如果事务A再次查询,可能看到800元(不可重复读)
  • 可重复读
 - 事务A在整个事务中看到一致的1000元
 - 但如果执行范围查询(如"SELECT COUNT(*) WHERE balance > 500"),可能看到不同结果(幻读)
  • 串行化
 - 事务B会等待事务A完成,或反之,确保完全一致

数学表达

隔离级别可以用可串行化理论来描述。对于调度S,如果存在一个等价于某个串行调度的调度S',则称S是可串行化的。

Conflict(S){(pi,qj)|piTi,qjTj,ij,piqj冲突}

其中冲突操作指至少有一个是写操作且访问同一数据项。

选择建议

选择隔离级别时应考虑:

  • 数据一致性要求
  • 系统并发需求
  • 性能要求

一般建议:

  • 对数据准确性要求高的系统(如金融)使用可重复读串行化
  • 对性能要求高且能容忍一定程度不一致的系统(如内容管理)使用读已提交
  • 读未提交通常只用于统计分析等非关键场景

总结

事务隔离级别是数据库并发控制的核心概念,理解不同级别的特性和适用场景对设计可靠的数据系统至关重要。开发者应根据应用需求选择合适的隔离级别,在数据一致性和系统性能之间取得平衡。