写在前面
之前总是零零散散学习mysql,觉得知识不成体系,用完就忘,于是订购了极客时间的Mysql实战笔记,总结学习一下。
连接器
连接器负责跟客户端建立连接、获取权限、维持和管理连接
建立连接,获取权限
首先在查询之前要与mysql建立连接。此时客户端与服务器三次握手建立连接,开始进行用户认证。
mysql -u root -h XXX.XXX....-p
your password
若密码正确,连接成功,Mysql便会查询权限表,之后的权限判断全部依据此时的查询结果。如果修改了权限,一定输入
flush privileges;
强制mysql重新读取权限,或者重新建立连接。只有这样做,才能修改后的权限才能生效。
连接的维持
连接存在的时间跟wait_timeout 参数有关 默认值是8小时
如果连接完成后,没有后续的动作,连接就会进入sleep状态,默认8个小时后自动断开。
长连接与短连接
长连接是指建立连接成功后,如果客户端有持续请求,一直使用同一个连接。
短连接则是建立连接成功后,只执行几个查询就关闭连接。
建立连接的过程较为复杂,建议使用长连接。
但是大量长时间使用长连接时,内存占用会涨的特别快。这是因为,mysql在执行过程中使用的临时内存是存放在连接对象中的,只有当连接断开的时候才会释放资源。如果长时间积累下来,就会导致内存占用太大,被系统强行杀掉,导致mysql异常重启。
解决办法:
1:定期断开长连接。使用一段时间或者在程序中判断一个大查询使用完毕时,断开连接,下次需要用时重新查询。
2:执行mysql_reset_connection 来初始化连接资源,这个过程不需要重新建立连接和做权限认证,但是会将连接恢复至刚刚创建完的状态。
查询缓存
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。如果没有命中查询缓存,第三步就要开始真正执行语句了。
查询缓存有下面的限制。
- 查询缓存是有一个哈希值索引,这个哈希值通过查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的 信息计算得来。所以两个SQL语句在任何字符上的不同(例如:空格、注释),都会导致缓存不会命中。
- 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,其查询结果
都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果,再比如包含CURRENT_USER或者CONNECION_ID()的查询语句会因为不同的用户而返回不同的结果,将这样的查询结果缓存起来没有任何的意义。 - 查询缓存会因为对表的改动而失效,那怕仅仅改变了一行的值。对查询缓存做失效处理时会消耗大量系统资源,而且缓存越大,消耗越大。所以查询缓存适用于相同查询密集,很少读写时使用。
mysql8.0取消了该模块
分析器
该模块分为词法分析和语法分析。
比如我们执行下面语句。
select * from table1
先使用词法分析将每个单词分析出来,再使用语法分析sql语句编写是否正确。
而且语法分析会在词法解析的基础上进一步做表名和字段名称的验证和解析;
一般语法错误会提示第一个出错的位置
优化器
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个查询语句中有多表连接时,决定join的顺序。
select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
- 此时可以找出t1.c=10 然后根据id连接两张表,再找出t2.d=20的。
- 也可以找出t2.d=20的,然后根据id连接两张表,再找t1.c=10 。
在实际环境中,两者的结果是一样的 但是执行的效率可能不一样。所以就需要内置的优化器去进行优化。
执行器
上述步骤都执行完之后,就开始执行语句。
首先判断你对该表有没有相应的权限,如果没有就返回错误。如果有就继续执行
select * from T where ID=10;
- 调用innoDB的引擎接口,取这个表的第一行,如果id== 10 就存放在结果集中,如果不是就执行第二步。
- 取下一行,如果id ==10 就将该行存在结果集中,如果不是就再取下一行。重复该逻辑,直至表结束。
- 返回结果集。