mvcc理解与解读
阅读贡献博客:
1、mvcc机制:https://blog.csdn.net/weixin_36380516/article/details/115291399
2、record lock锁机制:https://www.cnblogs.com/zhoujinyi/p/3435982.html
3、行锁和表锁理解:https://blog.csdn.net/nicajonh/article/details/78814987
4、mysql的八大锁:https://blog.csdn.net/Saintyyu/article/details/91269087
5、mysql的RR级别是否解决幻读:https://www.cnblogs.com/zxg-blog/p/15107808.html
6、间隙锁与临界锁:https://blog.csdn.net/weixin_39035120/article/details/105937400
当前读快照读的理解:
由于mvcc是保存了,历史版本和删除版本,利用这两个版本解决了不用加锁也可以实现可重复读的效果,所以在RR和RC的级别下读取的是历史数据,
并不是当前数据,故又称快照读
当使用:lock in share mode 或者for update 或 delete update insert等语句的时候,会强制刷新最新的数据,进行锁控制,故又称为当前读
结论:只有在当前读的情况下出现锁阻塞或者死锁的情况
1、行锁和表锁
在mysql 的 InnoDB引擎支持行锁,与Oracle不同,mysql的行锁是通过索引加载的,即是行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁。
表锁:不会出现死锁,发生锁冲突几率高,并发低。
行锁:会出现死锁,发生锁冲突几率低,并发高
解释:表锁是表级别的,事务A查询某张表的时候,事务B是无法对这张表进行加锁的,只能等待事务A把锁释放,事务B才能接着对表进行操作
结论:不会出现死锁,发生锁冲突几率高,并发低
解释:行锁是加在某条或者某个返回的记录上,且这些记录必须是通过索引加载的,当事务A对某条数据进行加锁,事务B可以对表的其他数据加锁,互不影响
结论:会出现死锁,发生锁冲突几率低,并发高
锁冲突:例如说事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)
注意:在同一个事务里,共享锁和排他锁是可以共存的,如下:
Start TRANSACTION; // 首先开启事务 单行执行 SELECT * FROM account_innodb lock in share mode; // 加上读锁 单行执行 update account_innodb set balance = 1000 // 数据已经被加上了读锁,但是这里能加写锁成功 单行执行
死锁:例如说两个事务,事务A锁住了1~5行,同时事务B锁住了6~10行,此时事务A请求锁住6~10行,就会阻塞直到事务B施放6~10行的锁,而随后事务B又请求锁住1~5行,事务B也阻塞直到事务A释放1~5行的锁。死锁发生时,会产生Deadlock错误
2、行锁的类型
行锁分 共享锁 和 排它锁。
共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
排它锁又称:写锁。当一个事务对某几行上写锁时,不允许其他事务写,也不允许读。更不允许其他事务给这几行上任何锁。包括写锁。
读锁:读锁是共享的,或者说是互不干涉的。多个客户端在同一时刻可以同时读取一个资源,而互不干扰
写锁:写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,只有这样才能保证在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。
3.行锁的实现
注意几点:
1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
2.两个事务不能锁同一个索引,例如:
事务A先执行: select math from zje where math>60 for update; 事务B再执行: select math from zje where math<60 for update; 这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞,但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。
3.insert ,delete , update在事务中都会自动默认加上排它锁。
会话1: begin; select math from zje where math>60 for update; 会话2: begin; update zje set math=99 where math=68; 阻塞...........
会话相当与用户
如上,会话1先把zje表中math>60的行上排它锁。然后会话2试图把math=68的行进行修改,math=68处于math>60中,所以是已经被锁的,会话2进行操作时,
就会阻塞,等待会话1把锁释放。当commit时或者程序结束时,会释放锁.
理解以上的锁,就可以阅读MVCC的文章:
mvcc:https://blog.csdn.net/weixin_36380516/article/details/115291399