一、MySQL的架构介绍

1.MySql简介

​ 概述:

2.MySQL逻辑架构介绍

2

1.Connectors

指的是不同语言中与SQL的交互

2 Management Serveices & Utilities:

系统管理和控制工具

3 Connection Pool: 连接池

管理缓冲用户连接,线程处理等需要缓存的需求。
负责监听对 MySQL Server 的各种请求,接收连接请求,转发所有连接请求到线程管理模块。每一个连接上 MySQL Server 的客户端请求都会被分配(或创建)一个连接线程为其单独服务。而连接线程的主要工作就是负责 MySQL Server 与客户端的通信,
接受客户端的命令请求,传递 Server 端的结果信息等。线程管理模块则负责管理维护这些连接线程。包括线程的创建,线程的 cache 等。

4 SQL Interface: SQL接口。

接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface

5 Parser: 解析器。

SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的,是一个很长的脚本。
在 MySQL中我们习惯将所有 Client 端发送给 Server 端的命令都称为 query ,在 MySQL Server 里面,连接线程接收到客户端的一个 Query 后,会直接将该 query 传递给专门负责将各种 Query 进行分类然后转发给各个对应的处理模块。
主要功能:
a . 将SQL语句进行语义和语法的分析,分解成数据结构,然后按照不同的操作类型进行分类,然后做出针对性的转发到后续步骤,以后SQL语句的传递和处理就是基于这个结构的。
b. 如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的

6 Optimizer: 查询优化器。

SQL语句在查询之前会使用查询优化器对查询进行优化。就是优化客户端请求的 query(sql语句) ,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果
他使用的是“选取-投影-联接”策略进行查询。
用一个例子就可以理解: select uid,name from user where gender = 1;
这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行gender过滤
这个select查询先根据uid和name进行属性投影,而不是将属性全部取出以后再进行过滤
将这两个查询条件联接起来生成最终查询结果

7 Cache和Buffer: 查询缓存。

他的主要功能是将客户端提交 给MySQL 的 Select 类 query 请求的返回结果集 cache 到内存中,与该 query 的一个 hash 值 做一个对应。该 Query 所取数据的基表发生任何数据的变化之后, MySQL 会自动使该 query 的Cache 失效。在读写比例非常高的应用系统中, Query Cache 对性能的提高是非常显著的。当然它对内存的消耗也是非常大的。
如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等

8 、存储引擎接口

存储引擎接口模块可以说是 MySQL 数据库中最有特色的一点了。目前各种数据库产品中,基本上只有 MySQL 可以实现其底层数据存储引擎的插件式管理。这个模块实际上只是 一个抽象类,但正是因为它成功地将各种数据处理高度抽象化,才成就了今天 MySQL 可插拔存储引擎的特色。
从图2还可以看出,MySQL区别于其他数据库的最重要的特点就是其插件式的表存储引擎。MySQL插件式的存储引擎架构提供了一系列标准的管理和服务支持,这些标准与存储引擎本身无关,可能是每个数据库系统本身都必需的,如SQL分析器和优化器等,而存储引擎是底层物理结构的实现,每个存储引擎开发者都可以按照自己的意愿来进行开发。
注意:存储引擎是基于表的,而不是数据库。

3.MySQL存储引擎

查看命令:

MyISAM和InnoDB区别:

2

image-20210629172838705

InnoDB四大特性

1、插入缓冲(insert buffer)

插入缓冲(Insert Buffer/Change Buffer):提升插入性能,change buffering是insert buffer的加强,insert buffer只针对insert有效,change buffering对insert、delete、update(delete+insert)、purge都有效

使用插入缓冲的条件:

  • 非聚集索引(辅助索引)

  • 非唯一索引

Change buffer是作为buffer pool中的一部分存在。Innodb_change_buffering参数缓存所对应的操作(update会被认为是delete+insert):

  • all: 默认值,缓存insert, delete, purges操作

  • none: 不缓存

  • inserts: 缓存insert操作

  • deletes: 缓存delete操作

  • changes: 缓存insert和delete操作

  • purges: 缓存后台执行的物理删除操作

