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:
beginselect  math  from zje where math>60 for update;    

会话2:
beginupdate 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

 

posted @ 2022-06-29 11:05  xzlnuli  阅读(102)  评论(0编辑  收藏  举报