目录

mysql架构介绍

Mysql简介

数据库排行榜:https://db-engines.com/en/ranking

什么是Mysql

  • MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。
  • Mysql 是开源的,可以定制的,采用了 GPL 协议,你可以修改源码来开发自己的 Mysql 系统。
  • MySQL 使用标准的 SQL 数据语言形式。
  • Mysql 可以允许于多个系统上,并且支持多种语言。这些编程语言包括 C、C++、Python、Java、Perl、PHP、 Eiffel、Ruby 和 Tcl 等。
  • MySQL 支持大型数据库,支持 5000 万条记录的数据仓库, 32 位系统表文件最大可支持 4GB,64 位系统支 持最大的表文件为 8TB。

Mysql重要知识点

  • 数据库内部结构和原理
  • 数据库建模优化
  • 数据库索引建立
  • SQL 语句优化
  • SQL 编程(自定义函数、存储过程、触发器、定时任务)
  • mysql 服务器的安装配置
  • 数据库的性能监控分析与系统优化
  • 各种参数常量设定
  • 主从复制
  • 分布式架构搭建、垂直切割和水平切割
  • 数据迁移
  • 容灾备份和恢复
  • shell 或 python 等脚本语言开发
  • 对开源数据库进行二次开发

Mysql安装

安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
1. 查看之前是否安装过mysql
brew list
2. 查看是否有mysql遗留文件
cd /usr/local/var
ls
如果有mysql文件夹则删除
3. 查看镜像源支持的版本
brew search mysql
4. 安装
brew install mysql
5. 配置环境变量
brew info mysql 直接复制粘贴 操作即可
6. 使用mysql
brew info mysql@5.6 按照指引去做

设置密码

设置密码有多种方式,可以使用mysql_secure_installation命令交互设置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
[root@server1 ~]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL

SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

In order to log into MySQL to secure it, we'll need the current

password for the root user. If you've just installed MySQL, and

you haven't set the root password yet, the password will be blank,

so you should just press enter here.

Enter current password for root (enter for none):# 初次运行直接回车

OK, successfully used password, moving on…

Setting the root password ensures that nobody can log into the MySQL

root user without the proper authorisation.

Set root password? [Y/n] # 是否设置root用户密码,输入y并回车或直接回车

New password: # 设置root用户的密码

Re-enter new password: # 再输入一次你设置的密码

Password updated successfully!

Reloading privilege tables..

… Success!

By default, a MySQL installation has an anonymous user, allowing anyone

to log into MySQL without having to have a user account created for

them. This is intended only for testing, and to make the installation

go a bit smoother. You should remove them before moving into a

production environment.

Remove anonymous users? [Y/n] # 是否删除匿名用户,生产环境建议删除,所以直接回车

… Success!

Normally, root should only be allowed to connect from 'localhost'. This

ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] # 是否禁止root远程登录,根据自己的需求选择Y/n并回车,建议禁止

… Success!

By default, MySQL comes with a database named 'test' that anyone can

access. This is also intended only for testing, and should be removed

before moving into a production environment.

Remove test database and access to it? [Y/n] # 是否删除test数据库,直接回车

- Dropping test database…

… Success!

- Removing privileges on test database…

… Success!

Reloading the privilege tables will ensure that all changes made so far

will take effect immediately.

Reload privilege tables now? [Y/n] # 是否重新加载权限表,直接回车

… Success!

Cleaning up…

All done! If you've completed all of the above steps, your MySQL

installation should now be secure.

Thanks for using MySQL!

之后需要设置密码才能进入

1
2
mysql -uroot -p
1234

查看mysql相关目录