innodb_change_buffer_max_size参数:控制使用的大小,默认25%,最大可设置50%,如果mysql实例中有大量的修改操作,可考虑增大该参数;

对满足插入缓存条件的插入,每一次的插入不是写到索引页中,而是:

  1. 会先判断插入的非聚集索引页是否在缓冲池中,如果在直接插入;

  2. 如果不在,则先放到insert buffer中,再按照一定的频率进行合并操作,再写会磁盘;

  3. 通常可以将多个插入合并到一个操作中,目的是为了减少随机IO带来的性能损耗;

这样通常能将多个插入合并到一个操作中,目的还是为了减少随机IO带来性能损耗

上面提过在一定频率下进行合并,那所谓的频率是什么条件

  1. 辅助索引页被读取到缓冲池中。正常的select先检查Insert Buffer是否有该非聚集索引页存在,若有则合并插入。

  2. 辅助索引页没有可用空间。空间小于1/32页的大小,则会强制合并操作。

  3. Master Thread 每秒和每10秒的合并操作。

insert buffer的数据结构是一颗B+树;

  • 全局只有一颗insert buffer B+树,负责对所有表的辅助索引进行insert buffer;

  • 这颗B+树放在共享表空间中,试图通过独立表空间ibd文件恢复表中数据时,往往会导致check table失败,因为表中的辅助索引中的数据可能还在insert buffer中,也就是共享表空间中,所以ibd文件恢复后,还需要repair table操作来重建表上所有的辅助索引;

2、二次写(double write)

  1. doublewrite缓存位于系统表空间的存储区域,用来缓存innodb的数据页从innodb buffer pool中flush之后并写入到数据文件之前;

  2. 当操作系统或数据库进程在数据页写入磁盘的过程中崩溃,可以在doublewrite缓存中找到数据页的备份,用来执行crash恢复;

  3. 数据页写入到doublewrite缓存的动作所需要的io消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入;

img

从上图可知:

  1. 内存中doublewrite buffer大小2M;物理磁盘上共享表空间中连续的128个页,也就是2个区(extent)大小同样为2M

  2. 对缓冲池脏页进行刷新时,不是直接写磁盘。流程:

  3. 通过memcpy()函数将脏页先复制到内存中的doublewrite buffer

  4. 通过doublewrite分两次,每次1M顺序的写入共享表空间的物理磁盘上。这个过程中,doublewrite页是连续的,因此这个过程是顺序的,所以开销并不大;

  5. 完成doublewrite页的写入后,再将doublewrite buffer中的页写入各个表空间文件中,此时写入是离散的,可能会较慢;

  6. 如果操作系统在第三步的过程中发生了崩溃,在恢复过程中,可以从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件中,再应用重做日志;

3、自适应hash索引(ahi)

innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,此索引成为热数据,建立hash索引以提升查询速度,此建立是自动建立哈希索引,故称为自适应哈希索引(adaptive hash index)。

该属性通过innodb_adapitve_hash_index开启,也可以通过—skip-innodb_adaptive_hash_index参数关闭

注意事项:

  • 自适应哈希索引会占用innodb buffer pool

  • 只适合搜索等值(=)的查询,对于范围查找等操作,是不能使用的

  • 极端情况下,自适应hash索引才有比较大的意义,可以降低逻辑读

4、预读(read ahead)

extent 定义:表空间(tablespace 中的一组 page)

InnoDB使用两种预读算法来提高I/O性能:线性预读(linear read-ahead)和随机预读(randomread-ahead)。

  • 线性预读:以extent为单位,将下一个extent提前读取到buffer pool中;

  • 随机预读:以extent中的page为单位,将当前extent中的剩余的page提前读取到buffer pool中;

