MySQL核心知识小结

MySQL基础架构了解嘛?能不能给我说一下一个SQL的执行过程。

**答:**在介绍MySQL架构前,我们不妨通过SQL执行过程了解一下整体步骤:

  1. 连接器:进行身份认证和权限校验。
  2. 查询缓存:建立连接后根据查询语句查看缓存中是否有数据,如果有就直接返回。注意,MySQL8.0取消了缓存。
  3. SQL解析:解析SQL语句,分析用户本条SQL要执行的操作,以及语法是否正确。
  4. 语句优化:按照MySQL认为最优的方式进行SQL优化。
  5. 执行:先判断用户是否具备权限,若有权限则通过存储引擎查询数据并返回。
  6. 存储引擎: 主要负责数据的存储和读取,采用的是插件式架构,常见的存储引擎有MyISAMInnoDBMemery等存储引擎。

在这里插入图片描述

MySQL支持哪些存储引擎?默认用哪个存储引擎知道嘛?

**答:**这一点我们可以通过下面这段命令查看:

show engines;

查询结果如下图所示,可以看到MySQL默认采用InnoDB作为存储引擎。而且InnoDB是唯一一个支持事务性存储的存储引擎。

在这里插入图片描述

嗯,那我怎么查看MySQL的版本呢?

答: 这个嘛,通过下面这段命令就可以知道了

select version(); 

可以看到笔者使用的MySQL版本是8

在这里插入图片描述

MySQL存储引擎架构了解嘛?

答: MySQL早起用的存储引擎就是MyISAM ,然后变成InnoDB,因为MySQL采用的是插件时存储引擎,所以存储引擎是可以任意切换的,注意存储引擎是针对表的,而不是针对某张数据库的。

如下面这个建表语句,我们就将存储引擎设置为innodb :

-- 测试脚本
drop table if exists `test`;
create table `test` (
    `id` bigint not null comment 'id',
    `name` varchar(50) comment '名称',
    `password` varchar(50) comment '密码',
    primary key (`id`)
) engine=innodb default charset=utf8mb4 comment '测试';

MyISAM和InnoDB有些那区别嘛?

答: 哦,那我先说说MyISAM:

  1. 它在性能方便是还行的,例如全文索引、压缩、空间函数等都没问题。
  2. 只支持表级锁。
  3. 不支持事务。
  4. 不支持故障后安全恢复。
  5. 正是因为不支持行级锁,所以就不支持mvcc了。
  6. MyISAM存储引擎数据和索引文件是分开。
  7. 不支持外键。

InnoDB

  1. 支持行级锁。
  2. 因为行级锁,所以支持mvcc
  3. 支持事务,所以并发读写的情况下性能优异。
  4. 同时支持故障后安全恢复(依赖redolog)
  5. 也支持外键,但是一般情况下我们不太建议开发数据表使用外键。
  6. 最后一点它索引和数据都在同一个文件上。

你刚刚说到mvcc,能不能给我讲讲这是什么?

碍于篇幅原因,可参考近期整理的这篇文章:

MySQL事务与并发控制详解

MyISAM和InnoDB如何选择呢?

答: 大部分情况下都建议使用InnoDB,很多人认为MyISAM性能要好于InnoDB,事实并非如此,在高性能MySQL中提及过:

不要轻易相信“MyISAM 比 InnoDB 快”之类的经验之谈,这个结论往往不是绝对的。在很多我们已知场景中,InnoDB 的速度都可以让 MyISAM 望尘莫及,尤其是用到了聚簇索引,或者需要访问的数据都可以放入内存的应用。


当然你要是不考虑并发性能以及崩溃后数据恢复等情况,可以使用MyISAM

MySQL 字段 char 和 varchar 的区别是啥,varchar(30)代表什么意思?(重点)

答: char定长,如果存储字符串小于char大小则使用空格填充,由于大小固定,所以查询效率比varchar50%,最多存放255字符,与编码无关。
varchar不定长,查询较慢,最多存放65535个字符。

需要了解的是varchar(30) 代表存30个字符,其中中文占3字节,所以30个字符要占用90字节。英文是1字节。

我们可以键入下面sql,这里补充一下char_length获取的字符长度,有几个字符长度就是多少,length算的是字节数,查看可以看到length('哈哈')为6,length('hh')2

select char_length('哈哈'),length('哈哈');
select char_length('hh'),length('hh'); 

MySQL查询缓存了解嘛?能不能给我介绍一下?

答:MySQL8.0之前是支持查询缓存的,查询缓存就是为了提高查询性能而诞生的。例如我们执行

select * from table where id=1;

