目录

mysql是怎么运行的笔记

服务器层次划分

为了管理方便,人们把连接管理、查询缓存、语法解析、查询优化这些并不涉及真实数据存储的功能划分为MySQL server的功能,把真实存取数据的功能划 分为存储引擎的功能。

缓存

如果两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中。另外,如果查询 请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql 、information_schema、 performance_schema 数据库中的表,那这个请求就不 会被缓存。

既然是缓存,那就有它缓存失效的时候。MySQL的缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使用了INSERT、 UPDATE、DELETE、TRUNCATE TABLE、ALTER TABLE、DROP TABLE或 DROP DATABASE语句,那使用该表的所有高速缓存查询都将变为无效并从高速缓存中 删除!

从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。

查询优化

优化的结果就是生成一个执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的。我们可以使 用EXPLAIN语句来查看某个语句的执行计划。

存储引擎

存储引擎原来叫表处理器 MySQL服务器把数据的存储和提取操作都封装到了一个叫存储引擎的模块 里。我们知道表是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理 存储器上,这都是存储引擎负责的事情。

配置

除了在命令行启动的时候指定参数如:mysqld –default-storage-engine = MyISAM外,MySQL程序在启动时会寻找多个路径下的配置文件,这些路径有的是固定的,有的是可以在命令行指定的。根据操作系统的不 同,配置文件的路径也有所不同。

配置路径

在类UNIX操作系统中,MySQL会按照下列路径来寻找配置文件:

路径名 备注
/etc/my.cnf
/etc/mysql/my.cnf
SYSCONFDIR/my.cnf
$MYSQL_HOME/my.cnf 特定于服务器的选项(仅限服务器)
defaults-extra-file 命令行指定的额外配置文件路径
~/.my.cnf 用户特定选项
~/.mylogin.cnf 用户特定的登录路径选项(仅限客户端)

配置分组

配置文件里面会分组:server、mysqld、mysqld_safe、client、mysql、mysqladmin。

配置文件中不同的选项组是给不同的启动命令使用的,如果选项组名称与程序名称相同,则组中的选项将专门应用于该程序。 |启动命令|类别|能读取的组| |-|-| | mysqld|启动服务器|[mysqld]、[server]| | mysqld_safe |服务 |[mysqld]、[server]、[mysqld_safe]| | mysql.server | 启动服务器 | [mysqld]、[server]、[mysql.server] | | mysql |启动客户端 | [mysql]、[client] | | mysqladmin | 启动客户端 | [mysqladmin]、[client]| | mysqldump | 启动客户端 | [mysqldump]、[client] |

如果我们想指定mysql.server程序的启动参数,则必须将它们放在配置文件中,而不是放在命令行中。 mysql.server仅支持start和stop作为命令行参数。

特定MySQL版本的专用选项组

我们可以在选项组的名称后加上特定的MySQL版本号。只有版本号为5.7的mysqld程序才能使用这个选项组中的选项[mysqld-5.7]

配置文件加载顺序

MySQL将按照我们在上表中给定的顺序依次读取各个配置文件,如果该文件不存在则忽略。值得注 意的是,如果我们在多个配置文件中设置了相同的启动选项,那以最后一个配置文件中的为准。

同一个配置文件中多个组的优先级 我们说同一个命令可以访问配置文件中的多个组,那么,将以最后一个出现的组中的启动选项为准

如果同一个启动选项既出现在命令行中,又出现在配置文件中,那么以命令行中的启动选项为准

mysql系统变量

MySQL服务器程序运行过程中会用到许多影响程序行为的变量,它们被称为MySQL系统变量,比如允许同时连入的客户端数量用 系统变量max_connections表示,表的默认存储引擎用系统变量default_storage_engine表示,查询缓存的大小用系统变 量query_cache_size表示,MySQL服务器程序的系统变量有好几百条,我们就不一一列举了。每个系统变量都有一个默认值, 我们可以使用命令行或者配置文件中的选项在启动服务器时改变一些系统变量的值。大多数的系统变量的值也可以在程序运行 过程中修改,而无需停止并重新启动它。

查看系统变量:SHOW VARIABLES [LIKE 匹配的模式];

设置的时候可以通过命令行、配置文件、甚至运行期间。

系统变量的作用范围

设计MySQL的大叔提出了系统变量的作用范围的概念,具体来说作用范围分为这两种: GLOBAL:全局变量,影响服务器的整体操作。 SESSION:会话变量,影响某个客户端连接的操作。

SET [GLOBAL|SESSION] 系统变量名 = 值;

通过启动选项设置的系统变量的作用范围都是GLOBAL的,也就是对所有客户端都有效的

我们的SHOW VARIABLES语句查看的是什么作用范围的系统变量呢? 答:默认查看的是SESSION作用范围的系统变量。

当然我们也可以在查看系统变量的语句上加上要查看哪个作用范围的系统变量,就像这样: SHOW [GLOBAL|SESSION] VARIABLES [LIKE 匹配的模式];