1
ps -ef | grep mysql

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200929235810737.png

  • mysql数据库文件的存放路径

    1
    
    /usr/local/var/mysql
    
  • 配置文件目录

    1
    
    /usr/local/etc/my.cnf
    

    加载my.cnf位置顺序查看

    1
    2
    3
    
    mysql --verbose --help | grep my.cnf
    /etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf
    默认安装位置:/usr/local/mysql,其他3处都没有
    
  • 相关命令目录

    1
    
    /usr/local/opt/mysql@5.6/bin
    
  • 启停服务目录

    1
    
    /usr/local/Cellar/mysql@5.6/5.6.47/bin/mysqld
    

使用配置文件

1
2
3
cp /usr/local/opt/mysql@5.6/support-files/my-default.cnf /etc/my.cnf
# 之后修改这个文件即可
cp /usr/local/opt/mysql@5.6/support-files/my-default.cnf /etc/my.cnf

centos8上安装

参考:https://baijiahao.baidu.com/s?id=1663376869588187061&wfr=spider&for=pc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 列出指定软件包的可用modules
$ dnf module list mysql
Last metadata expiration check: 0:01:45 ago on 2020年09月29日 星期二 16时35分31秒.
CentOS-8 - AppStream
Name              Stream             Profiles                      Summary
mysql             8.0 [d]            client, server [d]            MySQL Module
# 安装指定版本的ysql
$ dnf module install mysql:8.0
# 查看安装结果,Profiles 列带[i]表示已安装
$ dnf module list mysql
Last metadata expiration check: 0:10:54 ago on 2020年09月29日 星期二 16时35分31秒.
CentOS-8 - AppStream
Name            Stream               Profiles                        Summary
mysql           8.0 [d][e]           client, server [d] [i]          MySQL Module
# 启动mysql
$ systemctl start mysqld
# 关闭mysql
$ systemctl stop mysqld
# 重启服务
$ systemctl restart mysqld
# 查看mysqld服务状态和启动日志
$ systemctl status mysqld
Active: inactive (dead)
# 启动之后查看进程
$ ps -ef | grep mysql
mysql       1093       1 12 02:08 ?        00:00:01 /usr/libexec/mysqld --basedir=/usr
# 查看端口号
$ lsof -i :3306
# 设置密码,注意先开启mysqld服务,然后交互操作即可,过程中不用安装密码check工具,low级别都要输入8个以上字符,12345678
# 123
$ mysql_secure_installation
# 客户端登录
$ mysql -uroot -p
12345678

mysql数据存储目录

1
$ show variables like '%dir%';

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930102628943.png

注:以上是5.5版本case,高版本有所改变,查看各目录可以按照如下步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 查看配置文件位置, /etc/mysql/my.cnf ~/.my.cnf 这两个不存在
$ mysql --verbose --help | grep my.cnf
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
# 查看/etc/my.cnf
$ cat /etc/my.cnf
!includedir /etc/my.cnf.d
$ cd /etc/my.cnf.d && ls
client.cnf  mysql-default-authentication-plugin.cnf  mysql-server.cnf
$ cat mysql-server.cnf
[mysqld]
datadir=/var/lib/mysql # 数据库文件存放路径
socket=/var/lib/mysql/mysql.sock # 本地连接时用的unix套接字文件
log-error=/var/log/mysql/mysqld.log # mysql错误日志路径
pid-file=/run/mysqld/mysqld.pid # 进程pid文件

卸载mysql8.0

参考:https://ipcmen.com/dnf

1
2
3
$ dnf remove mysql
$ dnf clean all
$ rm -rf /var/lib/mysql

docker安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 查看Linux服务器上是否安装过MySQL
rpm -qa | grep -i mysql # 查询出所有mysql依赖包

# 1、拉取镜像
docker pull mysql:5.7

# 2、创建实例并启动
docker run -p 3306:3306 --name mysql \
-v /tmp/mysql/log:/var/log/mysql \
-v /tmp/mysql/data:/var/lib/mysql \
-v /tmp/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=333 \
-d mysql:5.7

