假装自己是个小白 ---- 重新认识MySQL

本文主要介绍 MySQL 服务器在 UNIX 以及 Windows 下的启动指令和方式,展示了如果启动 MySQL 客户端程序,并与服务器进行连接。介绍了 MySQL 服务器与客户端程序的连接过程等内容。详细介绍了服务器处理客户端请求时所进行了步骤,如连接管理、解析与优化【查询缓存、语法解析、查询优化】、存储引擎。最后对 MySQL 的常见存储引擎进行了介绍。

🧑 博主简介: 现任某互联网公司后端高级开发工程师。阿里、腾讯云等多个社区专家博主、创作之星,华为云开发者社区认证博主,华为云-云享专家,鸿蒙开发者。CSDN优质创作者,提供产品测评、学习辅导、简历面试辅导、毕设辅导、项目开发、C/C++/Java/Python/Linux/Vue/AI等方面的服务,如有需要请站内私信或者联系任意文章底部的的VX名片。
💬 博主粉丝群介绍:①目前正在搭建CSDN最活跃优质交流群,群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。③ 群内也有职场精英,大厂大佬,可交流技术、面试、找工作的经验。④ 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬。⑤ 进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。

假装自己是个小白 ---- 重新认识MySQL

启动MySQL服务器程序

UNIX里启动服务器程序

在类 UNIX 系统中可以用来启动 MySQL 服务器的可执行文件有很多,大多数在安装目录的 bin 目录下。

mysqld

mysqlId 这可执行文件就代表着 MySQL 服务器程序,运行这个可执行文件就可以直接启动一个服务器进程。但这个命令通常不使用。

mysqld_safe

mysqld_safe 是一个启动脚本,它会间接的调用 mysqld,而且还顺便启动了另外一个监控进程,这个监控进程在服务器进程挂了的时候,可以帮助重启它。另外,使用 mysqld_safe 启动服务器程序时,它会将服务器程序的出错信息和其他诊断信息重定向到某个文件中,产生出错误日志,这样就可以方便我们来排查出错原因。

mysql.server

mysql.server 也是一个启动脚本,它会间接的调用 ,mysqld_safe,在调用 mysql.server 时在后面指定 start 参数就可以启动服务器程序了,如下:

sql 复制代码
mysql.server start

需要注意的是,这个 mysql.server 文件其实是一个链接文件,它的实际文件是 .../support-files/mysql.server 。

除此之外还可以使用 mysql.server 命令来关闭正在运行的服务器程序,只需要把 start 参数换成 stop 就好了。

sql 复制代码
mysql.server stop

mysqld_multi

其实一台计算机上也可以运行多个服务器实例,也就是运行多个 MySQL 服务器进程。mysql_multi 可执行文件可以对每一个服务器进程的启动和停止进行监控。

Windows里启动服务器程序

Windows 里没有像类 UNIX 系统中那么多的启动脚本,但是也提供了手动启动和以服务形式启动这两种方式。

mysqld

同样的,在 MySQL 安装目录下的 bin 目录下有一个 mysqld 可执行文件,在命令行里输入 mysqld,或者直接双支运行它就算启动了 MySQL 服务器程序了。

以服务的方式运行服务器程序

什么是 Windows 服务?如果无论是谁正在使用这台计算机,我们都需要长时间的运行某个程序,而且需要再计算机启动的时候便启动它,一般我们都会把它注册为一个 Windows 服务,操作系统会帮我们管理它。把某个程序注册为 Windows 服务的方式挺简单的,如下:

bash 复制代码
"完整的可执行文件路径" --install [-manual] [服务名]

其中的 -manual 可以省略,加上它的话表示在 Windows 系统启动的时候不自动启动该服务,否则会自动启动。服务名 也可以省略,默认服务名就是 MySQL。比如我的 Windows 计算机上 mysqld 的完整路径是:

bash 复制代码
C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld

对应注册成服务的命令如下:

powershell 复制代码
"C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld" --install