有一些系统变量只具有SESSION作用范围,比如insert_id,表示在对某个包含AUTO_INCREMENT列的表进行插入时, 该列初始的值。

启动选项和系统变量的区别? 启动选项是在程序启动时我们程序员传递的一些参数,而系统变量是影响服务器程序运行行为的变量,它们之间的关系如下: 大部分的系统变量都可以被当作启动选项传入。 有些系统变量是在程序运行过程中自动生成的,是不可以当作启动选项来设置,比 如auto_increment_offset、character_set_client啥的。 有些启动选项也不是系统变量,比如defaults-file。

mysql状态变量

为了让我们更好的了解服务器程序的运行情况,MySQL服务器程序中维护了好多关于程序运行状态的变量,它们被称为状态变 量。比方说Threads_connected表示当前有多少客户端与服务器建立了连接,Handler_update表示已经更新了多少行记录。

SHOW [GLOBAL|SESSION] STATUS [LIKE 匹配的模式]; 不写明作用范围,默认的作用范围是SESSION

字符集及编码

MySQL中的 utf8和 utf8mb4

我们上边说utf8字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示了。而在MySQL中字符集表示一 个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以设计MySQL的大叔偷偷的定义了两个概念:

utf8mb3:阉割过的utf8字符集,只使用1~3个字节表示字符。 utf8mb4:正宗的utf8字符集,使用1~4个字节表示字符。

有一点需要大家十分的注意,在MySQL中utf8是utf8mb3的别名,所以之后在MySQL中提到utf8就意味着使用1~3个字节来表示一个字符,如果大 家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使用utf8mb4。

字符集相关配置

查看所支持的字符集。 SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式]; 其中CHARACTER SET和CHARSET是同义词,用任意一个都可以。

查看MySQL中支持的比较规则的命令如下: SHOW COLLATION [LIKE 匹配的模式]; 我们前边说过一种字符集可能对应着若干种比较规则,MySQL支持的字符集就已经非常多了,所以支持的比较规则更多

各级别的字符集和比较规则 MySQL有4个级别的字符集和比较规则,分别是: 服务器级别 数据库级别 表级别 列级别

  1. 服务器级别

MySQL提供了两个系统变量来表示服务器级别的字符集和比较规则:

character_set_server 服务器级别的字符集 collation_server 服务器级别的比较规则

SHOW VARIABLES LIKE ‘collation_server’;

  1. 数据库级别

我们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则,具体语法如下: CREATE DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称]; ALTER DATABASE 数据库名 [[DEFAULT] CHARACTER SET 字符集名称] [[DEFAULT] COLLATE 比较规则名称];

  1. 表级别 我们也可以在创建和修改表的时候指定表的字符集和比较规则,语法如下: CREATE TABLE 表名 (列的信息) [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称]] ALTER TABLE 表名 [[DEFAULT] CHARACTER SET 字符集名称] [COLLATE 比较规则名称]

  2. 列级别 需要注意的是,对于存储字符串的列,同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列定义的时候可以指定该 列的字符集和比较规则,语法如下: CREATE TABLE 表名( 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称], 其他列…);

客户端和服务器通信中的字符集

说到底,字符串在计算机上的体现就是一个字节串,如果你使用不同字符集去解码这个字节串,最后得到的结果可能让你挠头。

从发送请求到返回结果这个过程中伴随着多次字符集 的转换,在这个过程中会用到3个系统变量,我们先把它们写出来看一下:

系统变量 描述 c
character_set_client 服务器解码请求时使用的字符集
character_set_connection 服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
character_set_results 服务器向客户端返回数据时使用的字符集

innodb记录结构

我们知道读写磁盘的速度非常慢,和内存读写差了几个数量级,所以当我们想从表中获取某些记录时,InnoDB存储引擎需要一条一条的把记录 从磁盘上读出来么?

不,那样会慢死,InnoDB采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁 盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。

InnoDB行格式

我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式。设计InnoDB存储引擎的大叔们到现在为止设计了4种不同类型的行格式,分别 是Compact、Redundant、Dynamic和Compressed行格式。

我们可以在创建或修改表的语句中指定行格式: CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称 ALTER TABLE 表名 ROW_FORMAT=行格式名称

行溢出数据现象

MySQL对一条记录占用的最大存储空间是有限制的,除了BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字 节。所以MySQL服务器建议我们把存储类型改为TEXT或者BLOB的类型。

MySQL中磁盘和内存交互的基本单位是页,也就是说MySQL是以页为基本单位来管理存储空间的, 我们的记录都会被分配到某个页中存储。而一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M)类型的列就最多可以存储65532个字节,这样就可能造成一个页存放不了一条记录的尴尬情况。

在Compact和Reduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些 页的地址。

行溢出的临界点

那发生行溢出的临界点是什么呢?也就是说在列存储多少字节的数据时就会发生行溢出? MySQL中规定一个页中至少存放两行记录,只要知道如果我们想一个行中存储了很大的数据时,可能发 生行溢出的现象。