mysql 事务隔离级别、索引与锁之间相互影响

前面的文章学习了索引、事务隔离级别和锁。这三者在不同组合下有不同的表现形式。

1、这里说的锁侧重于行锁,首先还是列下锁的几种类型

记录锁:X,REC_NOT_GAP

间隙锁:X,GAP

邻键锁:X

插入意向锁:INSERT_INTENTION

2、准备test表,其中id是主键,a列有唯一索引,b列普通索引,c列无索引。有以下值。

mysql> select * from test;
+----+------+------+------+
| id | a    | b    | c    |
+----+------+------+------+
|  0 |    0 |    0 |    0 |
| 10 |   10 |   10 |   10 |
| 20 |   20 |   10 |   10 |
| 30 |   30 |   30 |   30 |
| 40 |   40 |   40 |   40 |
| 50 |   50 |   50 |   50 |
RR可重复读隔离模式

主键索引

1、主键等值条件

select * from test where id=10 for update;

主键具有唯一性,对id=10加索引记录锁(X,REC_NOT_GAP)。

如果记录不存在select * from test where id=11 for udpate;会对当条件下一值加Next-Key Locks锁(X,GAP),锁定(10,20],防止其它事务插入id=11的值。

2、主键范围条件

select * from test where id>=30 for update;

对范围内的记录加X锁,防止其它事务对范围内数据修改。

对id=30加X,REC_NOT_GAP。对(30,40],(40,50],(50,supremum pseudo-record)加X锁。

唯一索引

1、等值条件

select * from test where a=10 for update;

会对唯一索引添加X,REC_NOT_GAP锁,同时对对应的主键索引加X,REC_NOT_GAP锁。

索引值不存在

select * from test where a=11 for update;

当前索引所在区间添加(10,20)间隙锁X,GAP。防止其它事务在当前唯一索引此区间添加记录

insert into test(id,a,b,c) values(2,11,11,11);获取X,GAP,INSERT_INTENTION会进入锁等待。

但是这里不会锁定主键,insert into test(id,a,b,c) values(2,2,11,11);可以执行。

2、范围条件

select * from test where a>=40 for update;

会对唯一索引添加X锁,锁定区间(30,40],(40,50],(50,supremum pseudo-record)。同时对唯一索引对应的主键索引添加X,REC_NOT_GAP锁。

普通索引

1、等值

mysql> select * from test where b=10 for update;
+----+------+------+------+
| id | a    | b    | c    |
+----+------+------+------+
| 10 |   10 |   10 |   10 |
| 20 |   20 |   10 |   10 |

会对普通索引对应值所在区间添加X锁,下一值区间添加X,GAP锁。实际锁定普通索引区间(0,10],(10,20)。也就是锁定当前值前后两个值中间部分,因为这两个区间都有可能插入=10的值

普通索引对应主键索引添加X,REC_NOT_GAP锁。

2、范围

select * from test where b>=40 for update;
+----+------+------+------+
| id | a    | b    | c    |
+----+------+------+------+
| 40 |   40 |   40 |   40 |
| 50 |   50 |   50 |   50 |

会对普通索引加X锁,锁定范围(30,40],(40,50],(50,supremum pseudo-record)。对应主键值添加X,REC_NOT_GAP索引。

无索引列

update test set c=1 where c=30;

锁全表

RC读提交隔离模式

设置会话隔离级别

set session transaction isolation level read committed;

这里不再一一演示,总结下结论就是:读提交隔离级别模式下没有间隙锁和Next-Key锁,只有记录锁。其它特点和RR隔离级别下一致。主键索引锁定对应条件内的所有主键索引值,唯一索引和普通索引除了锁定当前索引对应条件的索引,还会锁定其对应的主键索引。无索引的列会对对应条件主键索引添加记录锁

为什么读提交模式不需要间隙锁和Next-Key锁?

间隙锁和Next-Key锁的目的是在我当前事务加锁前提下,不允许其它事务变更(插入,修改,删除)我当前条件下任何数据。保证只有我加锁时点看到的这些。这里不禁限制了幻读和幻行,对现有的修改也不允许。这个在读已提交快照读模式下比较适用。

而对于读已提交,本身我就能读到其它事务在我事务逻辑过程中新提交的事务数据,本身就解决不了幻读和幻行问题,也不需要解决这个问题。我只需要锁定当前满足我条件的在库数据就可以了。

你可能感兴趣的:(mysql学习记录,mysql,数据库)