与其他数据库相比,MySQL并不完美,但足够灵活,可以适应苛刻的环境。在开发中,MySQL是Gogo在项目中的首选数据库。为了更好的应用MySQL,充分发挥它的性能,有必要了解它的设计。从本文开始,我们开始学习MySQL数据库的基础知识。要想对MySQL服务器有更深入的了解,首先要掌握MySQL的逻辑架构,了解它的各个模块是如何协同工作的。下图是官网的逻辑结构图:我们对上图进行简化,就得到了如下图的MySQL简单逻辑结构,后面会详细分析各个组成部分。MySQL整体上可以分为Server层和存储引擎层。MySQL在服务器层的大部分核心服务功能都在服务器层,包括连接器、查询缓存、解析器、优化器和执行器。Server层涵盖了MySQL的大部分功能,包括查询解析、分析、优化、缓存以及所有内置功能(例如日期、时间、数学和加密功能)。所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。连接器的每个客户端连接都会在服务器进程中有一个线程,这个连接的查询只会在这个单独的线程中执行.当客户端应用程序连接到MySQL服务器时,它首先收到的是连接器。连接器负责与客户端建立连接、获取权限、维护和管理连接。连接MySQL服务器的命令:mysql-h$ip-P$port-u$user-p输入命令后会提示我们输入密码,也可以把密码写在-p后面,但是有会有密码泄露的风险。如果我们根据输入的用户名和密码无法连接到服务器,可以看到如下错误:[root@codegirl~]#mysql-hlocalhost-P3306-uroot-pEnterpassword:ERROR1045(28000):Accessdeniedforuser'root'@'localhost'(usingpassword:YES)此错误消息由连接器返回。所以当我们通过客户端命令mysql与服务器建立连接时,连接器做了两件事:验证用户名和密码,如果验证失败,我们收到上述1045异常,客户端程序结束执行。如果认证成功,则客户端与服务器建立连接。连接成功后,connector会继续验证用户的权限,比如我们对哪些表有查询权限,对哪些表有修改权限,或者授权权限。本次连接中的权限判断逻辑是根据此时读取的权限。所以如果修改了权限,一定要记得重新连接!连接器的连接分为长连接和短连接。长连接:连接成功后,如果客户端继续请求,会一直使用一个连接。短连接:每次执行几次查询后断开连接,下次查询时重新建立连接。建立连接的过程比较复杂,现在大部分服务都使用长连接。如果连接建立后没有客户端请求,此时会断开连接。这个时间由参数wait_timeout控制,默认为8小时。检查MySQL的连接时间设置:mysql>showvariableslike'wait_timeout%';超时时间的单位是秒,28800/60/60=8h;连接好查询缓存后,我们就可以执行sql语句了。选择查询语句:mysql>select*fromuserwhereid=1;它不直接查询表中的数据,而是先查询缓存,如果缓存中存在,则直接返回缓存中的数据,如果缓存中不存在,再查询表中的数据,然后将查询结果添加到缓存中。这个逻辑就像是加了一个Redis缓存来减轻数据库的压力。如果缓存存在,就不需要后续的解析和执行步骤,效率会大大提高。MySQL缓存的数据以key-value的形式存在,key就是我们查询的sql语句,value就是这条sql语句对应的查询结果。这时候我们不禁会想,如果数据库中的数据变化频繁,是否需要及时让缓存失效,以便我们在下次查询时获取到最新的数据。是的,只要表的数据或结构发生变化,MySQL就会使这个表的所有缓存失效。所以如果是经常涉及到增删改查的表,缓存并没有太大的实际意义。可能刚添加缓存就更新了,好不容易添加的缓存又失效了。但是如果我们的表是系统配置之类的静态表,缓存就可以发挥作用了。在开发中,如果我们测试某条sql的执行时间,首先要判断缓存是否可用。查询缓存是否可用的命令:mysql>showvariableslike'%have_query_cache%';缓存默认可用:修改缓存的配置,我们可以修改mysql的配置文件:/etc/my.cnf,添加配置:query_cache_type=0;其中选项为:0、1、2;0表示不使用缓存,1表示使用缓存,2表示按需使用。也可以使用命令:mysql>setglobalquery_cache_type=0;查看缓存是否开启:mysql>select@@query_cache_type;如果关闭了缓存,我们想对一些SQL语句使用缓存,可以通过SQL_CACHE显式指定SQL使用缓存。mysql>selectSQL_CACHE*fromuser;MySQL8.0版本已经完全删除了缓存,我们只需要了解缓存组件即可。在使用不同版本的MySQL时,需要注意缓存对性能的影响。当解析器开始真正执行sql语句时,解析器首先对我们输入的sql语句进行解析,MySQL解析器将sql语句解析成内部数据结构(解析树),然后优化器就可以对其进行优化。我们给解析器的sql语句是由字符串和空格组成的。解析器的第一步是解析字符串并识别其中每个字符串的含义。解析器将识别sql关键字,从而知道我们是在查询还是在更新。解析器将字符串“user”识别为表名,将字符串“id”识别为列。解析器识别出字符串后,就开始检查我们给出的字符串是否符合语法规范。解析器验证语法并根据解析的表和列验证表和列的存在。如果表或列不存在,或者存在语法问题,我们会收到一条错误消息。mysql>select*fromaawhereid=1;ERROR1146(42S02):表'test.aa'不存在mysql>select*fromuserwhereid=1;ERROR1064(42000):你的SQL语法有错误;得到了解析树。这个时候MySQL已经很清楚自己要做什么了,只是在开始执行之前会对sql进行优化。优化器对SQL语句的优化包括:重写查询、确定表的读写顺序、选择合适的索引等,优化器涉及的内容很多。先对它有个初步的印象,后面再详细了解一下。经过优化器,sql语句的执行计划已经确定,经过分析后,进入执行器开始执行。Executorexecutor执行sql语句时,首先会验证自己是否对该表有权限,如果没有,则返回没有权限的错误信息。如果授权,表将被打开以继续执行。打开表时,执行器会根据表的执行引擎使用执行引擎提供的接口。存储引擎存储引擎层负责数据的存储和检索。存储引擎是插件式的,支持InnoDB、MyISAM、Memory等存储引擎。MySQL还提供了一些第三方存储引擎。这种插件式结构设计使得不同的公司可以根据自己的需要选择不同的存储引擎。引擎。现在最常用的存储引擎是InnoDB,它是MySQL5.5.5之后默认的存储引擎。如果我们在建表时不指定存储引擎类型,默认使用InnoDB。不同的存储引擎共享Server层,区分Server层和引擎层的功能对于我们后面学习锁和事务很重要。不同的引擎保存数据和索引的方式不同,但是表的定义是MySQL服务层的职责,是一致的。今天我们只分析两种常见的存储引擎InnoDB和MyISAM。其他引擎合作伙伴有兴趣查看相关文档。InnoDB我们先来看'user'表的信息,它的存储引擎是InnoDB。mysql>showtablestatuslike'user'\G******************************1.row****************************Name:user#表名Engine:InnoDB#StorageenginetypeVersion:10Row_format:Dynamic#Rowformat,如果表中包含变长字段如Varchar,然后是DynamicRows:0#行数,对于InnoDB引擎来说,这是估计值Avg_row_length:0#平均每行包含的字节数data_length:16384#表数据的大小(字节)max_data_length:0#表数据的最大容量与引擎有关Index_length:0#所以大小(字节)data_free:0Auto_increment:NULL#下一次自增值Create_time:2021-02-1614:24:46Update_time:NULLCheck_time:NULLCollat??ion:utf8_general_ci#DefaultCharactersetChecksum:NULLCreate_options:Comment:1rowinset(0.00sec)InnoDB数据存储在表空间中,表空间将每个表的数据和索引存储在单独的文件中。'user'表在磁盘上有两个数据文件:.frm文件:表示表的定义,由MySQL的服务器层定义。.ibd文件:数据和索引文件。InnoDB使用MVCC多版本控制来支持高并发。并且它实现了四种标准的事务隔离级别,其默认的隔离级别是可重复读。它支持行锁并通过间隙锁策略防止幻读。InnoDB基于聚簇索引构建,对于基于主键的查询具有高性能。MyISAM我们先来看'user_isam'表的信息,它的存储引擎是MyISAM。mysql>showtablestatuslike'user_isam'\G******************************1.row***************************名称:user_isamEngine:MyISAMVersion:10Row_format:DynamicRows:0Avg_row_length:0Data_length:0Max_data_length:281474976710655Index_length:1024Data_free:0Auto_increment:NULLCreate_time:2021-02-61time_time:2021-03-61time_up:2-02-1616:36:25Check_time:NULLCollat??ion:utf8_general_ciChecksum:NULLCreate_options:Comment:1rowinset(0.00sec)MyISAM将表存储在两个文件中:数据文件和索引文件。.frm文件:表示表的定义,由MySQL的server层定义。.MYD文件:表示数据文件。.MYI文件:表示索引文件。MyISAM提供了很多特性,但不支持事务和行锁。它锁定了整个表并且在崩溃后无法安全地恢复,这就是它被InnoDB取代的原因。总结MySQL逻辑架构分为Server层和存储引擎层。Server层负责连接、缓存、解析、优化和执行。存储引擎负责数据的存储和检索。存储是可插拔的,可以根据每个表的要求选择不同的存储引擎,但不推荐这样做。除非你需要使用InnoDB没有的特性,解决不了问题只能选择其他引擎,否则需要修改,否则就按照默认的InnoDB引擎。并且除非绝对必要,否则不建议混合使用多个引擎。
