个人博客


  • 基于MySQL8

1、并发事务带来的问题

  1. 脏读(Dirty read)
  2. 丢失修改(Lost to modify)
  3. 不可重复读(Unrepeatableread)
  4. 幻读(Phantom read)

2、事务隔离级别

  1. **READ-UNCOMMITTED(读取未提交)**:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  2. **READ-COMMITTED(读取已提交)**:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
  3. **REPEATABLE-READ(可重复读)**:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  4. **SERIALIZABLE(可串行化)**:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别脏读不可重复读幻影读updateinsert/delete备注
READ UNCOMMITTED
READ COMMITTED×
REPEATABLE READ×××mysql默认隔离级别也可以防止幻影读
SERIALIZABLE×××××所有事务按顺序进行可以防止丢失修改

在使用一些持久层框架时,同一个事务多次查询结果一致是因为缓存,而非可重复读的体现。

2.1、如何防止丢失修改

  1. SERIALIZABLE 设置该隔离级别会使CRUD所有操作影响的行数据带上锁(其它隔离级别只有update操作才会上锁),其它事务必须等待锁释放才可继续执行。
  2. 写锁 直接使用update table set xx=xx+1
  3. 悲观锁 在查询语句后面加上for update,适合update多于select操作。
  4. 乐观锁 在表中维护1个version字段,每次更新+1,如果该条记录version与查询时不一致则回滚当前操作避免丢失修改,适合select多于update操作。

2.2、查看事务隔离级别

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation;命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;

2.3、设置隔离级别

1
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

2.4、手动控制事务

  1. START TARNSACTION |BEGIN:显式地开启一个事务。
  2. COMMIT:提交事务,使得对数据库做的所有修改成为永久性。
  3. ROLLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。

参考链接