线性预读一个重要参数:innodb_read_ahead_threshold,控制什么时间(访问extent中多少页的阈值)触发预读;

  • 默认:56,范围:0~64,值越高,访问模式检查越严格;

  • 没有该变量之前,当访问到extent最后一个page时,innodb会决定是否将下一个extent放入到buffer pool中;

随机预读说明:

  • 当同一个extent的一些page在buffer pool中发现时,innodb会将extent中剩余page一并读取到buffer pool中;

  • 随机预读给innodb code带来一些不必要的复杂性,性能上也不稳定,在5.5版本已经废弃,如果启用,需要修改变量:innodb_random_read_ahead为ON;

二、索引优化分析

1.索引简介

是什么?

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高校获取数据的数据结构。可以得到索引的本质:索引是数据结构。可以简单理解为”排好序的快速查找数据结构”。

结论:数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,
这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以文件形式存储在硬盘上。

优势:

通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗

劣势:

1.实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要占用空间的。

2.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如果对表INSERT,UPDATE和DELETE。因为更新表时,MySQL不仅要不存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

3.索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立优秀的索引,或优化查询语句。

mysql索引分类
1
2
3
4
5
单值索引:即一个索引只包含单个列,一个表可以有多个单列索引

唯一索引:索引列的值必须唯一,但允许有空值

复合索引:即一个索引包含多个列
基本语法:
1
2
3
4
5
6
7
8
9
10
创建:
1.CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length));
//如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定length。
2.ALTER mytable ADD [UNIQUE] INDEX [indexName] ON(columnname(length));

删除:
DROP INDEX [indexName] ON mytable;

查看:
SHOW INDEX FROM table_name\G
使用Alter命令:

2

mysql索引结构:
BTree:

B树(Balance Tree)是一种多路平衡查找树,他的每一个节点最多包含M个孩子,M就是B树的阶。M的大小取决于磁盘页的大小。

https://www.bilibili.com/video/BV1UJ411J7CU?p=2&spm_id_from=pageDriver

https://www.bilibili.com/video/BV1BK4y1X7Gp?from=search&seid=1872408051532032494

https://blog.csdn.net/whoamiyang/article/details/51926985

image-20210629183227536

B-树就是B树,中间的横线不是减号,所以不要读成B减树。

2

B+Tree

一个m阶的B+树具有如下几个特征:

1
2
3
4
5
6
7
8
9
10
11
1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

3.每个父节点的元素都同时存在于子节点中,是子节点中的最大(或最小)元素。

4.根节点的最大元素是整个B+树的最大元素。

5.由于父节点的元素都包含在子节点,因此所有叶子节点包括了全部的元素信息。

6.每个叶子节点都带有指向下一个节点的指针,形成一个有序链表。

2

B树索引:

2

B+树索引:

2

其中MyISAM和InnoDB存储引擎都采用B+树索引,但底层实现方式不同

InnoDB实现方式:其中叶子节点存储数据和键值即是原表中数据(聚集索引)

2

MyISAM实现方式:其中叶子节点存储键值和数据表中对应数据的物理地址(非聚集索引)

2

Hash索引:
1
2
3
4
5
6
7
1.只能使用=或<=>操作符的等式比较

2.优化器不能使用hash索引来加速order by操作

3.mysql不能确定在两个值之间大约有多少行。如果将一个myisam表改为hash索引的memory表,会影响一些查询的执行效率。

4.只能使用整个关键字来搜索一行

hash index是基于哈希表实现的,只有精确匹配索引所有列的查询才会生效。对于每一行数据,存储引擎都会对所有的索引列计算一个hash code,并将的有的hash code存储在索引中,同时在哈希表中保存指向每个数据行的指针。

2

哪些情况需要创建索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1.主键自动建立唯一索引

2.频繁作为查询的条件的字段应该创建索引

3.查询中与其他表关联的字段,外键关系建立索引

4.频繁更新的字段不适合创建索引