把 mysqld 注册为 windows 服务后,我们就可以通过下面的命令来启动 MySQL 服务器程序了:

sql 复制代码
net start MySQL

当然,也可以通过 windows 的服务管理器通过鼠标点点点的方式来启动和停止服务。

关闭这个服务也很简单,如下:

sql 复制代码
net stop MySQL

启动MySQL客户端程序

powershell 复制代码
mysql -h主机名  -u用户名 -p密码

各个参数的意义如下:

参数名 含义
-h 表示服务器进程所在计算机的域名或者IP地址,如果服务器进程就在本机的话,可以省略这个参数,或者直接填localhost或者127.0.0.1。也可以写作--host=主机名的形式。
-u 表示用户名。也可以写作 --user=用户名 的形式。
-p 表示密码。也可以写作 --password=密码 的形式。

注意:

像h、u、p这样名称只有一个英文字母的参数成为短形式的参数,使用时前边需要加单短划线,像host、user、password这样大于一个英文字母的参数称为长形式的参数,使用时前边需要加双短划线。

比如我执行下述的命令行就可以启动 MySQL 客户端,并且连到服务器了。

powershell 复制代码
mysql -hlocalhost -uroot -p123456

连接成功的界面:

powershell 复制代码
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.21 Homebrew

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

连接注意事项

  • 最好不要在一行命令中输入密码。
  • 如果非要在一行命令中显式的把密码输出来,那 -p 和密码值之间不能有空白字符(其他参数名之间可以有空白字符),如下:
powershell 复制代码
mysql -h localhost -u root -p123456
  • mysql 的各个参数的摆放顺序没有硬性规定,也就是说你也可以这么写:
powershell 复制代码
mysql -p  -u root -h localhost

客户端与服务器连接的过程

TCP/IP

真实环境中,数据库服务器进程和客户端进程可能运行在不同的主机中,它们之间必须通过网络来进行通讯。MySQL 采用 TCP 作为服务器和客户端之间的网络通信协议。在网络环境下,每台计算机都有一个唯一的 IP地址,如果某个进程有需要采用 TCP 协议进行网络通信方面的需求,可以向操作系统申请一个 端口号 ,这是一个整数值,它的取值范围是 0~65535。这样在网络中的其他进程就可以通过 IP地址 + 端口号 的方式来与这个进程连接,这样进程之间就可以通过网络进行通信了。

MySQL 服务器会默认监听 3306 端口。

可以在启动服务器程序的命令行里添加 -P 参数来明确指定一下端口号,如下:

powershell 复制代码
mysqld -P3307

客户端连接的时候也可以使用 -P 参数来指定端口号,如下:

powershell 复制代码
mysql -h127.0.0.1 -uroot -P3307 -p

命名管道和共享内存

如果你是一个 Windows 用户,那么客户端进程和服务器进程之间可以考虑使用 命名管道 或 共享内存 进行通信。不过启用这些通信方式的时候需要在启动服务器程序和客户端程序时添加一些参数:

  • 使用 命名管道 来进行进程间通信

    需要在启动服务器程序的命令中加上 --enable-named-pipe 参数,然后在启动客户端程序的命令中加入 --pipe 或者 --protocol=pipe 参数。

  • 使用 共享内存 来进行进程间通信

    需要在启动服务器程序的命令中加上 --shared-memory 参数,在成功启动服务器后,共享内存 便成为本地客户端程序的默认连接方式,不过我们也可以在启动客户端程序的命令中加入 --protocol=memory 参数来显式的指定使用共享内存进行通信。

不过需要注意的是,使用 共享内存 的方式进行通信的服务器进程和客户端进程必须在同一台 Windows 主机中。

Unix域套接字文件

如果我们的服务器进程和客户端进程都运行在同一台操作系统为类 Unix 的机器上的话,我们可以使用 Unix域套接字文件 来进行进程间通信。如果我们在启动客户端程序的时候指定的主机名为 localhost,或者指定了 --protocol=socket 的启动参数,那服务器程序和客户端程序之间就可以通过 Unix 域套接字文件来进行通信了。 MySQL 服务器程序默认监听的 Unix 域套接字文件路径为 /tmp/mysql.sock,客户端程序也默认连接到这个 Unix 域套接字文件。如果我们想改变这个默认路径,可以在启动服务器程序时指定 socket 参数,就像这样:

