网上关于事务和锁的理论知识文章非常丰富,但是每次看完总是很容易忘记,死记硬背也没什么意义,还不如实际操作一次,让自己印象更深刻。
此次实验准备了一张非常简单的表,数据库版本为5.7.x
1
2
3
4
5
create table user
(
id int,
name varchar(255)
)
首先从RC隔离级别开始,在RC级别下是只能读取到其他事务提交后的数据。
多事务读-写下,RC隔离等级未发生不可重复读,但是发生了幻读。那么在多事务写-写下的表现是怎么样的
先更新的事务获取到了锁,因此后更新的事务需等待锁的释放才可以更新成功,同时RC等级下insert是不会阻塞的
接下来观察RR等级下的表现,实验步骤和上面一模一样
可以看到没有出现幻读了,而其他表现与RC级别一致
接着来看锁相关的实验,事务隔离级别为RR,首先是表锁
表读锁会阻塞写,不会阻塞读,表写锁会阻塞读写。跟行锁里的共享锁(S)和排他锁(X)行为一致
然后是行锁,因为行锁输基于索引的,所以我们给id列加上索引
加锁的列为索引时
加锁的列不是索引
可以看到加的都是行锁,没有出现表锁,所以在加锁时如果索引失效导致对整张表加锁的情况下,用的还是行锁,只不过锁的范围说整张表
总结:锁的最终目的都是在并发下保证数据的正确性。MySQL使用的解决方案是读使用乐观锁(MVCC),写使用悲观锁(排他锁)