MySQL 安装后,包含一个 “mysqld” 服务器进程、客户端应用程序用于本地或远程连接,及一些本地安装的 mysql 非客户端程序。用户通过 mysql 客户端应用程序连接 MySQL 服务器发起数据请求
当 MySQL 的客户端与服务器进行通信时,客户端和服务器可以使用不同的操作系统,例如,客户端使用 Windows,服务器使用 Linux,客户端通过 TCP/IP 协议连接至服务器
MySQL 是一个单进程多线程的服务器,MySQL 进程的名称为 “mysqld” ,它负责管理数据库在磁盘和内存中的访问,支持多个存储引擎、支持事务和非事务的表,并且能够优化内存的使用
MYSQL 的组成部分有以下内容:
Mysql 的存储:基于表的,而不是数据库。
Mysql 的特点:插件式的表存储引擎
其结构图如下:
连接层为每个连接分配一个线程,该线程用来控制查询的执行。当连接通过用户名/密码的认证后,该连接可以发送 SQL 查询。
连接层接受通过 TCP/IP、Unix socket、shared memory、Named pipes 协议的应用程序连接。连接协议通过客户端的库及驱动实施,连接协议的速度因本地设置而异。上述协议中,MySQL 可以通过 TCP/IP 协议在网络间传送消息,其他的协议仅支持在本地使用(客户端和服务器必须在同一台主机上)
TCP/IP协议除了用于网络间的远程连接,也可以用于本地连接。使用TCP/IP协议时需要使用IP地址或者DNS名称标识主机,并使用端口号标识服务。MySQL的默认端口号为3306。当主机名使用“localhost”时,MySQL将认为用户使用Unix的socket进行通信,使用“127.0.0.1”IP地址时,将使用TCP/IP协议进行通信
Unix socket 通信是进程间通信的一种形式,用于在同一机器上的两个进程之间形成的双向通信链路的一端,要求服务器创建一个 socket 文件,客户端通过该文件进行连接。例如:
mysql -S var/lib/mysql/mysql.sock -uroot -P
当用户使用 window 时,可以通过 shared memory 和 Named pipes 进行连接。使用 shared memory 时,服务器将创建一个共享的内存块,客户端进程将使用该内存块与服务器进行通信。
Named pipes 在 window 上的工作方式与 Unix 的 socket 比较相像,服务器创建一个 named pipe,客户端通过该 named pipe与服务器建立连接
连接线程
服务器为每个活动的客户端连接创建一个连接线程,通过该客户端执行的全部语句将使用该线程,当客户端断开时,服务器将销毁该线程。服务器创建和销毁线程时,它必须事先分配一个专用的内存构造用于客户端的连接,当频繁建立销毁连接时,会为系统带来性能上的影响。MySQL在企业版中提供了线程池插件,该插件可以将线程进行分组管理,每组线程在任意时间点上只允许一个运行时间短的语句,线程组可以为运行时间长的语句额外创建一个线程,并且能够根据事务关系区分语句的优先级
常见的通信机制:
MySQL 客户端/服务端通信协议是“半双工”的:
传送过程:
max_allowed_packet
参数。但是需要注意的是,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常
- 在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯
- 这也是查询中尽量避免使用 SELECT * 以及加上 LIMIT 限制的原因之一
mysql 中存在 4 个控制权限的表,分别为:user 表,db 表,tables_priv 表,columns_priv 表
mysql权限表的验证过程为:
MySQL 的权限分级
全局性的管理权限: 作用于整个 MySQL 实例级别
数据库级别的权限: 作用于某个指定的数据库上或者所有的数据库上
数据库对象级别的权限:作用于指定的数据库对象上(表、视图等)或者所有的数据库对象上
对于一个 MySQL 连接,或者说一个线程,任何时刻都有一个状态,该状态表示了MySQL当前正在做什么。有很多种方式能查看当前的状态,最简单的就是下面这个:
SHOW FULL PROCESSLIST
执行结果如下:
command 列就是状态:
连接出现问题:对于出现问题的连接通过 kill {id} 的方式杀掉
长连接的问题: 使用长连接后,随着连接数不断增加,会导致内存占用升高,因为 MySQL 在操作过程中会占用内存来管理连接对象,只有等到连接断开后才会释放。如果连接一直堆积,就会导致内存占用过大,被系统强行杀掉,也就是会出现 MySQL 重启。
解决方案
1、定期断开长链接,每隔一段时间或者执行一个占用内存的大查询后断开连接,依次释放内存
2、MySQL 5.7+ 的版本中提供了 mysql_reset_connection 来重新初始化连接资源,这时不需要重新连接,就可以将连接恢复到刚刚创建完时的状态
MySQL:show processlist 详解
服务层:主要完成大多数的核心服务功能
mysql 的缓存主要的作用是为了提升查询的效率(mysql8.0 版本后被删除)
show status like 'Qcache%'
缓存执行状态图:
mysql是提供了按需使用缓存的设置,将参数query_cache_type设置成DEMAND,这样对于默认的SQL语句都不使用查询缓存。
用SQL_CACHE显式指定,像下面这个语句一样:
select SQL_CACHE * from T where ID = 10;
SQL 命令传递到解析器的时候会被解析器验证和解析。
分析器的执行过程:
在分析器中就通过语义规则器将 select from where
这些关键词提取和匹配出来,MySQL 会自动判断关键词和非关键词,将用户的匹配字段和自定义语句识别出来。这个阶段也会做一些校验:比如校验当前数据库是否存在 user 表,同时假如 User 表中不存在 userId 这个字段同样会报错:unknown column in field list.
SQL语句在查询之前会使用查询优化器对查询进行优化。
就是优化客户端请求的 query(sql语句) ,根据客户端请求的 query 语句,和数据库中的一些统计信息,在一系列算法的基础上进行分析,得出一个最优的策略,告诉后面的程序如何取得这个 query 语句的结果。
比如表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序
进行 sql 语句的优化,根据执行计划(explain)进行最优的选择,匹配合适的索引选择最佳的执行方案
存储引擎真正的负责 MySQL 中数据的存储和提取,服务器通过 API 与存储引擎进行通信,不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需进行选取。
mysql 区别于其他数据库的最重要的特点就是插件式表存储引擎。mysql 插件式的存储引擎架构提供标准的管理和服务支持
存储引擎基于表而不是基于数据库
主要是将数据存储在运行于裸设备的文件系统之上,并完成于存储引擎的交互
从 mysql 数据库 5.5.8 版本开始,innoDB 存储引擎是默认的存储引擎:
是 mysql5.5.8 版本之前的默认存储引擎
NDB 是一个集群存储引擎,特点是所有的数据都放在内存中,所以主键查找速度极快
Memory 存储引擎(之前称为 HEAP 存引擎)把表的数据放在内存中,如果发生数据库重启或在崩溃,表中的数据将会消失。适合用于存储临时数据的临时表,以及数据仓库中的纬度表。
只支持表锁,并发性能差,并且不支持 TEXT 和 BLOLB 类型
对比项 | InnoDB | MyISAM |
---|---|---|
主外键 | 支持 | 不支持 |
事务 | 支持 | 不支持 |
行、表锁 | 行锁。操作时只锁一行,对其它行不影响。适合高并发 | 表锁。操作一行也会锁整个表。不适合高并发 |
缓存 | 缓存索引、真实数据,对内存要求较高 | 只缓存索引 |
表空间 | 大 | 小 |
关注点 | 事务 | 性能 |
存储引擎的文件后缀:
mysql的逻辑架构解析
MySQL逻辑架构
第04章 逻辑架构