5.Where条件里用不到的字段不创建索引

6.单间/组合索引的选择问题,who?(在高并发下倾向创建组合索引)

7.查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度

8.查询中统计或者分组字段
哪些情况不要创建索引
1
2
3
4
5
1.表记录太少

2.经常增删改的表

3.数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。

2.性能分析

MySQL Query Optimizer

2

MySQL常见瓶颈:
1
2
3
4
5
CPU:CPU在饱和的时候一般发生在数据装入在内存或从磁盘上读取数据时候

IO:磁盘I/O瓶颈发生在装入数据远大于内存容量时

服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态

Explain

是什么(查看执行计划)
1
使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是结构的性能瓶颈
怎么玩
1
Explain+SQL语句
执行计划包含的信息

2

各个字段解释
id

select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
三种情况
id相同,执行顺序由上至下

2

id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行

2

id相同不同,同时存在

2

select_type

有哪些:

2

查询的类型,主要用于区别普通查询、联合查询、子查询等的复杂查询

1
2
3
4
5
6
7
8
9
10
11
1.SIMPLE:简单的select查询,查询中不包含子查询或者UNION

2.PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为

3.SUBQUERY:在SELECT或者WHERE列表中包含了子查询

4.DERIVED:在FROM列表中包含的子查询被标记为DERIVED(衍生)MySQL会递归执行这些子查询,把结果放 在临时表里。

5.UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外 层SELECT将被标记为:DERIVED

6.UNION RESULT:从UNION表获取结果的SELECT
table

显示这一行的数据是关于哪张表的

type

显示查询使用了何种类型
从最好到最差依次是:

1
system>con st>eq_ref>ref>range>index>ALL
1
2
3
4
5
6
7
8
9
10
11
12
13
system:表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也可以忽略不计

const:表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很 快。如将主键至于where列表中,MySQL就能将该查询转换为一个常量

eq_ref:唯一性索引,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描

ref:非唯一索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值的 行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体

range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引一般就是在你的where语句中出现了between、<、>、in等的查询这种范围扫描索引扫描比全表扫描要好,因为他只需要开始索引的某一点,而结束语另一点,不用扫描全部索引

index:Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据 文件小。(也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)

all:FullTable Scan,将遍历全表以找到匹配的行
possible_keys

显示可能应用在这张表中的索引,一个或多个。查询涉及的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用

key

实际使用的索引。如果为null则没有使用索引

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好key_len显示的值为索引最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的

ref

显示索引那一列被使用了,如果可能的话,是一个常数。那些列或常量被用于查找索引列上的值

rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数

Extra

包含不适合在其他列中显示但十分重要的额外信息

1
2
3
4
5
6
7
8
1.Using filesort:说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
MySQL中无法利用索引完成排序操作成为“文件排序”

2.Using temporary:使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by 和分组查询 group by

3.USING index:表示相应的select操作中使用了覆盖索引(Coveing Index),避免访问了表的数据行,效率不错!
如果同时出现using where,表明索引被用来执行索引键值的查找;
如果没有同时出现using where,表面索引用来读取数据而非执行查找动作。

覆盖索引(Covering Index):

2

1
2
3
4
5
6
7
8
9
10
11
4.Using where:表面使用了where过滤

5.using join buffer:使用了连接缓存

6.impossible where:where子句的值总是false,不能用来获取任何元组

7.select tables optimized away:在没有GROUPBY子句的情况下,基于索引优化MIN/MAX操作或者
对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,
查询执行计划生成的阶段即完成优化。

8.distinct:优化distinct,在找到第一匹配的元组后即停止找同样值的工作

3.索引优化

索引失效(应该避免)

1.全值匹配我最爱

2

2.最佳左前缀法则

2

3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描,这个意思是不能在where中做操作,但是可以在select中

2

4.存储引擎不能使用索引中范围条件右边的列

2

5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*

2

2

6.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描

2

7.is null,is not null 也无法使用索引

2