# 进入容器
docker start 9b
de 9b /bin/bash # 这种方式进去不能输入中文
# 系统使用的是POSIX字符集,POSIX字符集是不支持中文的,而C.UTF-8是支持中文的 只要把系统中的环境 LANG 改为"C.UTF-8"格式即可解决问题
# 使用以下方式
docker exec -it 9b env LANG=C.UTF-8 bash
# 此时通过docker进入mysql容器后,mysql控制台无法输入中文


# 服务启停
/etc/init.d/mysql start
/etc/init.d/mysql stop
/etc/init.d/mysql restart

# 3、mysql配置 新建/tmp/mysql/conf/my.cnf,将以下内容复制到my.cnf文件
[client]
#mysqlde utf8字符集默认为3位的,不支持emoji表情及部分不常见的汉字,故推荐使用utf8mb4
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
#设置client连接mysql时的字符集,防止乱码
init_connect='SET collation_connection = utf8_general_ci'
init_connect='SET NAMES utf8'

#数据库默认字符集
character-set-server=utf8mb4

#数据库字符集对应一些排序等规则,注意要和character-set-server对应
collation-server=utf8_general_ci

# 跳过mysql程序起动时的字符参数设置 ,使用服务器端字符集设置
skip-character-set-client-handshake

# 禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!
skip-name-resolve


# 4、重启mysql容器
docker restart mysql

# 5、进入到mysql容器
docker exec -it mysql /bin/bash

# 6、查看修改的配置文件
cat /etc/mysql/my.conf

Docker容器就是一个小型的Linux环境,进入到MySQL容器中。

1
docker exec -it mysql /bin/bash

Linux环境下MySQL的安装目录。

路径 解释
/var/lib/mysql MySQL数据库文件存放位置
/usr/share/mysql 错误消息和字符集文件配置
/usr/bin 客户端程序和脚本
/etc/init.d/mysql 启停脚本相关

MySQL5.7配置文件位置是/etc/my.cnf或者/etc/mysql/my.cnf,如果字符集不是utf-8直接进入配置文件修改即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[client]
#mysqlde utf8字符集默认为3位的,不支持emoji表情及部分不常见的汉字,故推荐使用utf8mb4
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
#设置client连接mysql时的字符集,防止乱码
init_connect='SET collation_connection = utf8_general_ci'
init_connect='SET NAMES utf8'

#数据库默认字符集
character-set-server=utf8mb4

#数据库字符集对应一些排序等规则,注意要和character-set-server对应
collation-server=utf8_general_ci

# 跳过mysql程序起动时的字符参数设置 ,使用服务器端字符集设置
skip-character-set-client-handshake

# 禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!
skip-name-resolve

注意:安装MySQL完毕之后,第一件事就是修改字符集编码。

数据初始化

1
2
3
4
5
mysql> create database db01;
mysql> use db01;
mysql> create table student( id int, name varchar(20) );
mysql> insert into student values( 1, '张三' );
mysql> alter table student add index idx_student_id(id);

字符集

如果中文乱码可以查看字符集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.02 sec)

utf8_general_ci 不区分大小写,这个你在注册用户名和邮箱的时候就要使用。 utf8_general_cs 区分大小写,如果用户名和邮箱用这个 就会照成不良后果 utf8_bin:字符串每个字符串用二进制数据编译存储。 区分大小写,而且可以存二进制的内容

utf8mb4: MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。

设置大小写不敏感

mysql命令行只是临时修改,my.cnf是永久修改

1
2
3
4
5
6
7
mysql> show variables like '%lower_case_table_names%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| lower_case_table_names | 0     |
+------------------------+-------+
1 row in set (0.06 sec)

/Users/david/Library/Application%20Support/typora-user-images/image-20200930125439347.png

注: lower_case_table_names只能在初始化服务器时配置,禁止在服务器初始化后更改设置,初始化后在my.inf中配置该参数会导致服务启动不了。可以在创建数据库时设置。

Mysql配置文件

Mysql8.0 配置详解

