一、MySQL基础架构
大体来说MySQL可分为Server层和存储引擎层
1、Server层
Server层包含了所有跨存储引擎的功能,比如存储过程
、触发器
、视图
、还有所有内置函数
(如日期、时间、数学等),此外Server层还包含了几个重要的组件,下面会逐个介绍它们的功能。
连接器
功能
和客户端 建立连接、获取权限、维持和管理连接。
特点
在连接建立时一次性的获取权限,之后 此连接的权限都将取决于建立连接时获取的权限。
常用命令
mysql -h$ip -P$port -u$user -p --建立连接(隐式输入密码)
建立连接后:
mysql> show processlist --显示所有连接状态
mysql> mysql_reset_connection --初始化连接资源(5.7版本以上)
常见报错
Access denied for user --用户名或密码错误
Lost connection to MySQL server during query --丢失连接(可能是超时自动断开,也可能是异常断开)
超时自动断开需要重新连接后再执行请求
常见问题
因为建立连接比较耗时和耗费资源,所以在项目中应尽量使用长连接。
长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接
短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个
- 长连接资源释放问题
在全部使用长连接后,有时候MySQL内存占用会明显变大,这是因为MySQL的临时内存由连接对象管理,内存资源在连接断开的时候才会释放。如果长时间不释放导致内存占用太大,会被操作系统强行杀掉(OOM),从现象看就是MySQL异常重启了。
解决方法:
- 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
- 如果你用的是MySQL 5.7或更新版本,可以在每次执行一个比较大的操作后,通过执行
mysql_reset_connection
来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。
查询缓存(8.0版本后已被删除)
功能
把执行过的语句和结果以key-value的形式缓存到内存中,提高查询效率。
大多数情况下建议不要使用查询缓存,对于经常更新的表,一次更新操作就会导致整个表的查询缓存失效。查询缓存的命中率非常低。只有一些系统配置类的静态表才适合使用查询缓存。
原理
把执行过的语句和结果以key-value的形式缓存到内存(key是查询的语句,value是查询的结果)
之后有新请求时,先从缓存中找是否存在该请求的缓存结果,如果有就直接返回,没有就从存储引擎中查询数据。
常用命令
mysql> query_cache_type=0 --关闭查询缓存,设置后需重启MySQL
mysql> query_cache_type=1 --开启查询缓存,设置后需重启MySQL
mysql> select SQL_CACHE * from T where ID=10 --SQL_CACHE显式指定该语句使用查询缓存
分析器
功能
分析SQL语句,词法分析、语法分析。
词法分析:识别语句中字符串代表什么。识别关键字、表明、字段名等等。
语法分析:判断SQL语句是否满足MySQL的语法
常见报错
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1
-- sql语句语法错误。
一般语法错误会提示第一个出现错误的位置,所以要关注的是紧接“use near”的内容。
优化器
功能
当表里有多个索引时,决定使用哪儿个索引
SQL语句中有多表关联时,决定各个表的连接顺序
执行器
功能
执行SQL语句
原理
开始执行语句时 ,先判断当前用户有没有对目标表的操作权限,如果没有就会返回错误
如果有权限,就打开表继续执行。
执行语句本质上就是调用存储引擎对应的接口。
select * from T where ID=10 的执行流程:
无索引的情况下:
1.调用InnoDB引擎接口取这个表的第一行,判断ID值是不是10,如果不是则跳过,如果是则将这行存在结果集中;
2.调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
3.执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
有索引的情况下:
1.调用InnoDB引擎接口“取满足条件的第一行”
2.循环取“满足条件的下一行”这个接口
3.执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
在数据库的慢查询日志中可以看到rows_examined字段,它表示这个语句在执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。
在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此 引擎扫描行数跟rows_examined并不是完全相同的。