MySQL原理学习知识汇总

1. MySQL中的锁 19篇

2. InnoDB存储引擎 35篇

3. MySQL学习笔记 285篇

总结

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


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


这是施加于索引记录间隙上的锁

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

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

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


记录锁 + 间隙锁 的组合,他锁定的是一个范围,并且锁定记录本身。也就是说,next key锁不是一个单独的锁,就我理解,它其实是一个概念,这个概念是由上面两个锁的概念组合而来的。有时候在开发的过程中,我们会发现在insert操作的时候,会锁定相邻的键,这就是一个next-key锁技术,

行锁防止别的事务修改或删除,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中的两种读操作


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

select * from table where id>10;


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

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使用的是意向锁。意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。

(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      互斥      互斥

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


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

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

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

什么叫做覆盖索引?

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

聚集索引(主键索引):

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

辅助索引(二级索引):

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

就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。

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

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

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

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

你可能感兴趣的:(MySQL原理学习知识汇总)