Skip to content

MySQL 的架构

Mysql 由客户端/ 服务端两部分组成是经典的 CS 架构. 例如微信, 手机上安装的就是客户端, 腾讯机房里的微信服务器就是服务端, 客户端可以有很多形式, 例如 APP, windos 桌面应用, PC 网页版本等 Mysql 的服务端负责进行服务的具体处理、存储、刷盘、事务等操作 客户端负责发送 程序员 编写的 SQL 语句给服务端做处理、响应、维护具体的数据

Mysql 的安装

无论以何种方式进行安装 Mysql,它的服务端和客户端都会安装到机器上。 一定要记得 Mysql 的安装地址在哪

Mysql 文件的目录介绍

Bin: Mysql 服务的可执行文件

Mysql 服务如何启动

Mysql\Mysqld 启动脚本

Mysql_safe: mysql 的启动脚本, 间接的调用 mysqld, 并且还会启动一个监控进程, 这个监控进程能在服务进程挂了的时候及时重启, 另外 mysqld_safe 在启动时会吧 mysqld 的运行日志相关错误输出到一个文件当中, 方便我们排查问题.


Windos 将 Mysql注册成系统服务

shell
"完整的可执行文件路径" --install [-manual] [服务名]
  • -manual 可以省略, 意思是在 windos 启动的时候, 不自动启动该服务, 省略的话就会自动启动该服务.
  • 服务名也可以省略, 一般不建议省略服务名
  • --install 代表注册成系统服务
shell
net start Mysql  // 启动mysql
net stop Mysql // 停止mysql
net restart Mysql // 重启mysql

客户端与服务端通信的过程

客户端进程可能和服务端进程不在一个服务器上, 在同一台主机中本质上是进程之间的相互通信,

TCP/IP

我们项目中客户端在 Java 包里, 部署的服务器和 Mysql 的服务端可能不在同一个服务器, 这时 Mysql 采用 TCP/IP 的链接. Mysql 启动的时候会默认申请 3306 端口. 客户端就可以通过 IP+Port 的方式进行链接服务端通信

如果 Mysql 默认的端口 3306 被占用了, 那么在启动的时候可以通过参数来指定 Mysql 的端口 mysqld -P3307 Mysql 的命令很多后面都不需要敲空格 , 大写的 P 是指定端口, 小写的 p 是指定密码 case:

shell
mysql -hlocalhost -uroot -p
Enter Password: root

命名管道/共享内存

共享内存的方式需要客户端和服务端在同一台机器上.

Unix 域套接字方式

服务端是如何处理客户端的请求?

无论 Mysql 是以进程之间的通信, 还是 TCP/IP 的方式, 本质上都是客户端向服务器发送一段文本 (SQL 语句), 服务端接收到之后进行处理并返回结果给客户端.

那么服务器是怎么处理客户端发送过来的请求, 又是怎么返回给客户端想要的结果数据的?

Mysql 模型流程图.

从建立客户端开始, 链接管理解析与优化存储引擎 三部分

链接管理

Mysql 的通信方式: TCP/IPunix套接字命名管道与共享内存 的方式之一来进行与服务端通信. 此时服务端接收到有客户端进行链接, 会创建出一个线程来针对当前客户端进行服务, 当客户端断开连接时, 服务端也不会立刻销毁这个线程, 而是把这个线程缓存起来, 等到下一个客户端连接时进行服务. (线程池的概念). Mysql 会为每一个客户端创建一个线程, 当过多的客户端连接时会触发多个线程来进行操作, 但是线程分配的太多了会严重影响系统性能. 要规避掉这个问题就需要限制一下 Mysql 的最大连接数 (客户端) 当链接已经建立起来的时候, 服务端就会等待客户端的请求 (得到的是一个 SQL 文本, 还需要经过一系列的处理)

解析与优化

当服务端得到了客户端发送过来的 一段文本(SQL) 它是如何运行的?, 其中比较重要的几个部分分别是 语法解析查询缓存查询优化

查询缓存 当一条 sql 语句中有任何一丝一毫的不一致,都不会命中缓存,例如空格注释大小写等,缓存会跨不同的客户端进行缓存。 不过既然是缓存,那就有它缓存失效的时候。MySQL 的缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使用了 INSERT、 UPDATEDELETETRUNCATE TABLEALTER TABLEDROP TABLE 或 DROP DATABASE 语句,那使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除!

