详解 MySQL 面试核心知识点 (4)

Gap Lock:间隙锁,锁定一个范围,但不包括记录本身,主要用于解决幻读问题,示例如下:

-- 利用间隙锁可以阻止其他事务将值15插入列 t.c1 SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;

Next-Key Lock:等价于 行锁+间隙锁,既锁定范围,也锁定记录本身。可以用于解决幻读中的 ”当前读“ 的问题。

四、事务 4.1 ACID 定义

InnoDB 存储引擎完全支持 ACID 模型:

1. 原子性(Atomicity)

事务是不可分割的最小工作单元,事务的所有操作要么全部提交成功,要么全部失败回滚,不存在部分成功的情况。

2. 一致性(Consistency)

数据库在事务执行前后都保持一致性状态,数据库的完整性没有被破坏。

3. 隔离性(Isolation)

允许多个并发事务同时对数据进行操作,但一个事务所做的修改在最终提交以前,对其它事务是不可见的。

4. 持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使宕机等故障,也不会丢失。

4.2 事务的实现

数据库隔离性由上一部分介绍的锁来实现,而原子性、一致性、持久性都由 undo log 和 redo log 来实现。

undo log:存储在 undo 表空间或全局临时表空间的 undo 日志段 (segment) 上,用于记录数据修改前的状态,主要用于帮助事务回滚以及实现 MVCC 功能 (如一致性非锁定读)。

redo log:负责记录数据修改后的值,主要用于保证事务的持久化。

4.3 并发问题

在并发环境下,数据的更改通常会产生下面四种问题:

1.丢失更新

一个事务的更新操作被另外一个事务的更新操作锁覆盖,从而导致数据不一致:

https://github.com/heibaiying

2. 脏读

在不同的事务下,一个事务读取到其他事务未提交的数据:

https://github.com/heibaiying

3. 不可重复读

在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致对同一条数据两次读到的结果不一致:

https://github.com/heibaiying

4.幻读

在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致第二次读取到第一次不存在数据,或第一次原本存在的数据,第二次却读取不到,就好像之前的读取是 “幻觉” 一样:

https://github.com/heibaiying

4.4 隔离级别

想要解决以上问题,可以通过设置隔离级别来实现:InnoDB 支持以下四个等级的隔离级别,默认隔离级别为可重复读:

读未提交:在此级别下,一个事务中的修改,即便没有提交,对其他事务也是可见的。

读已提交:在此级别下,一个事务中的修改只有已经提交的情况下,对其他事务才是可见的。

可重复读:保证在同一个事务中多次读取同样数据的结果是一样的。

串行化:所有事务强制串行执行,由于已经不存在并行,所以上述所有并发问题都不会出现。

在每个级别下,并发问题是否可能出现的情况如下:

隔离级别 脏读 不可重复读 幻读
读未提交(READ UNCOMMITTED)   可能出现   可能   可能  
读已提交(READ COMMITTED)   不可能出现   可能   可能  
可重复读(REPEATABLE READ)   不可能   不可能   可能  
串行化(SERIALIZABLE)   不可能   不可能   不可能  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxpfg.html