mysql事务的隔离级别有四个。
- read uncommitted (读未提交) ,允许读取未事务未提交的数据,可能造成脏读,不可重复读,幻读等问题。
- read committed (读已提交),允许读取事务已经提交的数据,可以避免脏读,可能会造成 不可重复读,幻读等问题。
- repeatable read (可重复读) 在事务内对同一数据全部查询操作多次查询的结果是一致的。
- serializable (串行化) 把所有的操作串行化,后续的操作阻塞等候。
1. 什么是事务
事务在逻辑上是一个操作单元,要么全部执行,要么全部不执行。
事务最经典的例子就是操作转账,比如小林要给小明转账1000元,这个转账会涉及到两个关键的操作,小林的余额减少1000,小明的余额增加1000。这两个操作要么同时成功,要么同时失败,不允许单个的操作进行,这里我们就可以使用事务来进行处理。
2. 事务的特性 (ACID)
- 原子性: 事务最小的执行单元 ,不可分割 ,要么全部执行,要么全部不执行,在innoDB存储引擎中,主要通过undo log来实现的。
- 隔离性: 在并发环境中,事务之间的操作相互隔离,一个事务不会看到其他事务未提交的数据,在innoDB存储引擎中,事务的隔离性主要通过多版本并发控制(MVCC)和锁机制实现的。
- 持久性: 一旦事务提交成功,对数据库的修改是永久性的,即使系统崩溃或系统发生故障数据也不会丢失。在innoDB存储引擎中,事务的持久性主要是通过redo log(重写日志)来进行实现的。
- 一致性: 事务一致性指事务执行前后数据库状态必须保持一致。这意味着事务的执行不能破坏数据库的约束和完整性规则。在innoDB存储引擎中,事务的一致性主要通过ACID属性(原子性,隔离性,持久性,一致性)的实现来保证。
3. 并发事务带来的问题
- 脏读: 当一个事务在访问数据库并且对数据做出了修改,但是没有提交事务,这时其他事务也访问了这条数据,那么其他事务拿到的数据是未被提交的数据,也就是 脏数据 ,这种读取 脏数据 的情况也就是 脏读 。
- 修改丢失: 一个事务读取数据时,另外一个事务也读取数据,同时修改同一条数据,第一次修改被第二次修改覆盖的情况,我们称之为 修改丢失 。
- 不可重复读: 在一个事务内多次读取同一条数据,因为其他事务对数据的修改并且提交,导致的第一个事务多次读取数据值不同,这种情况称之为不可重复读。
- 幻读: 幻读和不可重复读类似,幻读是查询操作同一个查询语句查询出的数据条数不同,也是因为有其他事务进行了插入操作。
4. 事务的隔离级别
读取未提交(read-uncommitted): 最低的隔离级别,允许读取尚未提交的数据,可能造成 脏读 、不可重复读 、幻读。
读取已提交(read-committed): 允许读取并发事务已经提交的数据,可以避免 脏读 ,但是可能造成 不可重复读 、幻读。
可重复读(repeatable-read): 对同一字段多次读取的结果是一致的,除非本身修改,可以避免 脏读、不可重复读 但是可能造成幻读。
串行化(serializable): 事务的最高隔离级别,完全服从ACID 的隔离级别,所有的事务顺序执行,可以避免全部错误的发生。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读取未提交 | 是 | 是 | 是 |
读取已提交 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
串行化 | 否 | 否 | 否 |