diff --git "a/note/MySQL/MYSQL\351\224\201.md" "b/note/MySQL/MYSQL\351\224\201.md" index a043627..9367e2d 100644 --- "a/note/MySQL/MYSQL\351\224\201.md" +++ "b/note/MySQL/MYSQL\351\224\201.md" @@ -24,13 +24,13 @@ 在这种情况下会发生`脏写`的问题,任何一种隔离级别都不允许这种问题的发生。所以在多个未提交事务相继对一条记录做改动时,需要让它们`排队执行`,这个排队的过程其实是通过锁来实现的。这个所谓的锁其实是一个`内存中的结构`,在事务执行前本来是没有锁的,也就是说一开始是没有`锁结构`和记录进行关联的,如图所示: -![image-20220328182710276](../../img/mysql/mysql锁//image-20220328182710276.png) +![image-20220328182710276](../../img/mysql/mysql锁/image-20220328182710276.png) 当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的`锁结构`,当没有的时候就会在内存中生成一个`锁结构`与之关联。比如,事务`T1`要对这条记录做改动,就需要生成一个`锁结构`与之关联: -![image-20220328182721374](../../img/mysql/mysql锁//image-20220328182721374.png) +![image-20220328182721374](../../img/mysql/mysql锁/image-20220328182721374.png) @@ -52,7 +52,7 @@ -![image-20220328182808108](../../img/mysql/mysql锁//image-20220328182808108.png) +![image-20220328182808108](../../img/mysql/mysql锁/image-20220328182808108.png) 小结几种说法: @@ -631,13 +631,13 @@ INSERT INTO student VALUES 记录锁也就是仅仅把一条记录锁上,官方的类型名称为:`LOCK_REC_NOT_GAP`。比如我们把id值为 8 的 那条记录加一个记录锁的示意图如图所示。仅仅是锁住了id值为 8 的记录,对周围的数据没有影响。 -![image-20220328185943202](../../img/mysql/mysql锁//image-20220328185943202.png) +![image-20220328185943202](../../img/mysql/mysql锁/image-20220328185943202.png) 举例如下: -![image-20220328185953649](../../img/mysql/mysql锁//image-20220328185953649.png) +![image-20220328185953649](../../img/mysql/mysql锁/image-20220328185953649.png) 记录锁是有S锁和X锁之分的,称之为`S型记录锁`和`X型记录锁`。 @@ -648,7 +648,7 @@ INSERT INTO student VALUES MySQL在`REPEATABLE READ`隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用`MVCC`方案解决,也可以采用加锁方案解决。但是在使用`加锁`方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些`幻影记录`加上`记录锁`。InnoDB提出了一种称之为`Gap Locks`的锁,官方的类型名称为:`LOCK_GAP`,我们可以简称为`gap锁`。比如,把id值为 8 的那条记录加一个gap锁的示意图如下。 -![image-20220328190138150](../../img/mysql/mysql锁//image-20220328190138150.png) +![image-20220328190138150](../../img/mysql/mysql锁/image-20220328190138150.png) 图中id值为 8 的记录加了gap锁,意味着`不允许别的事务在id值为 8 的记录前边的间隙插入新记录`,其实就是id列的值( 3 , 8 )这个区间的新记录是不允许立即插入的。比如,有另外一个事务再想插入一条id值为 4 的新记录,它定位到该条新记录的下一条记录的id值为 8 ,而这条记录上又有一个gap锁,所以就会阻塞插入操作,直到拥有这个gap锁的事务提交了之后,id列的值在区间( 3 , 8 )中的新记录才可以被插入。 @@ -907,7 +907,7 @@ InnoDB内部就不会有大量的死锁检测工作了。 InnoDB存储引擎中的锁结构如下: -![image-20220328191907367](../../img/mysql/mysql锁//image-20220328191907367.png) +![image-20220328191907367](../../img/mysql/mysql锁/image-20220328191907367.png) @@ -950,7 +950,7 @@ InnoDB存储引擎中的锁结构如下: 这是一个 32 位的数,被分成了lock_mode、lock_type和rec_lock_type三个部分,如图所示: - ![image-20220328192308086](../../img/mysql/mysql锁//image-20220328192308086.png) + ![image-20220328192308086](../../img/mysql/mysql锁/image-20220328192308086.png) @@ -1184,7 +1184,7 @@ insert into test values( 0 , 0 , 0 ),( 5 , 5 , 5 ), ##### 案例一:唯一索引等值查询间隙锁 -![image-20220328193145028](../../img/mysql/mysql锁//image-20220328193145028.png) +![image-20220328193145028](../../img/mysql/mysql锁/image-20220328193145028.png) 由于表 test 中没有 id=7 的记录 @@ -1304,7 +1304,7 @@ session A 是一个范围查询,按照原则 1 的话,应该是索引 id 上 由于c是普通索引,所以继续向右查找,直到碰到 (col1=15,id=15) 这一行循环才结束。根据优化 2 ,这是一个等值查询,向右查找到了不满足条件的行,所以会退化成 (col1=10,id=10) 到 (col1=15,id=15) 的间隙锁。 -![image-20220328194408224](../../img/mysql/mysql锁//image-20220328194408224.png) +![image-20220328194408224](../../img/mysql/mysql锁/image-20220328194408224.png) @@ -1329,7 +1329,7 @@ session A 的 delete 语句加了 limit 2 。你知道表 t 里 c=10 的记录 满足条件的语句已经有两条,循环就结束了。因此,索引 col1 上的加锁范围就变成了从( col1=5,id=5) 到( col1=10,id=30) 这个前开后闭区间,如下图所示: -![image-20220328194529282](../../img/mysql/mysql锁//image-20220328194529282.png) +![image-20220328194529282](../../img/mysql/mysql锁/image-20220328194529282.png) 这个例子对我们实践的指导意义就是, 在删除数据的时候尽量加 limit 。 @@ -1359,7 +1359,7 @@ select * from test where id>9 and id<12 order by id desc for update; 下图为这个表的索引id的示意图。 -![image-20220328194721419](../../img/mysql/mysql锁//image-20220328194721419.png) +![image-20220328194721419](../../img/mysql/mysql锁/image-20220328194721419.png) 1. 首先这个查询语句的语义是 order by id desc ,要拿到满足条件的所有行,优化器必须先找到 “ 第一个 id<12 的值 ” 。 2. 这个过程是通过索引树的搜索过程得到的,在引擎内部,其实是要找到 id=12 的这个值,只是最终没找到,但找到了 (10,15) 这个间隙。( id=15 不满足条件,所以 next-key lock 退化为了间隙锁 (10,15) 。) @@ -1406,7 +1406,7 @@ session A 的加锁范围是索引 col1 上的 (5,10] 、 (10,15] 、 (15,20] 通过这个操作, session A 的加锁范围变成了图 7 所示的样子: -![image-20220328194922739](../../img/mysql/mysql锁//image-20220328194922739.png) +![image-20220328194922739](../../img/mysql/mysql锁/image-20220328194922739.png)