事务隔离级别详解

1. 事务并发问题

    1. 脏读(Dirty Read)

  • 定义:事务A读取了事务B未提交的数据,事务B回滚后,事务A读取的数据无效。

  • 示例

    -- 事务A
    UPDATE users SET balance = 500 WHERE id = 1; -- 未提交
    
    -- 事务B
    SELECT balance FROM users WHERE id = 1; -- 读取到500(脏数据)
    
    -- 事务A回滚后,事务B读到的数据无效。

 2.不可重复读(Non-Repeatable Read)

  • 定义:事务A多次读取同一数据,事务B在期间修改并提交了该数据,导致事务A前后读取结果不一致。

  • 示例

    -- 事务A
    SELECT balance FROM users WHERE id = 1; -- 结果为100
    
    -- 事务B
    UPDATE users SET balance = 200 WHERE id = 1; -- 提交
    
    -- 事务A再次读取
    SELECT balance FROM users WHERE id = 1; -- 结果为200(不一致)

3.幻读(Phantom Read)

  • 定义:事务A查询某个范围的数据,事务B在期间插入或删除符合该范围的数据,导致事务A两次查询结果的行数不同。

  • 示例

    -- 事务A
    SELECT * FROM users WHERE age > 18; -- 返回2行
    
    -- 事务B
    INSERT INTO users (id, age) VALUES (3, 20); -- 提交
    
    -- 事务A再次查询
    SELECT * FROM users WHERE age > 18; -- 返回3行(出现幻行)


2. 事务隔离级别

由低到高分为四个级别,解决的问题逐步严格:

隔离级别脏读不可重复读幻读实现机制性能
读未提交 (Read Uncommitted)❌ 允许❌ 允许❌ 允许无锁或读不加锁最高
读已提交 (Read Committed)✅ 避免❌ 允许❌ 允许行级共享锁(读时加锁,读完释放)
可重复读 (Repeatable Read)✅ 避免✅ 避免⚠️ 部分避免(如MySQL)快照读(MVCC) + Next-Key锁
串行化 (Serializable)✅ 避免✅ 避免✅ 避免表级锁或严格范围锁最低

3. 各隔离级别实现原理

   1.读未提交

  • 实现:不采用任何锁机制,直接读取最新数据(包括未提交的数据)。

  • 问题:所有并发问题均存在。

   2.读已提交

  • 实现(以Oracle为例):

    • 写操作:事务修改数据时加排他锁(X锁),直到事务结束。

    • 读操作:每次读取时获取共享锁(S锁),读完立即释放。

  • 示例

    -- 事务A修改数据(加X锁)
    UPDATE users SET balance = 500 WHERE id = 1;
    
    -- 事务B读取时需等待事务A释放X锁,避免脏读。

   3.可重复读

  • 实现(以MySQL的InnoDB为例):

    • MVCC(多版本并发控制):为每个事务生成数据快照,保证多次读取一致性。

    • Next-Key锁:行锁 + 间隙锁,防止其他事务在范围内插入新数据(解决幻读)。

  • 示例

    -- 事务A首次读取(生成快照)
    SELECT * FROM users WHERE age > 18; -- 返回2行
    
    -- 事务B插入新数据(被Next-Key锁阻塞)
    INSERT INTO users (id, age) VALUES (3, 20); -- 等待
    
    -- 事务A再次读取(仍为2行)
    SELECT * FROM users WHERE age > 18;

  4.串行化

  • 实现:所有操作按顺序执行,通过表级锁或严格的范围锁实现。

  • 问题:并发性能极低,仅适用于低并发场景。


4. 数据库实现差异

   1.MySQL(InnoDB引擎)

  • 默认隔离级别:可重复读(Repeatable Read)。

  • 幻读处理:通过Next-Key锁避免幻读。

   2.Oracle / PostgreSQL

  • 默认隔离级别:读已提交(Read Committed)。

  • 幻读处理:在可重复读级别下仍可能出现幻读,需升级到串行化。

   3.SQL Server

  • 默认隔离级别:读已提交(Read Committed)。

  • 支持快照隔离级别(Snapshot Isolation):类似MVCC,避免不可重复读和幻读。


5. 隔离级别设置
  1. SQL语句设置

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

      2.JDBC连接设置(Java示例): 

Connection conn = dataSource.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

       3.Spring框架配置

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void updateUser() {
    // 业务逻辑
}

6. 实际应用建议
  • 读已提交:适用于多数OLTP场景,平衡性能与一致性。

  • 可重复读:需要事务内多次读取一致的场景(如对账系统)。

  • 串行化:仅用于关键数据(如金融交易),确保绝对一致。


总结:事务隔离级别通过锁机制或MVCC解决并发问题,需根据业务需求与数据库特性选择。理解不同级别的行为差异,是设计高并发系统的关键基础。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值