powershell 复制代码
mysqld --socket=/tmp/a.txt

这样服务器启动后便会监听 /tmp/a.txt。在服务器改变了默认的 UNIX 域套接字文件后,如果客户端程序想通过 UNIX 域套接字文件进行通信的话,也需要显式的指定连接到的 UNIX 域套接字文件路径,就像这样:

powershell 复制代码
mysql -hlocalhost -uroot --socket=/tmp/a.txt -p

这样该客户端进程和服务器进程就可以通过路径为 /tmp/a.txt 的 Unix 域套接字文件进行通信了。

服务器处理客户端请求

其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们这里以比较复杂的查询请求为例来画个图展示一下大致的过程:

从图中我们可以看出,服务器程序处理来自客户端的查询请求大致需要经过三个部分,分别是 连接管理、解析与优化、存储引擎。下边我们来详细看一下这三个部分都干了什么。

连接管理

客户端进程可以采用我们上边介绍的 TCP/IP、命名管道或共享内存、Unix域套接字 这几种方式之一来与服务器进程建立连接,每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程来专门处理与这个客户端的交互,当该客户端退出时会与服务器断开连接,服务器并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来,在另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端。这样就起到了不频繁创建和销毁线程的效果,从而节省开销。从这一点大家也能看出,MySQL 服务器会为每一个连接进来的客户端分配一个线程,但是线程分配的太多了会严重影响系统性能,所以我们也需要限制一下可以同时连接到服务器的客户端数量,至于怎么限制我们后边再说哈~

当连接建立后,与该客户端关联的服务器线程会一直等待客户端发送过来的请求,MySQL 服务器接收到的请求只是一个文本消息,该文本消息还要经过各种处理,预知后事如何,继续往下看哈~

解析与优化

到现在为止,MySQL 服务器已经获得了文本形式的请求,接着 还要经过九九八十一难的处理,其中的几个比较重要的部分分别是 查询缓存、语法解析 和 查询优化,下边我们详细来看。

查询缓存

MySQL 服务器程序处理查询请求的过程也是这样,会把刚刚处理过的查询请求和结果缓存起来,如果下一次有一模一样的请求过来,直接从缓存中查找结果就好了,就不用再傻呵呵的去底层的表中查找了。这个查询缓存可以在不同客户端之间共享,也就是说如果客户端A刚刚查询了一个语句,而客户端B之后发送了同样的查询请求,那么客户端B的这次查询就可以直接使用查询缓存中的数据。

如果两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中。

相当于,查询语句是 key,返回结果是 value,的 key-value 的缓存类型。

另外,如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql 、information_schema、 performance_schema 数据库中的表,那这个请求就不会被缓存。以某些系统函数举例,可能同样的函数的两次调用会产生不一样的结果,比如函数 NOW,每次调用都会产生最新的当前时间,如果在一个查询请求中调用了这个函数,那即使查询请求的文本信息都一样,那不同时间的两次查询也应该得到不同的结果,如果在第一次查询时就缓存了,那第二次查询的时候直接使用第一次查询的结果就是错误的!

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

注意:

虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。

语法解析

如果查询缓存没有命中,接下来就需要进入正式的查询阶段了。
MySQL 服务器首先要对这段文本做分析,判断请求的语法是否正确,然后从文本中将要查询的表、各种查询条件都提取出来放到 MySQL 服务器内部使用的一些数据结构上来。

注意:

这里还涉及到词法解析、语法分析、语义分析等阶段。

查询优化

语法解析之后,服务器程序就获得到了需要的信息,比如要查询的列是哪些,表是哪个,搜索条件是什么等等,但光有这些不够,因为我们写的 MySQL 语句执行起来效率可能并不是很高,MySQL 的优化程序会对我们的语句做一些优化,如外连接转换为内连接、表达式简化、子查询转为连接吧啦吧啦的一堆东西。

