MySQL-基础汇总

MySQL-基础汇总

数据库对于任何一个从事后台开发的人说都是永远躲不掉的,任何系统或程序离开了数据的支持都变的毫无意义。而管理数据的工具------数据库就显得尤为重要。本章节我们的核心就是 MySQL,相信很多小伙伴跟我一样,也沉浸在增、删、改、查的舒适区里沾沾自喜。认为MySQL也不过如此,这不用起来也得心应手的嘛!而当你真正走出这个舒适圈,看看外面的世界(与他人技术交流亦或求职面试)。猛然发现自己真的是井底之蛙,有些概念或许听说过,有些甚至不知所云。所以有必要认真系统的去学习并整理一下 MySQL。

SQL的执行流程

众所周知,我们对 MySQL 数据库中数据的操作是通过执行 sql 语句来实现的。那么一个 sql 语句的执行中间经历了怎样的过程?

建立连接

无论我们的 sql 语句写的再天花乱坠,没有连上 MySQL 就是白费功夫。所以第一步得需要跟 MySQL数据库建立连接,客户端向 MySQL 数据库发送网络请求(TCP/IP、命名管道或共享内存、Unix域套接字这几种方式之一来与服务器进程建立连接。这几种连接方式了解下即可),每当有一个客户端进程连接到 MySQL 时,MySQL 都会创建一个线程来专门处理与这个客户端的交互,当该客户端退出时会与MySQL 断开连接,MySQL 并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来,在另一个新的客户端再进行连接时,为了节省线程销毁和创建的开销,把这个缓存的线程分配给这个新连接的客户端。那怎么知道相关线程的连接情况呢?(注:本文所有的命令执行都是通过Navicat执行的)

我们可以通过执行命令

sql 复制代码
show status like 'Threads%';

执行结果如下

  1. Threads_cached :表示线程缓存中的线程数量。MySQL会缓存一定数量的线程以应对新的连接请求,这样可以避免为每个新连接都创建和销毁线程的开销。如果这个数字接近Threads_connected,那么说明线程缓存设置得比较合适。设置缓存大小的配置是thread_cache_size 默认大小为-1 可自动调整。它的最大值是16384。
  2. Threads_connected:当前打开的连接数。这个数字显示了有多少客户端正在与MySQL服务器进行交互。
  3. Threads_created:自服务器启动以来创建的线程总数。如果这个值越大,配置项 thread_cache_size 可相应的增大以提升线程的缓存命中率
  4. Threads_running:当前正在执行查询(运行)的线程数量。

这里提到了 thread_cache_size 我们可以通过命令进行查看

sql 复制代码
SELECT @@thread_cache_size

执行结果如下

sql 复制代码
-- 显示用户正在运行的线程
show FULL PROCESSLIST 

关于连接其实还有一个需要关注的点------连接数,那要查看最大连接数我们可以通过执行

sql 复制代码
SELECT @@max_connections

执行结果如下

max_connections 表示最大的连接数,超过该值不允许建立连接 。 默认值是151,最小值是1最大值是‌100000。

想要查看连接超时时间可以通过执行命令

sql 复制代码
SELECT @@wait_timeout;

wait_timeout 非交互连接等待的时间 (单位s) 默认值28800 也就是8小 时,空闲的线程如果8小时没动静,则会断开。

在其他的连接的配置中比较重要的就是 Max_used_connections,查看与之相关的信息可以通过执行命令

sql 复制代码
show status like 'Max_used_connections%';

执行结果如下

Max_used_connections 自服务启动以来最大的连接数,它记录了自MySQL服务器启动以来,同一时刻并行连接数的最大值。这个值并不表示当前的连接数,而是提供了一个历史记录,用于评估MySQL服务器在过去所承受的最大连接压力。

Max_used_connections_time 表示达到这个峰值的时间。

在成功的与 MySQL 建立连接之后接下来就要开始进入查询的阶段了,因为我们发送给MySQL的请求是我们输入的sql语句(本质上是一段文本)所以首先要对sql 语句进行分析

解析sql