8.like以通配符开头(’$abc…’)mysql索引失效会变成全表扫描操作

2

​ 建立全文索引:https://blog.csdn.net/Samdy_Chan/article/details/78138420

如果要使用全值匹配,,但是又不想要索引失效,则对要匹配的值和要筛选的值建立索引,要符合索引覆盖。

9.字符串不加单引号索引失效

2

10.少用or,用它连接时会索引失效

2

11.小总结

2

2

一般性建议

1
2
3
4
5
6
7
对于单键索引,尽量选择针对当前query过滤性更好的索引

在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

在选择组合索引的时候,尽量选择可以能包含当前query中的where子句中更多字段的索引

尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

4.索引下推

https://blog.csdn.net/sinat_29774479/article/details/103470244

为什么范围查找索引回失效,后续索引回失效

作者:Limit
链接:https://www.zhihu.com/question/304037770/answer/1287557228
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

假设 表T1有字段a,b,c,d,e,其中a是主键,除e为varchar其余为int类型,并创建了一个联合索引idx_t1_bcd(b,c,d),然后b、c、d三列作为联合索引。Tip:基于InnoDB存储引擎。

imgimgT1表

联合索引:联合索引的所有索引列都出现在索引数上,并依次比较三列的大小。

imgimg联合索引B+树的结构

先看T1表,他的主键暂且我们将它设为整型自增的(PS:为什么是整型自增),InnoDB会使用主键索引在B+树维护索引和数据文件,然后我们创建了一个联合索引(b,c,d)也会生成一个索引树,同样是B+树的结构,只不过它的data部分存储的是联合索引所在行的主键值(上图叶子节点紫色背景部分)

对于联合索引来说只不过比单值索引多了几列,而这些索引列全都出现在索引树上。对于联合索引,存储引擎会首先根据第一个索引列排序,如上图我们可以单看第一个索引列,如,1 1 5 12 13…他是单调递增的;如果第一列相等则再根据第二列排序,依次类推就构成了上图的索引树,上图中的1 1 4 ,1 1 5以及13 12 4,13 16 1,13 16 5就可以说明这种情况。

联合索引的查找方式

当我们的SQL语言可以应用到索引的时候,比如

1
select * from T1 where b = 12 and c = 14 and d = 3;  

也就是T1表中a列为4的这条记录。存储引擎首先从根节点(一般常驻内存)开始查找,第一个索引的第一个索引列为1,12大于1,第二个索引的第一个索引列为56,12小于56,于是从这俩索引的中间读到下一个节点的磁盘文件地址,从磁盘上Load这个节点,通常伴随一次磁盘IO,然后在内存里去查找。当Load叶子节点的第二个节点时又是一次磁盘IO,比较第一个元素,b=12,c=14,d=3完全符合,于是找到该索引下的data元素即ID值,再从主键索引树上找到最终数据。

imgimg

三、查询截取分析

查询优化

永远小表驱动大表,类似嵌套循环Nested Loop

2

2

2

order by关键字优化

ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序

尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀

如果不在索引列上,filesort有两种算法:
mysql就要启动双路排序和单路排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
双路排序
1.MySQL4.1之前是使用双路排序,字面意思是两次扫描磁盘,最终得到数据。
读取行指针和orderby列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据传输
2.从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。
取一批数据,要对磁盘进行两次扫描,众所周知,I\O是很耗时的,所以在mysql4.1之后,出现了第二张改进的算法,就是单路排序。

单路排序
从磁盘读取查询需要的所有列,按照orderby列在buffer对它们进行排序,然后扫描排序后的列表进行输出,
它的效率更快一些,避免了第二次读取数据,并且把随机IO变成顺序IO,但是它会使用更多的空间,
因为它把每一行都保存在内存中了。

结论及引申出的问题
由于单路是后出来的,总体而言好过双路
但是用单路有问题

2

优化策略

增大sort_buffer_size参数的设置

