当前位置: 首页 > 科技观察

InnoDB,为什么选择块插入?

时间:2023-03-14 19:13:00 科技观察

MySQL的InnoDB的细粒度行锁是它最吸引人的特性之一。但是,《InnoDB,5项***实践》所提到的,如果查询没有活动索引,也会退化为表锁。InnoDB的细粒度锁是在索引记录上实现的。1.InnoDB索引InnoDB索引中有两种索引,聚集索引(ClusteredIndex)和普通索引(SecondaryIndex)。InnoDB中的每张表都会有一个聚簇索引:(1)如果表定义了PK,那么PK就是聚簇索引;(2)如果表没有定义PK,那么第一个非空唯一列就是聚簇索引;(3)否则,InnoDB会创建一个hiddenrow-id作为聚集索引;为了描述方便,下面以PK来说明。索引的结构是B+树。B+树的细节这里就不展开了,只做几点总结:(1)在索引结构中,非叶子节点存放键,叶子节点存放值;(2)聚簇索引,叶子节点存放行记录(row);画外音:因此,InnoDB的索引和记录是放在一起的,而MyISAM的索引和记录是分开存放的。(3)普通索引,叶子节点存放PK的值;画外音:因此,InnoDB的普通索引其实会扫描两次:第一次,PK被普通索引找到;第二次,行记录被PK找到;索引结构,InnoDB/MyISAM的索引结构,如果有兴趣,我以后会写一篇详细的文章。例如,假设有一个InnoDB表:t(idPK,nameKEY,sex,flag);表中有4条记录:1、神剑、m、A3、zhangsan、m、A5、lisi、m、A9、wangwu、f、B可以看到:(1)第一张图片,idPK的聚簇索引,叶存储所有行记录;(2)第二张图,name上的commonindex,叶子存放PK的值;for:select*fromtwherename='shenjian';(1)会先在名称普通索引上查询PK=1;(2)然后在聚簇索引中查询(1,shenjian,m,A)的行记录;下面简单介绍一下InnoDB七种锁中剩下的三种:RecordLocksGapLocksNext-KeyLocks就是重复读(RR)。2、记录锁(RecordLocks)记录锁,即块索引记录,例如:select*fromtwhereid=1forupdate;它会锁定id=1的索引记录,以防止其他事务插入、更新和删除id=1这一行。需要注意的是:select*fromtwhereid=1;是快照读取(SnapShotRead),不加锁,在《InnoDB为什么并发高,读取快?》中有详细解释。3.GapLocks间隙锁,阻塞索引记录中的区间,或者第一条索引记录之前的范围,或者最后一条索引记录之后的范围。还是上面的例子,InnoDB,RR:t(idPK,nameKEY,sex,flag);表中有4条记录:1、shenjian,m,A3,zhangsan,m,A5,lisi,m,A9,wangwu,f,B,SQL语句select*fromtwhereidbetween8and15forupdate;会阻塞区间,防止插入其他事务id=10的记录。画外音:为什么要阻止id=10的记录被插入?如果插入成功,第一个事务执行相同的SQL语句,你会发现结果集中多了一条记录,也就是幻像数据。间隙锁的主要目的是防止其他事务在间隙中插入数据,造成“不可重复读”。如果事务的隔离级别降为ReadCommitted(RC),间隙锁会自动失效。4.Next-KeyLocksNext-KeyLocks是记录锁和间隙锁的组合。它的阻塞范围包括索引记录和索引区间。更具体地说,临时键锁会阻塞索引记录本身,以及索引记录之前的间隔。如果一个会话持有索引记录R的共享/排他锁,其他会话不能立即在R之前的区间内插入新的索引记录。画外音:原文说如果一个session在一个索引中的记录R上有共享锁或排它锁,那么另一个session不能在索引顺序中R之前的空隙中插入新的索引记录。还是上面的例子,InnoDB,RR:t(idPK,nameKEY,sex,flag);表中有4条记录:1,shenjian,m,A3,zhangsan,m,A5,lisi,m,A9,wangwu,f,BPK上的潜在keylocks为:(-infinity,1](1,3](3,5](5,9](9,+infinity]键锁的主要目的也是为了避免幻读(PhantomRead)。如果事务隔离级别降级为RC,键锁就会也失败了画外音:关于事务和幻读的隔离级别,之前的文章没有讲解,有兴趣的后面会详细介绍,今天的内容主要是关于InnoDB的索引和三种的概念锁的介绍,场景和例子也是最简单的场景和最简单的例子,InnoDB的锁跟索引类型和事务的隔离级别有关,还有更多更复杂更有趣的案例后面给大家介绍.5.总结(1)InnoDB的索引和行记录是存储在一起的,这一点与MyISAM不同;(2)InnoDB的clustered索引存储的是行记录,而普通索引存储的是PK,所以普通索引需要进行两次Query;(3)记录锁锁住索引记录;(4)Gaplock对区间进行加锁,防止区间被其他事务插入;(5)Proximitylock锁定索引记录+区间,防止幻读;