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.丢失更新
一个事务的更新操作被另外一个事务的更新操作锁覆盖,从而导致数据不一致:
2. 脏读
在不同的事务下,一个事务读取到其他事务未提交的数据:
3. 不可重复读
在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致对同一条数据两次读到的结果不一致:
4.幻读
在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致第二次读取到第一次不存在数据,或第一次原本存在的数据,第二次却读取不到,就好像之前的读取是 “幻觉” 一样:
4.4 隔离级别想要解决以上问题,可以通过设置隔离级别来实现:InnoDB 支持以下四个等级的隔离级别,默认隔离级别为可重复读:
读未提交:在此级别下,一个事务中的修改,即便没有提交,对其他事务也是可见的。
读已提交:在此级别下,一个事务中的修改只有已经提交的情况下,对其他事务才是可见的。
可重复读:保证在同一个事务中多次读取同样数据的结果是一样的。
串行化:所有事务强制串行执行,由于已经不存在并行,所以上述所有并发问题都不会出现。
在每个级别下,并发问题是否可能出现的情况如下:
隔离级别 脏读 不可重复读 幻读读未提交(READ UNCOMMITTED) 可能出现 可能 可能
读已提交(READ COMMITTED) 不可能出现 可能 可能
可重复读(REPEATABLE READ) 不可能 不可能 可能
串行化(SERIALIZABLE) 不可能 不可能 不可能