解析sql是借用解析器去把sql语句解析出来,看是否正确可分为 词法解析和语法解析

  1. 词法解析

    顾名思义就是将 sql 语句打碎,转化成一个个的单词,判断单词是否正确

  2. 语法解析

    在输入的sql语句中所有单词都正确的基础上检查该sql的语法是否正确。例如,where是不是写成where1,from写成from1. 表名、列名是否存在、用户是否有操作权限等等。 如果出现错误直接抛出错误。

通过解析器的解析,我们写的 sql 词法正确,语法上也没有错误。那接下来 MySQL 还要对 sql 语句进行预处理操作

预处理

在 MySQL 中,预处理(Prepared Statements)是一种通过编译和执行 SQL 语句的分离来优化性能和增强安全性的技术。预处理语句通常用于防止 SQL 注入攻击,并可以通过减少 SQL 语句的编译次数来提高性能。预处理语句是一种在 SQL 语句中包含占位符(通常是问号 ?)的语句。Mybatis 中拼接 sql 时用的 #{} 和 ${},其中 #{} 就会去解析变成参数,然后进行预处理,能防止sql注入,并且必须传入参数。

查询优化

经过前面几个步骤的洗礼,我们的 sql 语句的所包含的信息完整且语法正确 (所查询的表、列、以及筛选条件都正确),但是我们写的 sql 执行效率不是特别高,需要进行优化。此时优化器就登场了,它会对我们的 sql 语句进行优化(如外连接转化为内连接、表达式简化、子查询转为连接等等)在执行的时候还会判断需不需要走索引,总之优化器会先帮我们做这些工作。优化后会生成一个最终的执行计划,所以这个语句到底如何执行更好,优化器来决定。

到目前为止,我们还未真正的获取到数据。MySQL 把数据的存储和提取操作都封装到了存储引擎中。

存储引擎

执行器去根据表设置的存储引擎,调用不同存储引擎的API接口获取数据。如果要查看当前 MySQL的存储引擎可以通过执行命令

sql 复制代码
SHOW ENGINES;  -- 查询当前服务器支持的存储引擎

执行结果如下

在以上存储引擎中常用的存储引擎就只有 InnoDB 和 MyISAM,其中 InnoDB 为默认的存储引擎。我们通过表格的形式来对比一下这两个存储引擎的区别。

对比 事务支持 外键支持 锁机制 计数统计 主键要求
InnoDB 支持 支持 支持行级锁 没有保存表的总行数 必须有主键
MyISAM 不支持 不支持 只支持表锁,不支持行锁和页面锁 保存有表的总行数 允许没有任何索引和主键的表存在

我们都知道数据最终是存到磁盘中的,不同的存储引擎会有自己的存储实现方式。那如何在磁盘里找到数据存储的位置,可以执行如下命令

sql 复制代码
SHOW VARIABLES LIKE '%datadir%'; 

结果如下

注:这里是安装的windows 版本的 MySQL, Linux 下的地址会有不同

为了体现不同存储引擎在磁盘中的存储方式不同,我们模拟创建两个存储引擎的表,执行如下命令