增大max_length_for_sort_data参数的设置

2

小总结:

2

GROUP BY关键字优化
1
2
3
4
5
groupby实质是先排序后进行分组,遵照索引建的最佳左前缀

当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置

where高于having,能写在where限定的条件就不要去having限定了。

慢查询日志

是什么

2

日志分析工具mysqldumpslow

查看mysqldumpshow的帮助信息

2

批量数据脚本

往表里插入1000W数据

1.建表

2.设置参数log_trust_function_createors

2

3创建函数保证每条数据都不同

2

​ 随机产生字符串

​ 随机产生部门编号

4.创建存储过程

2

​ 创建往emp表中插入数据的存储过程

​ 创建往dept表中插入数据的存储过程

5.调用存储过程

Show profiles

是什么:
1
是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优测量

默认情况下,参数处于关闭状态,并保存最近15次的运行结果

分析步骤:

1.是否支持,看看当前的SQL版本是否支持

2

2.开启功能,默认是关闭,使用前需要开启

3.运行SQL

1
select * from emp group by id%10 limit 150000

4.查看结果,show profiles;

5.诊断SQL,show profile cpu,block io for query 上一步前面的问题SQL 数字号码;

2

2

6.日常开发需要注意的结论

1
2
3
4
5
6
7
converting HEAP to MyISAM 查询结果太大,内存都不够用了往磁盘上搬了。

Creating tmp table 创建临时表

Copying to tmp table on disk 把内存中临时表复制到磁盘,危险!!!

locked

全局查询日志

配置启用

2

编码启用

2

永远不要在生产环境开启这个功能。

四、MySQL锁机制

概述

https://blog.csdn.net/qq_44766883/article/details/105879308

锁的分类

从数据操作的类型(读、写)分:
1
2
3
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响

写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。
从对数据操作的颗粒度:
1
2
3
表锁

行锁

从程度上划分:

1
2
3
悲观锁

乐观锁

表锁(偏读)

特点

1
偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低

案例分析

建表SQL

2

加读锁

2

2

2

加写锁

2

2

案例结论

2

表锁分析

2

行锁(偏写)

特点

1
2
3
偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁

由于行锁支持事务,复习老知识

事务(Transation)及其ACID属性
并发事务处理带来的问题
1
2
3
4
5
6
脏读:(Dirty Reads):事务A读到了事务B已修改但尚未提交的数据,还在这个数据基础上做了操作,此时,如果						B事务回滚,A读取的数据无效,不符合一致性要求。
不可重复读(Non-Repeatable Reads):事务A读取到事务B已经提交的数据,不符合隔离性
幻读(Phantom Reads):事务A读取到事务B新增的数据


脏读和幻读的区别:脏读是事务B修改了数据,幻读是事务B新增了数据.
事务隔离级别

2

案例分析

建表SQL

2

行锁定基本演示

2

无索引行锁升级为表锁
1
varchar  不用 ' '  导致系统自动转换类型, 行锁变表锁
间隙锁危害

2

面试题:常考如何锁定一行

2

案例结论

2

行锁分析

2

优化建议

1
2
3
4
5
尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
合理设计索引,尽量缩小锁的范围
尽可能较少检索条件,避免间隙锁
尽量控制事务大小,减少锁定资源量和时间长度
尽可能低级别事务隔离

五、主从复制

复制的基本原理

1
slave会从master读取binlog来进行数据同步
三大步骤:
1
2
3
4
5
master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志时间,binary log events

slave将master的binary log ebents拷贝到它的中继日志(relay log

slave重做中继日志中的时间,将改变应用到自己的数据库中。MySQL复制是异步的且串行化的

2

复制的基本原则

1
2
3
4
5
每个slave只有一个master

每个slave只能有一个唯一的服务器ID

每个master可以有多个salve

复制最大问题

延时

六、参考资料

哔哩哔哩尚硅谷讲堂
哔哩哔哩图灵学院

github:java2020