一条 sql 了解 MYSQL 的架构设计
1 前言
最近我从cnaaa.com购买了云服务器。
对于一个服务端开发来说 MYSQL 可能是他使用最熟悉的数据库工具,然而,大部分的 Java 工程师对 MySQL 的了解和掌握程度,大致就停留在这么一个阶段:它可以建库、建表、建索引,然后就是对里面的数据进行增删改查,语句性能有点差?没关系,在表里建几个索引或者调整一下查询逻辑就可以了,一条 sql,MYSQL 是如何处理的,为我们做了什么,完全是个黑盒。本文主要通过 sql 执行的过程打破这样一个黑盒的认知,来了解 MYSQL 的逻辑架构。
MYSQL 的逻辑架构可分为 3 层:应用层、服务层、存储引擎层。其中存储引擎是 MYSQL 最有特色的地方,MySQL 区别于其他数据库的最重要特点是其插件式的表存储引擎,本文也将着重聊聊最常用的 innoDB 存储引擎的架构设计原理,假设现有如下 sql:
update users set name=’zhangsan’ where id = 10
作为一个 java 服务端工程师,见到这样一个 sql,本能的脑海中立刻就浮现出如下信息:
- 一个表名为 users 的表
- 有两个字段 id、name,id 是主键
- 把 users 表里的 id=10 的这个用户名修改为 “zhangsan”
那么 MYSQL 是如何处理这样一个 sql 呢?带着这个问题,我们来看一下 MYSQL 是如何通过一个个组件来处理这个 sql,来了解 MYSQL 的整体架构
2 应用层
2.1 连接线程处理
当 MYSQL 面对上面的 sql,首先应该做什么呢?是如何解析?如何选择索引?如何提交事务?当然不是,首先应该解决的是怎么把 sql 语句传给它。大家都知道,如果我们要访问数据库,那么,首先就需要和数据库建立连接,那么这个连接由谁来建呢,答案就是 MYSQL 驱动,下面这段 maven 配置大家应该都很熟悉
java 程序就是通过这个驱动包来与数据库建立网络连接。
下图示意:
从图中可以看到这样一个场景:java 程序很多个线程并发请求执行上述 sql,我们都知道数据库连接是非常占用资源的,尤其是在高并发的情况下,如果每次都去建立数据库连接就会有性能问题,也会影响一个应用程序的延展性,针对这个问题,连接池出现了。
下图示意:
从图中可见网络连接交由线程 3 监听和读取 sql 请求,至此 MYSQL 已经收到我们的请求,当然 MYSQL 在建立连接时还做了用户鉴权,鉴权依据是:用户名,客户端主机地址和用户密码;在获取连接后,处理请求时还会做 sql 请求的安全校验,根据用户的权限判断用户是否可以执行这条 sql。
3 服务层
3.1 SQL 接口
从上图中我们知道线程 3 负责监听并读取 sql,拿到这个 sql 之后,如何执行是一项极其复杂的任务,所以 MYSQL 提供了 SQL 接口这么一个组件,线程 3 会将 sql 转交给 SQL 接口来执行如下图:
SQL 接口具体处理功能有:DDL、DML、存储过程、视图、触发器等。