sql 复制代码
CREATE TABLE `t_teacher` (
  `id` int(10) NOT NULL COMMENT '主键id',
  `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',
  `age` int(5) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

CREATE TABLE `t_student` (
  `id` int(10) NOT NULL COMMENT '主键id',
  `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',
  `age` int(5) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE= MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

在上述 sql 片段中我们创建了两个表教师表和学生表,其中教师表采用默认的存储引擎 InnoDB,学生表用 MyISAM 我们来看这两个表在磁盘中的存储情况

从图上我们可以明显的看出 MyISAM的文件是3个,而InnoDB表数据文件只有1个。

MyISAM磁盘文件

  1. MYD文件 存储所有的数据记录
  2. MYI文件 存储索引信息,即表的索引数据
  3. sdi 系统数据文件,存储一些元数据、表结构,比如行数、空间碎片等

InnoDB磁盘文件

而 InnoDB 的磁盘文件就一个ibd文件存储数据与索引(关于Innodb的具体内容会单独整理一篇文章,此处不做具体的展开)

字符集与比较规则

与 sql执行流程相关的内容梳理完了,我们接下来看一块儿经常容易忽略的内容------字符集和比较规则。众所周知,我们创建数据库的时候都会有这样的选择项

字符集

字符集(Character Set),也被称为编码表,是一个系统支持的所有字符的集合。为了使计算机能够准确地表示、存储和处理各种文本数据,字符集定义了字符与二进制数据之间的映射关系。在计算机内部,所有的信息都是以二进制形式存储和处理的。字符集就是一套规则,它规定了如何将字符转换为二进制数据,以及如何将二进制数据转换回字符。我们看一下常见的字符集

字符集 特征
ASCII 共收录128个字符,包括空格、标点、数字、大小写字母及一些不可见字符
ISO 8859-1 共收录256个字符是 ASCII 字符集的扩充,它的别名为 Latin1
GB2312 收录汉字6763个,其他文字符号682个
GBK 是GB2312字符集的扩充,编码方式兼容GB2312
UTF-8(重要) 几乎收录了所有的字符,编码一个字符需要1~4字节

其他的字符集稍微了解下即可,我们还是把目光集中在重点的 UTF-8上

MySQL中的字符集

我们在创建数据库时会发现UTF-8字符集时有两个,utf8 与 utf8mb4。正如前面所说 UTF-8 字符集表示一个字符时需要1~4个字节,而正常情况下一般常用的字符用1~3个字节就够了,某些特殊的字符则需要1~4的字节来表示(比如表情 emoji)一个字符所用最大字节长度会在某些方面影响性能以及存储。所以我们在创建数据库时看到的 utf8 其实是一个 "简化" 的 UTF-8,它有一个别名叫 utf8mb3 它只使用1~3个字节。utf8mb4 才是正儿八经的 UTF-8 使用1~4个字节。在 MySQL8.0 以后已经将utf8mb4 认定为默认的字符集。那我们要看一下目前 MySQL中有哪些字符集,执行如下命令

sql 复制代码
show charset;

执行结果如下

Default collation 代表该字符集默认的比较规则,Maxlen则表示该字符集最多需要几个字节表示一个字符。

字符集比较规则

我们来看一下 UTF-8 系列的字符集有哪些比较规则,执行命令

sql 复制代码
SHOW COLLATION LIKE'utf8_%';

执行结果如下

那这么多的比较规则该如何进行选择呢,其实 Default 中 包含 yes的都是默认的比较规则。我们可以看到这些比较规则以 utf-8 开头而后面跟着的是比较规则对应的语言,比如 utf8mb4_polish_ci 表示波兰语比较规则,utf8mb4_spanish2_ci 是西班牙语比较规则。这些我们肯定大概率用不到仅作为一个了解,我们只需要知道 general_ci 结尾的是通用的比较规则就可以了。

附:比较规则后缀代表的含义

后缀 含义
_ai 不区分重音
_as 区分重音
_ci 不区分大小写
_cs 区分大小写
_bin 以二进制方式比较

总结

本篇是 MySQL 章节的开篇,内容不是很多。主要从sql执行流程的角度出发,在执行流程中涉及每个阶段一些 mysql 的信息查看,另外就是总结了下字符集和比较规则的一点冷知识,姑且算做一个开胃小菜。

相关推荐
沃和莱特11 分钟前
C++中类的继承
数据库·c++·编程·c·指针·友元函数
FF在路上26 分钟前
MySQL数据库-视图的介绍和使用
数据库·sql·mysql
计算机毕设指导639 分钟前
基于SpringBoot的教学辅助平台系统【附源码】
java·spring boot·后端·mysql·spring·tomcat·mybatis
数字扫地僧1 小时前
如何使用MySQL实现多租户架构:设计与实现全解析
数据库·mysql·架构
乄bluefox2 小时前
SpringBoot中使用Sharding-JDBC实战(实战+版本兼容+Bug解决)
java·数据库·spring boot·redis·后端·缓存·bug
尘佑不尘2 小时前
蓝队基础,了解企业安全管理架构
数据库·笔记·安全·web安全·蓝队
重生之我是数学王子2 小时前
QT 网络编程 数据库模块 TCP UDP QT5.12.3环境 C++实现
数据库·c++·qt·udp·tcp
running up that hill2 小时前
数据库中的增删改查操作、聚合函数、内置函数、分组查询
java·数据库·sql·mysql
莳花微语2 小时前
oracle如何配置第二个监听优化数据传输
数据库·oracle·php
小码的头发丝、2 小时前
Maven的安装与配置
java·数据库·maven