如果开启了查询缓存,那么这一结果就会被缓存起来,下次我们在进行相同查询则会直接从结果中获取。

那我们如何开启查询缓存呢?

: 在my.cnf中加入下面这段配置即可

query_cache_type=1
query_cache_size=600000

那你知道缓存不命中的几个场景嘛?

答: 大抵有以下几种情况吧:

  1. 查询SQL一样,但是字符串大小写不一样。
  2. 查询的SQL涉及自定义函数、用户变量、临时表、MySQL库中的表等情况,压根就不会缓存数据。
  3. 一旦我们进行数据更新或者表结构调整的情况,那么缓存也会被清理掉。
  4. 缓存空间满了,会根据缓存回收算法去清空SQL缓存。

那你知道MySQL缓存有什么缺点嘛?

答: MySQL8.0移除查询缓存就说明这个机制根本很大的优势,如果我们开启缓存大量的查询都在缓存中,无论是维护还是移除都会带来很大的开销。所以如果你在MySQL5.0+使用缓存时,若希望某张表不进行缓存,就可以使用下面这样的SQL避免使用缓存

select sql_no_cache count(*) from usr;

MySQL事务

由于事务涉及知识较多,可以参考笔者写的这篇文章

http://t.csdn.cn/uBaUP

MySQL磁盘爆满了,要怎么解决呢?

答: 首先我们要知道磁盘爆满的原因:

数据量暴增

这就得多方面考虑了,为什么会暴增,暴增是否因为业务涉及不合理,我们是否可以从功能上进行优化。实在不行就只能扩容了。

日志

日志导致容量暴增基本就bin log或者error日志没有及时清理了,这种情况我们只能删除一些bin log即可了。

临时文件

数据库某些查询结果都会放在内存的,当内存空间不足时就会为查询结果生成一个临时文件,供用户使用。但是高并发+大量慢查询很可能导致这些临时文件未能及时清除进而出现容量爆满问题。

解决方式也很简单,首先找到临时文件的位置

show variables like 'tmpdir'

然后到达对应的位置将临时文件内容置空

echo '' >> host-xxxxx.log  

注意我们此时可能还需清除慢查询SQL,查看是否有time数据很大的慢查询

	SELECT id, `state`, user,host,time,`INFO` FROM information_schema.processlist where state IS NOT NULL  and state <> "" ORDER BY time desc;

如果有则杀掉

SELECT concat('kill ', id, ';') FROM information_schema.processlist where user = 'HispaceCMS' and  `COMMAND` = 'Query' and  state IS NOT NULL and state <> '' and DB is not null and time > 1000 ORDER BY time desc

知不知道MySQL中的count(*)、count(1)、count(列名)的区别

回答这个问题我们不妨做个实验,首先建立数据表

create table count_test(
	id int 
)


insert into count_test values(1);
insert into count_test values(2);
insert into count_test values(null);

然后键入以下SQL进行查询,可以看到前面两条不会忽略null值,最后count(列名)会忽略null值。

select count(*),count(1),count(id) from count_test;

而性能方便,如果有主键的话,count(列名)最优。如果没有主键索引且表中有多列的话,count(1)最优,如果表只有1列的话,count(*)最优。

一些常见的笔试题

MySQL查询系统时间的函数是

select sysdate();

请描述一下可以从哪几个方面进行数据库优化

  1. 用分片键(如果有涉及分库分表的话)
  2. 优化缓存:可以提高PGASGA分区大小等手段。
  3. 优化索引:建立索引方式可以参考上文。
  4. 优化SQL:尽可能让SQL走索引,不要用*触发没必要的回表操作。

请设计一张单科目的学生成绩表

drop table xx_score;
create table xx_score(
	id int ,
	socre float,
	level char(1)
);

insert into xx_score values (1,99,'A');
insert into xx_score values (2,94,'A');
insert into xx_score values (3,93,'A');
insert into xx_score values (4,92,'A');
insert into xx_score values (5,91,'A');
insert into xx_score values (6,89,'B');
insert into xx_score values (7,70,'C');
insert into xx_score values (8,71,'C');
insert into xx_score values (9,76,'C');
  1. 查询成绩大于平均成绩的学生人数。
select
	count(1)
from
	xx_score
where
	socre > (
	select
		avg(socre)
	from
		xx_score);

  1. 查询70分以上的学生人数,每10分一个区间。
select level,count(1) from xx_score group by level;

参考文献

MySQL常见面试题总结

看完这篇还不懂MySQL的MVCC机制算我输

MVCC 水略深,但是弄懂了真的好爽!

MySQL 数据库救火:磁盘爆满了,怎么办?

猜你喜欢

转载自blog.csdn.net/shark_chili3007/article/details/108188009