注意:

这里可以使用 EXPLAIN 来查看某个语句的执行计划。

存储引擎

MySQL 服务器把数据的存储和提取操作都封装到了一个叫 存储引擎 的模块里。

为了管理方便,人们把 连接管理、查询缓存、语法解析、查询优化 这些并不涉及真是数据存储的功能划分为 MySQL server 的功能,把真实存取数据的功能划分为 存储引擎 的功能。各种不同的存储引擎向上边的 MySQL sever 层提供统一调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、"读取索引下一条内容"、"插入记录"等等。

常用存储引擎

最常用的就是 InnoDB 和 MyISAM,有时会提一下 Memory。其中 InnoDB 是 MySQL 是默认的存储引起。


关于存储引擎的一些操作

查看当前服务器程序支持的存储引擎

查看当前服务器支持的存储引擎:

sql 复制代码
SHOW ENGINES;

执行结果:

sql 复制代码
mysql> SHOW ENGINES;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

mysql>

Support 列表示该存储引擎是否可用。
DEFAULT 表示当前服务器程序的默认存储引擎。
Comment 列是对存储引擎的一个描述。
Transactions 列代表该存储引擎是否支持事务处理。
XA 列代表着该存储引擎是否支持分布式事务。
Savepoints 代表着该存储引擎是否支持部分事务回滚。

设置表的存储引擎

不同的表可以设置不同的存储引擎。

创建表时指定存储引擎

创建表的语句没有指定表的存储引擎,那就会使用默认的存储引擎 InnoDB(当然这个默认的存储引擎也是可以修改的)。

显式的指定一下表的存储引擎:

sql 复制代码
CREATE TABLE 表名(
    建表语句;
) ENGINE = 存储引擎名称;

比如我们想创建一个存储引擎为 MyISAM 的表可以这么写:

sql 复制代码
mysql> CREATE TABLE engine_demo_table(
    ->     i int
    -> ) ENGINE = MyISAM;
Query OK, 0 rows affected (0.02 sec)

mysql>

修改表的存储引擎

如果表已经建好了,我们也可以使用下边这个语句来修改表的存储引擎:

sql 复制代码
ALTER TABLE 表名 ENGINE = 存储引擎名称;

比如我们修改一下 engine_demo_table 表的存储引擎:

sql 复制代码
mysql> ALTER TABLE engine_demo_table ENGINE = InnoDB;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql>

这时我们再查看一下 engine_demo_table 的表结构:

sql 复制代码
mysql> SHOW CREATE TABLE engine_demo_table\G
*************************** 1. row ***************************
       Table: engine_demo_table
Create Table: CREATE TABLE `engine_demo_table` (
  `i` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)

mysql>
相关推荐
腾科IT教育10 小时前
Oracle OCP和MySQL OCP怎么选?方向对比指南
mysql·oracle·ocp·oracle ocp·ocp怎么选·mysql ocp
三少爷的鞋10 小时前
别再这么写协程了!Marcin Moskała 剖析的 几个常见协程误区与重构
android
大牧师10 小时前
Mybatis 框架教程
java·数据库·mybatis·数据持久化·orm
有想法的py工程师11 小时前
PostgreSQL【内核】 CBO 优化器的“早停下注”与数学模型失效分析
数据库·postgresql
用户4603812919411 小时前
别人都 commit 了,为什么我的 select 还是旧值?图解 MySQL MVCC
mysql
冰暮流星11 小时前
sql之计算
数据库·sql
mmsx11 小时前
Android 防二次打包第一道锁:签名校验与完整性校验
android·kotlin
mmsx11 小时前
Android 混淆不等于安全:二次打包链路完整走一遍
android·kotlin
dishugj12 小时前
HANA集群状态监控
数据库·系统架构
小蒜学长12 小时前
基于Java的公司采购系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·公司采购系统