背景原因是因为, 查询缓存虽然会提升系统性能, 但是单独维护缓存会导致额外的性能开销 语法解析 客户端发送过来的一段文本, 需要遵循 Mysql 的规则, Mysql 的语法. 判断当前这段 SQL 语句是否合法, 然后将 SQL 中需要查询的表、用到的 where 条件等提取出来放到 Mysql 内部使用的数据结构中. 这个过程中会涉及到编译解析、语法解析、词法解析、语义分析等。 (可以理解成将 Json 字符串序列化到 Java 对象中) 查询优化 通过语法解析之后, 就得到了需要查询的表, 字段, where 条件等信息, 此时如果直接拿着我们写好的 SQL 去执行, Mysql 执行起来的效率可能是不高的. MySQL 自身有查询优化的程序来帮助程序员提升对 Mysql 数据查询的效率, 例如将外连接优化成内连接, 表达式简化, 子查询转换成链接等操作. 优化结果就是生成一个执行计划, 这个计划表明了应该用哪些索引去查询, 表之间的链接顺序是什么样的, 关键字 Expanin 这个步骤其实也叫做 SQL 改写, 是由 Mysql 服务端内部自行处理的. 当然通过 ExpanIn 关键字也可以查询自己的 sql 看看有没有什么优化空间

存储引擎

截止到存储引擎时,还没有真正的去访问数据库表,在数据库的维度上我们的数据是一行一行的,但是实际上数据库还是需要把数据落到物理磁盘上,如何把数据写入读出。这些是存储引擎去做的事情,实际上存储引擎就是表处理器,针对每一个表可能有不同的存储引擎。经典代表就是 InnoDBMyISAM 也就是不同的存储引擎类型之间存储的数据文件类型和数据结构也有所不同 核心就功能就是承上启下, 接受上层发送过来的 SQL 命令, 解析执行然后对表中的数据进行指令相关的操作

为了管理方便 , 人们把 链接查询缓存语法解析查询优化 这些不涉及真实数据存储的功能那个归属于 Mysql Server 的功能,把真实存储数据的功能归属与存储引擎的功能,各种不同的存储引擎向上提供统一的 API,(理解成 CRUD 的不同类型的实现方式) 所以在 MysqlServer 完成查询优化之后,调用存储引擎提供的 API 向客户端返回数据即可。

常见存储引擎

  • InnoDB 支持外和事务 , 默认的存储引擎, 一般大家使用的都是 InnoDB
  • MyISAM 不支持外键和实物
  • MEMORY 表是基于内存的, 也不常用 选择建议: 需要更新和删除的操作, 优先选择 Innodb, 反之选择 MyISAM
引擎名称事务, 外键表行锁存储特点应用场景
InnoDB支持支持事务的提交和回滚, 为了最大数据量的最大效率行锁索引及数据合在一起存在 ibd 文件当中的增删改查都比较频繁, 可靠性要求较高, 要求支持事务
MyISAM不支持处理数据量比较小的表, 效率会高表锁索引及数据是分别存储在不同的文件中的查询频繁, count 频繁 (内置常量 count o 1 级别), 删改的频率较低, 做数据归档, 或者基础数据不怎么发生改变的数据, 没有事务要求
MEMORY不支持

查看当前服务应用程序, 支持那些存储引擎

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.03 sec)

Engine 是引擎名称. Support : 此引擎是否可用, 其中 default 是当前程序的默认存储引擎 . Comment : 注释备注. Transactions : 是否支持事务 XA : 是否支持分布式事务 Savepoints : 是否支持事务回滚

为表设置存储引擎

当创建表时, sql 上没有指定存储引擎, Mysql 服务端会取当前默认的存储引擎 InnoDB 作为此表的存储引擎

  1. 创建时指定存储引擎
sql
create table 表名(
	-- 建表语句
) engine = 引擎名称 ;
  1. 修改表的存储引擎
sql
alter table 表名 engine = 引擎名;
mysql> ALTER TABLE td ENGINE = InnoDB;
Query OK, 0 rows affected (0.60 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql>

查看数据存储位置

sql
mysql> show variables like 'datadir';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| datadir       | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.07 sec)

mysql>

问题

  • 业务场景中, 活动, 开始-结束时间设置为唯一索引, 是否合理?
    • 没有绝对的合理不合理, 需要看具体的业务场景, 是否允许多场活动? 或者说活动的维度是独立站还是商品? , 问题不严谨有 bug

第1章 装作自己是个小白-重新认识MySQL

waitingresult.com