二进制日志log-bin

主从复制

MySQL Binlog 介绍

错误日志log-error

默认关闭,记录查询的sql语句,如果开启会减低mysql的整体性能,因为记录日志也是需要消耗系统资源的

慢查询日志log

默认关闭,记录查询的sql语句,如果开启会减低mysql的整体性能,因为记录日志也是需要消耗系统资源的

在这儿设置慢查询的阈值,3s以上就记录

数据文件

linux

默认路径:

1
/var/lib/mysql

看看当前系统中的全部库后再进去

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
➜  mysql pwd
/var/lib/mysql
➜  mysql ls -lF | grep ^d
drwxr-x--- 2 mysql mysql     4096 9月  30 05:21 db01/
drwxr-x--- 2 mysql mysql     4096 9月  30 03:38 #innodb_temp/
drwxr-x--- 2 mysql mysql     4096 9月  30 03:15 mysql/
drwxr-x--- 2 mysql mysql     4096 9月  30 03:15 performance_schema/
drwxr-x--- 2 mysql mysql     4096 9月  30 03:15 sys/
➜  mysql cd db01
➜  db01 ls
student.ibd

frm文件 存放表结构

myd文件 存放表数据

myi文件 存放表索引

mysql8.0取消了frm文件,元数据都存储到以.ibd为结尾的文件中


mysql5.7

MySQL配置文件讲解:https://www.cnblogs.com/gaoyuechen/p/10273102.html

1、二进制日志log-bin:主从复制。

1
2
3
# my,cnf
# 开启mysql binlog功能
log-bin=mysql-bin

2、错误日志log-error:默认是关闭的,记录严重的警告和错误信息,每次启动和关闭的详细信息等。

1
2
3
# my,cnf
# 数据库错误日志文件
log-error = error.log

3、查询日志log:默认关闭,记录查询的sql语句,如果开启会降低MySQL整体的性能,因为记录日志需要消耗系统资源。

1
2
3
4
# my,cnf
# 慢查询sql日志设置
slow_query_log = 1
slow_query_log_file = slow.log

4、数据文件。

  • frm文件:存放表结构。
  • myd文件:存放表数据。
  • myi文件:存放表索引。
1
2
3
4
5
6
$ cd /tmp/mysql/data/db01
$ ll
total 352
-rw-r-----  1 david  wheel    61B  9 30 15:03 db.opt
-rw-r-----  1 david  wheel   8.4K  9 30 15:05 student.frm
-rw-r-----  1 david  wheel   112K  9 30 15:05 student.ibd

MySQL5.7Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间。 共享表空间以及独立表空间都是针对数据的存储方式而言的。

  • 共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中,默认这个共享表空间的文件路径在data目录下。 默认的文件名为:ibdata1 初始化为10M
  • 独立表空间: 每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有一个.ibd文件。 其中这个文件包括了单独一个表的数据内容以及索引内容,默认情况下它的存储位置也是在表的位置之中。在配置文件my.cnf中设置: innodb_file_per_table

Mysql逻辑架构介绍

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930135129514.png

mysql设计,分层(4层架构),可拔插

可拔插组件式存储引擎,5.5以后默认都是innodb

和其它数据库相比, MySQL 有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在 存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可 以根据业务的需求和实际需要选择合适的存储引擎。

  • Connectors:指的是不同语言中与SQL的交互。
  • Connection Pool:管理缓冲用户连接,线程处理等需要缓存的需求。MySQL数据库的连接层。
  • Management Serveices & Utilities:系统管理和控制工具。备份、安全、复制、集群等等。。
  • SQL Interface:接受用户的SQL命令,并且返回用户需要查询的结果。
  • Parser:SQL语句解析器。
  • Optimizer:查询优化器,SQL语句在查询之前会使用查询优化器对查询进行优化。就是优化客户端请求query,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果。For Exampleselect uid,name from user where gender = 1;这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行gender过滤;然后根据uidname进行属性投影,而不是将属性全部取出以后再进行过滤。最后将这两个查询条件联接起来生成最终查询结果。
  • Caches & Buffers:查询缓存。
  • Pluggable Storage Engines存储引擎接口。MySQL区别于其他数据库的最重要的特点就是其插件式的表存储引擎(注意:存储引擎是基于表的,而不是数据库)。
  • File System:数据落地到磁盘上,就是文件的存储。

