连接层最上层是一些客户端和连接服务,包括本地sock通信和大部分基于客户端/服务器工具的类似于TCP/IP的通信。主要完成一些类似的连接处理,授权认证,以及相关的安全解决方案。在这一层引入了线程池的概念,为通过认证和安全访问的客户端提供线程。基于SSL的安全链接也可以在该层上实现。服务器还验证它对每个安全访问的客户端所具有的操作权限。服务层第二层架构主要完成大部分核心服务功能,如SQL接口,并完成缓存查询、SQL分析优化、一些内置功能的执行。所有跨存储引擎的功能也是在这一层实现的,比如过程、函数等。在这一层,服务器会对查询进行解析,并创建对应的内部解析树,并进行相应的优化,比如确定表查询的顺序,是否使用索引等,最终生成相应的执行操作。如果是select语句,服务器也会查询内部缓存。如果缓存空间足够大,在解决大量读操作的环境下,可以大大提高系统性能。引擎层存储引擎层,存储引擎真正负责MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信。不同的存储引擎有不同的功能,所以我们可以根据自己的需要选择合适的存储引擎。数据库中的索引是在存储引擎层实现的。存储层数据存储层主要将数据(如:redolog、undolog、data、index、binarylog、errorlog、querylog、slowquerylog等)存储在文件系统上,完成与存储引擎的交互。与其他数据库相比,MySQL有点不同的地方在于它的架构可以在很多不同的场景下很好的应用和发挥作用。主要体现在存储引擎上。插件存储引擎架构将查询处理与其他系统任务以及数据存储和提取分开。这种架构可以根据业务需要和实际需要选择合适的存储引擎。存储引擎简介你可能没有听说过存储引擎,但你一定听说过引擎这个词。引擎就是引擎,是机器的核心部件。比如舰载机、直升机、火箭,它们都有自己的发动机,发动机是它们的核心部件。而我们在选择引擎的时候,需要在合适的场景下选择合适的存储引擎,就像在直升机上一样,不能选择舰载机的引擎。存储引擎也是如此,它是mysql数据库的核心,我们也需要在合适的场景下选择合适的存储引擎。接下来介绍一下存储引擎。存储引擎是存储数据、建立索引、更新/查询数据等技术的实现。存储引擎是基于表的,而不是库,所以存储引擎也可以称为表类型。我们可以在创建表的时候指定选择的存储引擎,如果不指定,会自动选择默认的存储引擎。创建表时,指定存储引擎CREATETABLE表名(field1field1type[COMMENTfield1comment],......fieldnfieldntype[COMMENTfieldncomment])ENGINE=INNODB[COMMENTtable评论];查询当前数据库支持的存储引擎SHOWENGINES;创建表my_myisam,并指定MyISAM存储引擎CREATETABLEmy_myisam(`id`INT,`name`VARCHAR(10))ENGINE=MYISAM;创建表my_memory,指定Memory存储引擎CREATETABLEmy_memory(`id`INT,`name`VARCHAR(10))ENGINE=MEMORY;存储引擎特点上面我们介绍了什么是存储引擎以及在建表时如何指定存储引擎,接下来我们将重点介绍InnoDB、MyISAM、Memory这三种存储引擎的特点。InnoDB简介InnoDB是一个具有高可靠性和高性能的通用存储引擎。MySQL5.5之后,InnoDB是默认的MySQL存储引擎。特点DML操作遵循ACID模型,支持事务;行级锁提高并发访问性能;支持外键FOREIGNKEY约束,保证数据的完整性和正确性;文件xxx.ibd:xxx代表表名,innoDB引擎每张表都会对应这样一个表空间文件,里面存放了表的结构(frm-early,sdi-newversion),表的数据和索引。参数:innodb_file_per_table显示像'innodb_file_per_table'这样的变量;Variable_nameValueinnodb_file_per_tableON如果启用该参数,则表示对于InnoDB引擎的表,每张表对应一个ibd文件。我们直接打开MySQL数据存放目录:D:\DevelopTools\mysql-5.7.19-winx64\data,这个目录下有很多文件夹,不同的文件夹代表不同的数据库。我们直接打开frx_db02文件夹。可以看到里面有很多ibd文件,每个ibd文件对应一个表,比如:我们有一个表account,就有这么一个account.ibd文件,而这个ibd文件不仅存储了表结构,数据,同时也会存储该表对应的索引信息。该文件是基于二进制存储的,不能直接用记事本打开。我们可以使用mysql提供的一条指令ibd2sdi从ibd文件中提取sdi信息,sdi数据字典信息包括表。表结构。ibd2sdiaccount.ibd为MySQL8有效逻辑存储结构表空间:InnoDB存储引擎逻辑结构的最高层,ibd文件实际上是一个表空间文件,可以包含多个Segment段。段:表空间由各种段组成,常见的段包括数据段、索引段、回滚段等。InnoDB中段的管理由引擎自己完成,无需人工控制。一个段包含多个区域。区域:区域是表空间的单位结构,每个区域的大小为1M。默认情况下,InnoDB存储引擎页面大小为16K,即一个区域中有64个连续的页面。页:页是一个区域的最小单位,页也是InnoDB存储引擎磁盘管理的最小单位。每页的默认大小为16KB。为了保证页面的连续性,InnoDB存储引擎每次从磁盘申请4-5个区域。行:InnoDB存储引擎是面向行的,也就是说数据是按行存储的。除了定义表时指定的字段外,每一行还包含两个隐藏字段(稍后详细介绍)。MyISAM简介MyISAM是早期MySQL默认的存储引擎。特性不支持事务,不支持外键支持表锁,不支持行锁访问速度快文件xxx.sdi:存放表结构信息xxx.MYD:存放数据xxx.MYI:存放索引MemoryStore引入表数据时Memoryengine在内存中,由于硬件问题,或者断电问题,这些表只能作为临时表或者缓存使用。Featuresmemorystoragehashindex(default)filexxx.sdi:storagetablestructureinformationdifferenceandcharacteristicsInnoDBMyISAMMemorystoragelimit64T??Bhastransactionsecuritysupport--lockmechanismrowlocktablelocktablelockB+treeindexsupportsupportsHashindexsupport--支持全文索引支持(5.6版本后)support-SpaceusehighbottomN/Amemoryusehighbottommediumbatchinsertspeedlowhighhighsupportforeignkeysupport--storageengineselection在选择存储引擎时,应该根据应用系统特性选择合适的存储引擎。对于复杂的应用系统,也可以根据实际情况选择多个存储引擎进行组合。InnoDB:是Mysql默认的存储引擎,支持事务和外键。如果应用对事务的完整性要求比较高,要求并发条件下数据的一致性,数据操作除了插入和查询之外还包括很多更新和删除操作,那么InnoDB存储引擎是更合适的选择。MyISAM:如果应用主要是读和插入操作,很少有更新和删除操作,事务的完整性和并发性不是很高,那么这个存储引擎就非常适合。MEMORY:将所有数据存储在内存中,存取速度快,通常用于临时表和缓存。MEMORY的缺点是对表的大小有限制。太大的表无法缓存在内存中,数据安全性得不到保证。MySQLInnoDB引擎逻辑存储引擎InnoDB的逻辑存储结构如下图所示:表空间表空间是InnoDB存储引擎逻辑结构的最高层。如果用户开启参数innodb_file_per_table(8.0版本默认开启),每张表都会有一个表空间(xxx.ibd),一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。段分为数据段(Leafnodesegment)、索引段(Non-leafnodesegment)、回滚段(Rollbacksegment),InnoDB是索引组织表,数据段是B+树的叶子节点,索引段是B+树的非叶节点。Segments用于管理多个Extents(区域)。area,表空间的单位结构,每个area的大小为1M。默认情况下,InnoDB存储引擎页面大小为16K,即一个区域中有64个连续的页面。页是InnoDB存储引擎磁盘管理的最小单位,每页默认大小为16KB。为了保证页面的连续性,InnoDB存储引擎每次从磁盘申请4-5个区域。Rowbyrow,InnoDB存储引擎数据是按行存储的。行中默认有两个隐藏字段:Trx_id:每有一条记录发生变化,对应的交易id就会赋值给trx_id隐藏列。roll_pointer:每修改一条引用记录,就会将旧版本写入undolog,然后这个隐藏列就相当于一个指针,通过它可以找到该记录修改前的信息。架构概述从MySQL5.5版本开始,默认使用InnoDB存储引擎。擅长事务处理,具有崩溃恢复特性,在日常开发中应用广泛。下面是InnoDB架构图,左边是内存结构,右边是磁盘结构。内存架构在左侧的内存结构中,主要分为四大块:BufferPool、ChangeBuffer、AdaptiveHashIndex、LogBuffer。让我们来介绍一下这四个部分。BufferPoolInnoDB存储引擎是基于磁盘文件存储的,访问物理硬盘和在内存中访问,速度差别很大,为了尽可能弥补两者在I/O效率上的差异,它是有必要将经常使用的数据加载到缓冲池中,以避免每次访问都进行磁盘I/O。在InnoDB的缓冲池中,不仅缓存了索引页和数据页,还包括了undopages、insertcaches、adaptivehashindexes、InnoDBlock信息。缓冲池BufferPool是主存中的一块区域,可以缓存磁盘上频繁操作的真实数据。在进行增删改查操作时,先对缓冲池中的数据进行操作(如果缓冲池中没有数据,则从磁盘中加载并缓存),然后以一定的频率刷新到磁盘中,从而减少磁盘IO并加快处理速度。缓冲池的单位是Page,底层使用链表数据结构来管理Page。根据状态,Page分为三种:freepage:空闲页面,未使用。cleanpage:页面被使用,数据未被修改。Dirtypage:脏页,页面被使用,数据被修改,里面的数据和磁盘上的数据不一致。在专用服务器上,最多80%的物理内存通常分配给缓冲池。参数设置:showvariableslike'innodb_buffer_pool_size';mysql>showvariableslike'innodb_buffer_pool_size';+------------------------+----------+|变量名|值|+------------------------+----------+|innodb_buffer_pool_size|134217728|+------------------------+------------+1rowinset(0.00sec)ChangeBufferChangeBuffer,改变缓冲区(针对非唯一二级索引页),在执行DML语句时,如果这些数据页不在BufferPool中,则不会直接操作磁盘,但数据会发生变化更改缓冲区中的缓冲区。当以后的数据被读取时,会将数据合并并恢复到BufferPool中,然后合并后的数据会刷新到磁盘中。ChangeBuffer是什么意思?我们先看一张图,是二级索引的结构图:与聚集索引不同,二级索引通常是非唯一的,二级索引的插入顺序是比较随机的。同样,删除和更新可能会影响索引树中不相邻的二级索引页面。如果每次都操作磁盘,会造成大量的磁盘IO。通过ChangeBuffer,我们可以在缓冲池中进行merge处理,减少磁盘IO。AdaptiveHashIndex自适应哈希索引,用于优化BufferPool数据的查询。MySQL的innoDB引擎虽然不直接支持哈希索引,但是它为我们提供了一个功能,就是这种自适应哈希索引。前面我们提到,哈希索引在进行等价匹配时一般性能要高于B+树,因为哈希索引一般只需要一次IO,而B+树可能需要多次匹配,所以哈希索引的效率较高,但是hash索引不适合范围查询,模糊匹配等,InnoDB存储引擎会监控表上每个索引页的查询。如果观察到哈希索引在一定条件下可以提高速度,就会建立哈希索引,称为自适应哈希索引。自适应哈希索引,无需人工干预,由系统根据情况自动完成。参数:adaptive_hash_indexLogBufferLogBuffer:日志缓冲区,用于保存要写入磁盘的日志数据(redolog,undolog),默认大小为16MB,日志缓冲区中的日志会周期性的刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘I/O。参数:innodb_log_buffer_size:缓冲区大小innodb_flush_log_at_trx_commit:日志刷盘时,取值主要包括以下三个:1:每次事务提交时,日志写入并刷盘,默认值。0:日志每秒写入并刷新到磁盘一次。2:日志在每次事务提交后写入,每秒刷新一次到磁盘。mysql>showvariableslike'innodb_flush_log_at_trx_commit';+--------------------------------+-------+|变量名|值|+----------------------------+--------+|innodb_flush_log_at_trx_commit|1|+--------------------------------+--------+1组中的行(0.00sec)diskstructure接下来我们看InnoDB架构右边的部分,也就是diskstructure:SystemTablespacesystemtablespace是changebuffer的存储区域。如果表是在系统表空间而不是file-per-table或通用表空间中创建的,它还可能包含表和索引数据。(在MySQL5.x版本中还包括InnoDB数据字典、undolog等)参数:innodb_data_file_pathmysql>showvariableslike'innodb_data_file_path';+-----------------------+------------------------+|变量名|值|+---------------------+---------------------+|innodb_data_file_path|ibdata1:12M:autoextend|+----------------------+------------------------+1rowinset(0.00sec)系统表空间,默认文件名为ibdata1。File-Per-Table表空间如果打开innodb_file_per_table开关,则file-per-table表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。开关参数:innodb_file_per_table,该参数默认开启。mysql>showvariableslike'innodb_file_per_table';+------------------------+--------+|变量名|值|+--------------------+--------+|innodb_file_per_table|ON|+----------------------+--------+1rowinset(0.00sec)也就是说,每次我们创建一个表,会生成一个表空间文件,如图:GeneralTablespaces表空间,需要通过CREATETABLESPACE语法创建一个通用表空间,创建表时可以指定表空间。A.创建表空间CREATETABLESPACEts_nameADDDATAFILE'file_name'ENGINE=engine_name;mysql>CREATETABLESPACEts_iheimaADDDATAFILE'myitheima.ibd'ENGINE=innodb;QueryOK,0rowsaffected(0.00sec)B.创建时指定表表空间CREATETABLExxx...TABLESPACEts_name;mysql>createtablea(idintprimarykeyauto_increment,namevarchar(10))engine=innodbtablespacets_itheima;QueryOK,0rowsaffected(0.01sec)UndoTablespacesundotablespace,MySQL实例在初始化时,会自动创建两个默认的undo表空间(初始大小16M),用于存放undolog日志。临时表空间InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。DoublewriteBufferFiles双写缓冲,innoDB引擎在将BufferPool中的数据页刷新到磁盘之前,先将数据页写入双写缓冲文件中,便于系统异常时的数据恢复。RedoLog重做日志是用来实现事务持久化的。日志文件由两部分组成:重做日志缓冲区(redologbuffer)和重做日志文件(redolog),前者在内存中,后者在磁盘中。事务提交后,所有的修改信息都会保存在日志中,用于刷脏页到磁盘出错时的数据恢复。以涉及两个文件的循环方式写入重做日志文件:-rw-r-----。1mysqlmysql5033164810月2日22:52ib_logfile0-rw-r-----。1mysqlmysql50331648October222:52ib_logfile1前面我们介绍了InnoDB的内存结构和磁盘结构,那么我们在内存中更新的数据是如何到达磁盘的呢?此时,涉及到一组后台线程。下面介绍一下InnoDB涉及的一些后台线程。InnoDB后台线程中后台线程分为四类,分别是:MasterThread、IOThread、PurgeThread和PageCleanerThread。MasterThread核心后台线程负责调度其他线程,同时负责将缓冲池中的数据异步刷新到磁盘以保持数据一致性,包括刷新脏页、合并插入缓存、回收undo页等。IOThread在InnoDB存储引擎中大量使用了AIO来处理IO请求,可以极大的提升数据库的性能,而IOThread主要负责这些IO请求的回调。默认线程类型数职责Readthread4负责读操作Writethread4负责写操作Logthread1负责将日志缓冲区刷新到磁盘Insertbufferthread1负责将写缓冲区的内容刷新到磁盘我们可以查看InnoDB通过以下命令获取Status信息,其中包括IOThread信息。显示引擎innodb状态;PurgeThread主要用于回收事务已经提交的undolog。事务提交后,undolog可能用不到,所以用来回收。PageCleanerThread辅助MasterThread将脏页刷新到磁盘线程,可以减轻MasterThread的工作压力,减少阻塞。如果本文对您有帮助,请关注并点赞;有什么建议也可以留言或私信。您的支持是我坚持创作的动力。转载请注明出处!
