InnoDB中事务隔离级别和锁的关系
事务的四大特征
- 原子性A
- 一致性C
- 隔离性I
- 持久性D
并发事务带来的问题
- 脏读。
- 丢失修改
- 不可重复读
- 幻读
事务隔离级别
- 读未提交(Read uncommitted)RU
- 读提交(Read committed)RC
- 可重复读(Repeatable read)RR
- 可串行化(Serializable)
两段锁
- 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
- 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
事务中的加锁方式
Read-Committed(读取提交)
在RC级别中,数据的读取是不加锁的,数据的写入,修改和删除是加锁的,避免了脏读。
Repeatable Read(可重复读)
在RR级别中,通过MVCC机制,让数据变得可重复读。
Mysql如何避免幻读
在RR级别中,通过MVCC机制,虽然让数据变得可重复读,但我们读到的数据可能是历史数据,是不及时的数据,不是数据库当前的数据!这在一些对于数据的时效特别敏感的业务中,就很可能出问题。
- MySQL事务使用了Next-Key锁,Next-Key锁是行锁和GAP(间隙锁)的合并。
- 行锁可以防止不同事务版本的数据修改提交时造成数据冲突的情况。但如何避免别的事务插入数据就成了问题。
- RR级别中,事务A在update后加锁,事务B无法插入新数据,这样事务A在update前后读的数据保持一致,避免了幻读。这个锁,就是Gap锁,间隙锁。
- mysql,通过Innodb将数据分成几个个区间,每个区间就是一个间隙。
- (negative infinity, 5],
- (5,30],
- (30,positive infinity);
总结
行锁防止别的事务修改或删除,GAP锁防止别的事务新增,行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的幻读问题。
参考 or 转载自
https://tech.meituan.com/2014/08/20/innodb-lock.html