美文网首页MySQL
MySQL原理学习知识汇总

MySQL原理学习知识汇总

作者: 小超_8b2f | 来源:发表于2021-07-23 17:28 被阅读0次

    1. MySQL中的锁 19篇

    2. InnoDB存储引擎 35篇

    3. MySQL学习笔记 285篇

    总结

    行级锁
    • 共享锁(S锁)
    • 排他锁(X锁)

    \color{red}{1. 记录锁record lock}
    即索引的记录锁,他建立在索引记录上,很多时候,扫描一个表,如果没有索引,往往会导致整个表被锁住,建立合适的索引可以防止扫描整个表。

    \color{red}{2. 间隙锁gap lock}
    这是施加于索引记录间隙上的锁

    1、间隙锁锁定的是某个索引记录之前和之后的一个间隙范围。
    2、间隙锁之间互不影响,可以在锁定的区间再次添加间隙锁。
    3、间隙锁可能造成死锁
    4、间隙锁是在RR隔离级别下特有的
    5、间隙锁只影响一般索引,对于唯一索引和主键,情况有些许不同,下篇文章我们会着重分析。

    当字段是唯一索引或者主键的时候,间隙锁产生的规则如下:

    1. 如果查询的结果中包含这个记录,那么在另外的会话上插入该记录前后间隙的记录时,不会产生间隙锁
    2. 如果查询的结果中不包含这个记录,那么在另外的会话上插入该记录前后间隙的记录时,会产生间隙锁。

    \color{red}{3. next-key(临键)锁}
    记录锁 + 间隙锁 的组合,他锁定的是一个范围,并且锁定记录本身。也就是说,next key锁不是一个单独的锁,就我理解,它其实是一个概念,这个概念是由上面两个锁的概念组合而来的。有时候在开发的过程中,我们会发现在insert操作的时候,会锁定相邻的键,这就是一个next-key锁技术,\color{red}{MySQL用这个技术来避免“幻读”。}

    行锁防止别的事务修改或删除,GAP锁防止别的事务新增,行锁和GAP锁的结合形成的Next-Key锁共同解决了RR级别在写数据时的幻读问题。

    幻读

    事务发现莫名地多了一条或多数据,而且没有被之前的update语句所修改。

    行级锁的优点有:

    1.在很多线程中访问不同的行时只存在少量锁定冲突;
    2.回滚时只有少量的更改;
    3.可以长时间锁定单一的行;
    需要注意的是,innodb中的锁定技术往往是基于索引来实现的,如果我们的SQL语句中没有利用到索引,那么innodb将会执行一个全表扫描,锁定所有的行。而锁定过多的行往往又会导致问题,就是锁之间的竞争激烈,降低了并发率,所以建立合适的索引是很重要的,innodb需要索引来过滤那些不需要访问的行。

    MySQL中获得读取锁的SQL语法:

    1共享锁:  SELECT ... LOCK IN SHARE MODE 
    2排它锁:  SELECT ... FOR UPDATE
    

    没有索引的表,在进行获取排它锁的时候,会锁定整个表的所有记录。查询条件若有类型转换,则不走索引,全表扫描。


    当我们对数据库中的表进行select、update、delete以及insert的时候,innodb存储引擎会根据操作类型的不同来给这些操作添加具体的锁。

    MySQL中的两种读操作

    \color{red}{快照读:}
    读取的是记录的可见版本 (有可能是历史版本),不用加锁。简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)

    select * from table where id>10;
    

    \color{red}{当前读:}
    读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。

    select * from table where id>10 lock in share mode; 
    select * from table where id>10 for update;  
    insert into table values (…);
    update table set id=11 where id=10;
    delete from table where id>10;
    

    读取之后,需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句明确指出了lock in share mode之外,也就是对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。

    一致性非锁定读

       一致性非锁定读是指innodb通过行记录的多版本控制来读取当前执行时间数据库中行的数据,如果读取的行正在执行delete或者update操作,则会读取一个该行记录的一个快照数据。

    select * from table where id>10;
    

    一致性锁定读

    读取的就是当前数据的真实内容,它需要在读取的时候给记录进行上锁(必须在事务里面才管用,才能获得锁)

    select * for update(X锁定)
    select * lock in share mode(S锁定)
    

    意向锁(Intention Locks)

    InnoDB支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,实际应用中,InnoDB使用的是意向锁。意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。
    \color{red}{意向锁特点}
    (1)首先,意向锁,是一个表级别的锁(table-level locking);
    (2)意向锁分为:
    意向共享锁(intention shared lock, IS),它预示着,事务有意向对表中的某些行加共享S锁
    意向排它锁(intention exclusive lock, IX),它预示着,事务有意向对表中的某些行加排它X锁
    举个例子:

    select ... lock in share mode,要设置IS锁;
    select ... for update,要设置IX锁;
    

    (3)意向锁协议(intention locking protocol)并不复杂:
    事务要获得某些行的S锁,必须先获得表的IS锁
    事务要获得某些行的X锁,必须先获得表的IX锁
    (4)由于意向锁仅仅表明意向,它其实是比较弱的锁,意向锁之间并不相互互斥,而是可以并行,其兼容互斥表如下:

            IS          IX
    IS      兼容      兼容
    IX      兼容      兼容
    

    (5)额,既然意向锁之间都相互兼容,那其意义在哪里呢?它会与共享锁/排它锁互斥,其兼容互斥表如下:

              S          X
    IS      兼容      互斥
    IX      互斥      互斥
    

    画外音:排它锁是很强的锁,不与其他类型的锁兼容。这也很好理解,修改和删除某一行的时候,必须获得强锁,禁止这一行上的其他并发,以保障数据的一致性。

    \color{red}{插入意向锁}
    插入意向锁是一种间隙锁,专门针对的是数据行的插入操作,多个事务插入相同的索引间隙时,只要不是插入到相同的位置,则不需要进行锁等待。

    假设有索引记录的值分别是4和7,单独的事务分别尝试插入5和6,在获得插入行的排它锁之前,每个事务都是用插入意图锁来锁定4和7之间的空间,但是不会相互阻塞。因为行级别是没有冲突的。

    简单理解就是插入意向锁锁定了索引之间的间隙,但是插入意向锁之间没有互相阻塞。

    什么叫做覆盖索引?

    在了解覆盖索引之前我们先大概了解一下什么是聚集索引(主键索引)和辅助索引(二级索引)

    聚集索引(主键索引):

    聚集索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的记录数据。
    聚集索引的叶子节点称为数据页,聚集索引的这个特性决定了索引组织表中的数据也是索引的一部分。

    辅助索引(二级索引):

    非主键索引,叶子节点=键值+书签。Innodb存储引擎的书签就是相应行数据的主键索引值。
    再来看看什么是覆盖索引,有下面三种理解:

    \color{red}{解释一:} 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。

    \color{red}{解释二:} 索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫 做覆盖索引。

    \color{red}{解释三:} 是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。

    不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引

    当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息

    相关文章

      网友评论

        本文标题:MySQL原理学习知识汇总

        本文链接:https://www.haomeiwen.com/subject/pkdpmltx.html