你好,我是idea。
本文是该专栏的第一篇文章,主要是聊聊关于MySQL的整体架构和它的一些背景介绍。之所以我把这一讲的内容放在了第一篇,是因为我认为对于数据库的理解和学习应该是先从总体入手,再到细微的部分深入挖掘,这样的学习过程会给自己留下更加深入的印象。
相信在大部分的程序员在工作中都有接触过MySQL这款数据库,在MySQL的官网上边,你会看到这样的一段介绍内容:
大致翻译过来的意思就是说:
MySQL是世界上最受欢迎的开源数据库。无论您是快速增长的Web资产,技术ISV还是大型企业,MySQL都能经济高效地帮助您交付高性能,可扩展的数据库应用程序。
这款开源的数据库,其源码在github上边的地址为:github.com/mysql/mysql… star还是挺多的。
那么既然是一款公认好用的开源数据库,我们是否应该对它进行一个深入的了解呢?
下边我画了一个大致的MySQL基本架构图:
客户端
MySQL的整体结构可以分成2个大模块,分别是客户端和服务端。这里头说的客户端是指提供连接MySQL的工具集合,常见的客户端工具有mysql client,mysqladmin,mysqldump,mysqlcheck,mysqlimport,mysqlshow等等。MySQL数据库本身提供的连接方式包含有多种,其中最常见的就是基于TCP/IP协议进行连接了。基础的命令内容为:
mysql -h [地址] -u [用户名] -p [密码] 复制代码
在安装完毕了MySQL数据库之后,我们会发现数据库自身已经帮我们预先设置了一个名字叫做mysql的数据库,每次获取链接的时候就会到该库里面的User表检索账号信息以及相关的权限。
在Linux系统中,有很多进程间通信方式,套接字(Socket)就是其中的一种。但传统的套接字的用法都是基于TCP/IP协议栈的,需要指定IP地址。如果不同主机上的两个进程进行通信,当然这样做没什么问题。但是,如果只需要在一台机器上的两个不同进程间通信,还要用到IP地址就有点大材小用了。
MySQL数据库自身是支持UNIX域套接字进行通信的,因此在MySQL的文件目录下边会有这么一份文件:mysql.sock。
这份文件主要是通过Unix域套接字供我们将本地连接数据库服务器使用。
以前笔者就遇到过sock文件被修改,导致连接数据库异常的情况,例如mysql的log中出现这种报错记录:
Could not create unix socket lock file 复制代码
如果sock文件丢失的话,可以重新创建一份sock文件进行通信。
服务端
每次客户端想要链接到服务端都需要从服务端的连接池获取相应的连接。假设我们每次连接都需要完成 构建链接,当我们获取到了链接之后,在mysql的server端可以通过这样一个命令来对每个链接的状态进行查看:
mysql> show processList; +----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+ | 2 | system user | | NULL | Connect | 195290 | Waiting for master to send event | NULL | | 3 | system user | | NULL | Connect | 257 | Slave has read all relay log; waiting for more updates | NULL | | 19 | root | localhost | NULL | Query | 0 | starting | show processList | +----+-------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+ 3 rows in set (0.01 sec) 复制代码
注意通过show process List命令我们一般也只能够查看到当前登录用户的连接情况。在这方面mysql是会有权限区分的。
mysql的information_schema 系统库里面的processlist 表记录了关于数据库连接数的信息,可以通过查看这张表来分析连接数的问题。
processlist表的基本结构如下:
CREATE TEMPORARY TABLE `PROCESSLIST` ( `ID` bigint(21) unsigned NOT NULL DEFAULT '0', `USER` varchar(32) NOT NULL DEFAULT '', `HOST` varchar(64) NOT NULL DEFAULT '', `DB` varchar(64) DEFAULT NULL, `COMMAND` varchar(16) NOT NULL DEFAULT '', `TIME` int(7) NOT NULL DEFAULT '0', `STATE` varchar(64) DEFAULT NULL, `INFO` longtext ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 复制代码
这里面的几个参数大概讲解一下:
USER 是指当前连接数据库所用的账号信息,在实际的业务场景中,连接的账号可能是业务服务器发送的连接,也有可能是从库的连接;有个特殊的名称叫做system user 账号,这个链接是由服务器产生的非客户端线程。
Host 这个参数是指链接的客户端主机名。
db 这个标识链接的数据库
Command 标识该线程正在执行的命令,通常都是会有对应的ddl或者dml语句。
Time 表示线程处于当前状态的时间长短,线程当前时间的概念在某些情况下可能会发生改变:线程可以改变时间。对于正在从主机处理事件的从站上运行的线程,线程时间设置为事件中发现的时间,因此反映了主站而不是从站的当前时间。SET TIMESTAMP = value。
State 对应Command指令,大多数状态对应于非常快速的操作。如果线程在给定状态下保持多秒,则可能存在需要调查的问题。
Info 包含由线程执行的语句的文本或者NULL,如果它不是执行的话。默认情况下,此值仅包含语句的前100个字符。要查看完整的语句,请使用SHOW FULL PROCESSLIST。
查询缓存
对于一些数据修改变动比较少的表,MySQL内部提供了一套叫做Query Cache的缓存池来进行存储。MySQL可以通过以下命令来查看内部的查询缓存参数值:
mysql> show variables like '%query_cache%'; +------------------------------+---------+ | Variable_name | Value | +------------------------------+---------+ | have_query_cache | YES | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 1048576 | | query_cache_type | OFF | | query_cache_wlock_invalidate | OFF | +------------------------------+---------+ 6 rows in set (0.00 sec) 复制代码
关于查询缓存的功能,在MySQL中是根据sql语句来做缓存检索的,默认情况下该缓存属性是关闭的,对于更新频率较高的表而言,设置查询缓存其实本身的命中率并不高,因此该功能MySQL也并不提倡使用,在MySQL8.0的时候该功能也被移除了。
语法分析器
接下来便是语法分析环节了,该模块主要是对传入的SQL语句内容做一些语法内容的校验,例如判断该语句是属于DQL还是DML等类型。
优化器
有时候你会发现,执行的一条SQL可能并不会按照预期的方式来走索引,这是因为MySQL内部有优化器这么一个角色的存在。当然索引的选择只是优化器的其中一项特点,优化器的目的就是通过一定的逻辑判断,将sql执行的效率发挥到最高效化。
执行器
当Sql准备好了,优化结束了,执行器便会发起sql请求引擎层的接口,这个环节中,执行器还回去判断当前请求的会话是否有权限执行相关的SQL语句。
存储引擎
可以说整个数据库的核心部分就是存储引擎环节了,不同的存储引擎对数据的存储结构和算法设计方便都有着巨大的差别,而且不同的存储引擎专门为不同的应用场景所设计。目前我们主流的存储引擎有Innodb,MyISAM,Memory,等
通过下边的这条命令我们可以看到MySQL数据库所支持的存储引擎有哪些:
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的整体架构介绍大概到这里就先暂时告一段落了,下一篇文章我会讲解一些关于存储引擎的比对问题。