背景
上一次我们了解mysql在事务隔离级别为可重复读的情况下,加锁的各种现象。

这次来看一下在读已提交级别下加锁的各种情况。
实验
主键索引
等值更新
命中
sql 代码:update lock_test set f_num = 0 where id = 10;

除了表意向排它锁之外,就加了主键的记录锁,这个和RR级别一样。
未命中
sql 代码:update lock_test set f_num = 0 where id = 11;

这和RR级别不一样了,除了表意向排它锁之外,没有任何锁。
范围更新
命中
sql 代码:update lock_test set f_num = 0 where id >= 5 and id <=15;

这次也和RR级别不一样,除了表意向排它锁、主键记录锁之外没有间隙锁。
未命中
sql 代码:update lock_test set f_num = 0 where id >= 5 and id <=7;
这次依旧和RR级别不一样,但是和等值主键查询未命中是一样的,除了表意向排它锁之外,没有任何锁。
唯一索引
等值更新
命中
sql 代码:update lock_test set f_num = 0 where f_uq = 10;

数据库加了表意向排它锁、唯一索引记录锁、主键记录锁。
未命中
sql 代码:update lock_test set f_num = 0 where f_uq = 11;
未命中时和主键更新是一样的,除了表意向排它锁之外,没有任何锁。
范围更新
命中
sql 代码:update lock_test set f_num = 0 where f_uq >= 5 and f_uq <=15;
和等值更新一样,数据库加了表意向排它锁、唯一索引记录锁、主键记录锁。
未命中
sql 代码:update lock_test set f_num = 0 where f_uq >= 5 and f_uq <=7;
和等值更新一样,除了表意向排它锁之外,没有任何锁。
普通索引
- 等值更新
update lock_test set f_num = 0 where f_index = 10;
范围更新
sql 代码:update lock_test set f_num = 0 where f_index >= 5 and f_index <=15;

命中的时候都会加表意向排它锁、普通索引记录锁、主键记录锁。在未命中时,除了表意向排它锁之外,没有任何锁。
无索引
sql 代码:update lock_test set f_num = 0 where f_num = 10;
sql 代码:update lock_test set f_num = 0 where f_num >= 5 and f_num <=15;

和RR级别有很大区别,无论是等值更新还是范围更新,在命中时,只加了主键记录锁。未命中时,除了表意向排它锁之外,没有任何锁。
总结

总结一下,RC和RR级别加锁上来看,RR的加锁比较复杂,不仅多了间隙锁、临键锁,而且在未命中时也会加一些锁来保证可重复读。RC就比较简单,找到记录就加记录锁,没找到就不加锁。
由此也可以看出,除非业务场景必须要用到可重复读特性,不然RC的性能比RR高很多。
另外,虽然在RC中不使用索引更新比使用索引(唯一索引或普通索引)更新加的锁要少(只加主键记录锁),但是在没有索引的情况下数据库需要全表扫描,性能反而会下降,所以并不建议无索引更新。