MySQL数据库和其他数据库相比,MySQL有点与众不同,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需求选择合适的存储引擎。

https://gitee.com/lienhui68/picStore/raw/master/null/20200930153013.png

各层介绍

连接层

最上层是一些客户端和连接服务,包含本地 sock 通信和大多数基于客户端/服务端工具实现的类似于 tcp/ip 的 通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证 安全接入的客户端提供线程。同样在该层上可以实现基于 SSL 的安全链接。服务器也会为安全接入的每个客户端验 证它所具有的操作权限。

服务层

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930140026563.png

引擎层

存储引擎层,存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 与存储引擎进行通信。不同 的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。

存储层

数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

Mysql存储引擎

查看命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 查看mysql现在已经提供什么存储引擎
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

# 查看mysql当前默认的存储引擎
mysql> show variables like '%storage_engine%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| default_storage_engine          | InnoDB    |
| default_tmp_storage_engine      | InnoDB    |
| disabled_storage_engines        |           |
| internal_tmp_mem_storage_engine | TempTable |
+---------------------------------+-----------+
4 rows in set (0.00 sec)

MyISAM和InnoDB

myisam偏读,innodb偏写

https://gitee.com/lienhui68/picStore/raw/master/null/20200930141152.png

阿里巴巴、淘宝用哪个

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930141505999.png

profile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 查看 profile 是否开启
mysql> show variables  like '%profiling%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| have_profiling         | YES   |
| profiling              | OFF   |
| profiling_history_size | 15    |
+------------------------+-------+
3 rows in set (0.05 sec)
# 如果没有开启,可以执行 set profiling=1 开启!
mysql> set profiling=1;
# 使用profile
# 执行 show prifiles 命令,可以查看最近的几次查询。
mysql> show profiles;
+----------+------------+------------------------------------+
| Query_ID | Duration   | Query                              |
+----------+------------+------------------------------------+
|        1 | 0.00184475 | show variables  like '%profiling%' |
+----------+------------+------------------------------------+
1 row in set, 1 warning (0.00 sec)
1
show profiles

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930212035001.png

根据 Query_ID,可以进一步执行 show profile cpu,block io for query Query_id 来查看 sql 的具体执行步骤。

1
show profile cpu,block io for query 164;

https://gitee.com/lienhui68/picStore/raw/master/null/image-20200930212204325.png

大致的查询流程

mysql 客户端通过协议与 mysql 服务器建连接,发送查询语句,先检查查询缓存,如果命中,直接返回结果, 否则进行语句解析,也就是说,在解析查询之前,服务器会先访问查询缓存(query cache)——它存储 SELECT 语句以及 相应的查询结果集。如果某个查询结果已经位于缓存中,服务器就不会再对查询进行解析、优化、以及执行。它仅 仅将缓存中的结果返回给用户即可,这将大大提高系统的性能。

语法解析器和预处理:首先 mysql 通过关键字将 SQL 语句进行解析,并生成一颗对应的“解析树”。mysql 解析 器将使用 mysql 语法规则验证和解析查询;预处理器则根据一些 mysql 规则进一步检查解析数是否合法。

查询优化器当解析树被认为是合法的了,并且由优化器将其转化成执行计划。一条查询可以有很多种执行方式, 最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。

然后,mysql 默认使用的 BTREE 索引,并且一个大致方向是:无论怎么折腾 sql,至少在目前来说,mysql 最多只用到表中的一个索引