事务隔离级别
外观
事务隔离级别
事务隔离级别(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)
- 最高隔离级别
- 通过完全锁定相关数据避免所有并发问题
- 性能最差,但数据一致性最强
隔离级别对比表
隔离级别 | 脏读 | 不可重复读 | 幻读 | 并发性能 |
---|---|---|---|---|
读未提交 | 可能 | 可能 | 可能 | 最高 |
读已提交 | 不可能 | 可能 | 可能 | 高 |
可重复读 | 不可能 | 不可能 | 可能 | 中 |
串行化 | 不可能 | 不可能 | 不可能 | 低 |
代码示例
以下是在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是可串行化的。
其中冲突操作指至少有一个是写操作且访问同一数据项。
选择建议
选择隔离级别时应考虑:
- 数据一致性要求
- 系统并发需求
- 性能要求
一般建议:
- 对数据准确性要求高的系统(如金融)使用可重复读或串行化
- 对性能要求高且能容忍一定程度不一致的系统(如内容管理)使用读已提交
- 读未提交通常只用于统计分析等非关键场景
总结
事务隔离级别是数据库并发控制的核心概念,理解不同级别的特性和适用场景对设计可靠的数据系统至关重要。开发者应根据应用需求选择合适的隔离级别,在数据一致性和系统性能之间取得平衡。