InnoDB 存储引擎<一>InnoDB简介与MySQL存储架构及相干数据布局 ...

打印 上一主题 下一主题

主题 1020|帖子 1020|积分 3060

目录

回顾MySQL架构
 InnoDB简介
​MySQL存储布局

回顾MySQL架构


   对MySQL架构图的总结:
        MySQL服务器是以网络服务的方式对外提供数据库服务的,我们使用的应用程序以及客户端统称为外部程序。
        外部程序通过发送网络请求的方式来连接MySQL服务器,这时起首每一个连接都会到MySQL架构中的连接层进行身份校验,比如用户名和密码是否正确,还会进行一些关于服务器自身连接限制的校验等。
         通过校验后,这个请求会被转发到服务层,由具体的实验线程来处理用户的一些交互,如发送一些sql语句,这些sql语句会通过SQL interface来接收,在接收后服务层会对这些文本情势的sql语句进行解析,把关键字等解析出来,如对于一个查询,解析出来表,字段以及where条件等,在解析工作完成后,mysql会把这些sql语句做一些优化,优化为它认为服从最高的情势,最终实验一些预操作,预查询,形成一些sql指令
        这些指令会被发送到存储引擎上,在存储引擎中做一些处理。对于存储引擎层是有许多种差异的存储引擎,每一种存储引擎都有自己的特性,可以根据存储引擎的特性以及联合应用程序的具体使用场景来选择恰当应用程序的存储引擎,帮助我们处理数据,其中有些数据是要现实落盘的,有些是要在内存中存储的,有些是以文本的情势来进行保存的,有些以B+树来组织的等等
        当要真正落盘时,就会与文件系统层进行交互,把要落盘的数据按照自己组织数据的方式写到磁盘文件中进行保存,如Data目录中的表空间文件中
       对于查询,存储引擎层也会通过一个检索的过程从磁盘文件中把数据检索出来,然后再逐层向上返回,最终返回给客户端,就完成一个整个数据库的交互
  
  在MySQL架构中焦点的层有服务层和存储引擎层,服务层重要完成与用户的交互,接受用户的请求,存储引擎层则是重要完成处理数据,组织数据
  
  在平时使用数据库时,真正处理数据,组织数据,保证查询服从,保证数据安全,保证数据落盘时使用到的都是存储引擎
  对于下面内容的介绍都是通过这6个方面进行介绍的,以达到
      以问题的情势引导,通过分析如何解决问题,从⽽明确MySQL的实现过程          分析对于解决问题的过程中引发的新问题,如何处理或规避   

 InnoDB简介

1.InnoDB存储引擎的由来
解答问题:
      InnoDB做为MySQL的默认存储引擎,实在并不是MySQL开辟的,⽽是由    Innobase Oy    公司所开辟,2006年五⽉时由甲⻣⽂公司并购。这也是MySQL做为⼀个开源数据库的长处之⼀,第三⽅开辟者可以根据⾃⼰的业务场景开辟出⾼性能的存储引擎,像    Innobase Oy    公司开辟的InnoDB,⼀旦被官⽅采取,那么就大概通过被收购从⽽得到可观的收⼊,官⽅的产品也得到了有用的扩展,是⼀个双赢的结果。          开源社区有许多,除了MySQL之外,常⻅的还有Linux,Java,Android,开辟都通过社区交流并贡献⾃⼰的技术,渐渐完善各种应⽤场景下的技术⽀持,如今开辟过程中使⽤的许多框架和中间件都得益与此   

2. MySQL为什么默认使⽤InnoDB存储引擎?
   分析过程:这个问题也可以说是InnoDB存储引擎的长处或者InnoDB与MyISAM的区别
  解答问题:
     InnoDB在设计时思量到了处理巨⼤数据量时的性能,InnoDB⽀持事务(transaction)、回滚        (rollback)而且具有崩溃修复的能⼒(crash recovery capabilities),通过多版本并发控制(multi-       versioned concurrency control)减少锁定,同时还⽀持外键约束(FOREIGN KEY constraints),通过缓冲池在主内存中缓存数据从⽽提⾼查询性能,也可以每个表使⽤各⾃的独⽴表空间存储数据而且⽂件⼤⼩只受限于操作系统,由于InnoDB存储引擎存储数据量⼤,性能⾼,可以有用的保证数据安全等长处,在MySQL5.5版本之后成为默认的存储引擎   

   衍生问题:
     1.    InnoDB事务是什么?        2.    事务的回滚是什么?        3.    InnoDB崩溃修复如何处理?        4.    多版本并发控制是什么?        5.    锁分类都有哪些?        6.    缓冲池的作⽤及⼯作原理?        7.    独⽴表空间的作⽤及长处?       将在后面的内容中进行介绍    3.InnoDB存储引擎的架构⻓啥样?
   分析过程:这里可以参考官网的介绍
  传送门: InnoDB存储引擎架构链接
  解答问题:
     InnoDB重要包括内存布局和磁盘布局。   


   衍生问题:
  1.为什么要设计成内存布局和磁盘布局两个部分?
     我们从MySQL实现的⻆度来思考这个问题,数据库的作⽤就是保存数据,⽤⼾的真实数据最终都会保存在磁盘上,在查询数据的过程中,假如每次都从磁盘上读取会严峻影响服从,为了提⾼数据的访问服从,InnoDB会把查询到的数据缓存到内存中,当再次查询时,假如⽬标数据已经存在于内存中,就可以从内存中直接读取,从⽽⼤幅提升服从。          也就是说磁盘布局中的⽂件是⽤来保存数据实现数据持久化的,内存布局是⽤来缓存数据提升服从的。   

 4.使⽤InnoDB存储引擎创建的表对应的数据⽂件在哪⾥?
   前置知识:当创建一个数据库时,会在数据目录(工作目录)生成一个与数据库同名的子目录,内里包罗创建的表的数据文件
  

   分析过程:⽆论使⽤哪个存储引擎创建表,真实的数据都必须存储在磁盘或其他存储介质中
     解答问题:           当使⽤InnoDB存储引擎创建⼀个表时,默认会在数据⽬录对应的数据库⼦⽬录中⽣成相应的表空间⽂件(以表名为文件名),以     .ibd     为⽂件的后缀,⽤来存储数据和索引,假如每个表都对应⼀个表空间⽂件,称为独⽴表空间,在MySQL5.7及以后的版本中默认为每个表⽣成独⽴表空间,可以通过系统变量    innodb_file_per_table[=ON|OFF]     进⾏控制,假如关闭这个选项,则全部表的数据都在系统表空间中存储          独⽴表空间⽂件如下所⽰:      
 MySQL存储布局


对于MySQL存储布局可以明确为MySQL为了有用的维护数据而界说的一系列数据布局
1.什么是表空间⽂件?
   解答问题:
     表空间⽂件是⽤来存储表中数据的⽂件,表空间⽂件的⼤⼩由存储的数据(业务数据)多少决定,差异的表空间⽂件存储数据的种类也有所差异,在MySQL中表空间分为五类,包括:系统表空间、独⽴表空间、通⽤表空间、暂时表空间和撤销表空间,这些在上⾯的InnoDB架构图中都有表现。             衍⽣问题               1.表空间与表空间⽂件的关系是什么?                   表空间可以明确为MYSQL为了管理数据⽽设计的⼀种数据布局,重要形貌的对布局的界说,表空间⽂件是对界说的具体实现,以⽂件的情势存在于磁盘上                2.⽤⼾数据在表空间中是怎么存储的?
   分析过程:
     (1)⾸先明确⼀点,⽤⼾的数据以数据⾏的⽅式存储在对应的表空间⽂件中,那么表空间中许多个数据⾏就必要进⾏管理,以便后续进⾏⾼效的查询;          (2)为了⽅便管理,表空间由段 (segment)、区组(group)、区 (extent)、⻚ (page) 、数据⾏组成,其中⻚是 InnoDB 磁盘管理的最⼩单位;     为了更加方便明确段,区组,区,页,数据行,可以举一个小区中差异层次的概念

   解答问题:
     可以这么明确,若⼲数据⾏组成了⻚,多个⻚组成了区,多区组成了区组,多个区组组成了段,多个段组成了表空间             衍⽣问题               1.段 (segment)、区组(group)、区 (extent)、⻚ (page) 、数据⾏是如何管理起来的?              后面会具体介绍每个部分的作⽤,他们之间的关系和管理⽅式如下。           
 3.为什么要使⽤⻚这个数据管理单元? 
   分析过程:
     (1)⾸先要明确⼀点,MySQL中的⻚是应⽤层的⼀个概念,是MySQL根据⾃⾝的应⽤场景,界说的⼀种数据布局。          (2)通常操作系统中的⽂件系统在管理磁盘⽂件时以4KB⼤⼩为⼀个管理单元,称为"数据块",但是在数据库的应⽤场景⾥,查询时数据量都⽐较⼤,假如也使⽤4KB做数据存储的最⼩的单元,就显的有点⼩了,同时会造成频仍的磁盘I/O,导致降低服从;          (3)MySQL根据⾃⾝情况界说了⼤⼩为16KB的⻚,做为磁盘管理的最⼩单位,一次I/O读16KB,即磁盘与内存交互时,一次交互的为一页,一页多行数据         (4)假如现实上只必要查询一条数据,但是从磁盘上读取了16KB,会不会造成过度读取或者资源浪费?,现实上不会,原因为如下的局部性原理       每次内存与磁盘的交互⾄少读取⼀⻚,所以在磁盘中每个⻚内部的地址都是一连的,之所以这样做,是因为在使⽤数据的过程中,根据局部性原理,将来要使⽤的数据⼤概率与当前访问的数据在空间上是邻近的,所以⼀次从磁盘中读取⼀⻚的数据放⼊内存中,当下次查询的数据还在这个⻚中时就可以从内存中直接读取,从⽽减少磁盘I/O,提⾼性能              解答问题:               MySQL根据⾃⾝的应⽤场景使⽤⻚做为数据管理单元,最重要的⽬的就是减少磁盘I/O,提⾼性能。                 衍生问题:                   什么是局部性原理?                       局部性原理是指程序在执⾏时呈现出局部性规律,在⼀段时间内,整个程序的执⾏仅限于程序中的某⼀部分。相应地,执⾏所访问的存储空间也局限于某个内存地区,局部性通常有两种情势:时间局部性和空间局部性。                          时间局部性(Temporal Locality):假如⼀个信息项正在被访问,那么在近期它很大概还会被再次访问。                          空间局部性(Spatial Locality):将来要⽤到的信息⼤概率与正在使⽤的信息在空间地址上是邻近的                      4. 数据⻚有哪些基本特性是必须要掌握的? - ⻚
   解答问题:
     (1)⻚的16KB的⼤⼩是MySQL的⼀个默认设置,可以适⽤于⼤多数场景,固然也可以根据⾃⼰的现实业务场景(根据焦点表中的数据行巨细)进⾏修改⻚的⼤⼩,通过系统变量    innodb_page_size    进⾏调整与检察,在调整⻚⼤⼩的时候必要保证设置的值是操作系统"数据块" 4KB的整数倍,从⽽保证通过操作系统和磁盘交互时"数据块"的完备性,不被分割或浪费,所以规定了    innodb_page_size    可以设置的值,分别是    4096    、    8192    、    16384    、    32768    、    65536    ,对应    4KB    、    8KB    、    16KB    、    32KB    、   64KB    ;       (2)   每⼀个⻚中纵然没有数据也会使⽤ 16KB   的存储空间,即当数据页写满后,若要创建新的数据页,就会一次性在磁盘上申请一个一连的空间,巨细为16KB,当有数据写入表中时,就会找到空闲的或当前使用的页进行填充数据,填满了就再去申请,以此类推       同时与索引的B+树中的节点对应,后续会   具体讲解B+树的内容,检察⻚的⼤⼩,可以通过系统变量    innodb_page_size    检察   
  1. mysql> SHOW VARIABLES LIKE 'innodb_page_size';
  2. +------------------+-------+
  3. | Variable_name | Value |
  4. +------------------+-------+
  5. | innodb_page_size | 16384 | # 16KB
  6. +------------------+-------+
  7. 1 row in set, 1 warning (0.04 sec)
复制代码
  (3) 在差异的使⽤场景中,⻚的布局也有所差异,在MySQL中有多种差异范例的⻚,但不论哪种范例的⻚都会包罗⻚头(File Header)和⻚尾(File Trailer),在这⻚头和⻚尾之间的⻚主体信息根据差异的范例有差异的布局,最常⽤的就是⽤来存储数据和索引的"索引⻚",也叫做"数据⻚",⻚的主体信息使⽤数据"⾏"进⾏填充,⻚的基本布局如下图所⽰:
  
 

 5.查询的数据高出⼀⻚的⼤⼩,怎么提⾼查询服从 ?区
   前置知识:
  由上面的内容得知,磁盘中每个⻚内部的地址都是一连的,而且页是内存与磁盘之间交互的最小单位,每访问一个数据页就会发生一次磁盘IO,那么当进行范围查询/where条件中进行or查询时,就有大概访问多个数据页,发生多次磁盘IO
     分析过程:       (1)   差异的⻚在磁盘中是不是一连的呢?           答案是不⼀定,在不做任何控制的情况下,是一种随机的情势,这就导致差异⻚在磁盘中申请的地址⼤概率是不一连的。           我们可以很快的分析出来一连的地址对查询服从的影响,假如⻚在磁盘中可以被一连读取,那么查询服从就⾼,否则果询服从就低。             (2)为什么不一连的地址会降低查询的服从?               当存储介质是机械硬盘时,访问不一连的地址会带来磁盘寻址的开销,也就是磁头在差异盘⾯、磁道和扇区的机械转动,这个过程称为磁盘随机访问,⾮常影响服从,磁盘布局如下:           

对磁盘布局的简要介绍
磁盘面是存储数据的,多个磁盘面通过转轴连接在一起,转轴以固定的方式旋转从而带动全部的磁盘面进行旋转,同时机械臂杆为每个磁盘面配置了一个读写磁头,通过磁头就可以把盘面上的数据读到缓冲区,让操作系统读走
      经过以上的分析,当查询的数据⼤于⼀⻚时不加任何控制会产⽣磁盘随机访问,这个是影响查询服从的重要因素,那么如今怎么提⾼查询服从的问题就变成了,⻚在磁盘中是否一连的问题         (3)InnoDB如何保证⻚在磁盘中的一连性?           为相识决磁盘随机访问⾮常低效的问题,必要尽大概在磁道上读取一连的数据,减少磁头的移动,从⽽提升服从,MySQL使⽤ Extent(区) 这个布局来管理⻚,规定每个区固定⼤⼩为     1MB     ,可以存放     64     个⻚,这时假如跨⻚读数据时,⼤概率都在附近的地址,可以⼤幅减少磁头移动               同时,假如频仍的读取某个区中的⻚,可以把整个区都读取出来放⼊内存中,减少后续查询对磁盘的访问次数,进⼀步提升服从           
 
   解答问题:
     通过对问题的分析,我们相识到InnoDB中⽤来组织⻚的数据布局--区,而且每个区固定⼤⼩为   1MB    ,可以包罗64个一连的⻚,查询的数据高出⼀⻚⼤⼩时,大概会有以下⼏种情况:        a.    ⻚在区内是相邻的:磁盘顺序I/O,可以⼤幅提升服从        b.    ⻚在区内但不是相邻的:可以⼤幅减少碰头移动,可以提升服从        c.    ⻚在差异的区:还是要发⽣随机I/O,不能提升服从       衍⽣问题:
     那么⼜有⼀个问题来了,新创建表时没有数据,或者说有的表只有很少的数据,1MB的空间⽤不完,那不是就存在空间浪费的问题吗?        的确是这样,InnoDB在设计时也思量到了这个问题,我们继续提出问题,然后再来解决。         总结:           1.区的特点:每个区固定⼤⼩为     1MB           2.    区和⻚的关系           区是⽤来管理⻚的⼀种数据布局,其中包罗若⼲个⻚,从⽽保证⻚与⻚之间的一连性       6.当表中的数据很少时如何制止空间浪费? 
      分析过程:           1.当创建表时,并不知道当前表的数据量级           2.为了节流空间,最初只创建7个初始⻚(在MySQL5.7中创建6个初始⻚),⽽不是⼀个完备的区,可以通过以下SQL检察:      
  1. mysql> select * FROM information_schema.INNODB_TABLESPACES WHERE name =
  2. 'test_db/student'\G
  3. *************************** 1. row ***************************
  4. SPACE: 13
  5. NAME: test_db/student
  6. FLAG: 16417
  7. ROW_FORMAT: Dynamic
  8. PAGE_SIZE: 16384 # ⻚⼤⼩
  9. ZIP_PAGE_SIZE: 0
  10. SPACE_TYPE: Single
  11. FS_BLOCK_SIZE: 65536
  12. FILE_SIZE: 114688 # 数据⽂件初始⼤⼩
  13. ALLOCATED_SIZE: 114688
  14. AUTOEXTEND_SIZE: 0
  15. SERVER_VERSION: 8.0.33
  16. SPACE_VERSION: 1
  17. ENCRYPTION: N
  18. STATE: normal
  19. 1 row in set (0.01 sec)
  20. # 根据数据⽂件⼤⼩和每⻚⼤⼩计算出⻚数
  21. # 114688 / 16384 = 7 个数据⻚
复制代码
  3. 这些零星⻚会放在表空间中⼀个叫碎⽚区的地区,随着数据量的增加,会申请新的⻚来存储数据,当碎⽚区达到32个⻚的时候,后续每次都会申请⼀个完备的区来存储更多的数据;
  
 
   解答问题:通过零星⻚和碎⽚区制止空间浪费的问题 
   7.假如访问的数据跨区了怎么办?--区组
   分析过程:
  1.当创建一个区时,要把这个区对应的自界说属性记录下来,包罗区的偏移量,区管理数据的范围,再用双向链表把区组织起来
  2.差异的区在磁盘上⼤概率是不一连的,那么这个问题实在是InnoDB如何⾼效的的管理区?
     当表中的数据越来越多,为了有用的管理区,界说了区组的布局,每个区组固定管理256个区即   256MB    ,通过区组可以在物理布局层⾯⾮常⾼效的管理和定位到每个区,对于区组也必要管理自身属性,包罗区组管理数据的范围,然后再用双向链表把区组也组织起来   

    3.第⼀个区组中的⾸个区的前四⻚⽐特别,也就是初始⻚中的前4⻚,分别是:
     File Space Header: 表空间和区组中条⽬信息        Insert Buffer Bitmap:Change Buffer相干信息        File Segment inode: 段信息        B-tree Node:索引根信息        其他为空闲⻚⽤来存储真实的数据           4.其他区组中⾸个区的布局都⼀样,前两个⻚分别是:           Extent Descriptor(XDES):区组条⽬信息           Insert Buffer Bitmap:Change Buffer相干信息             解答问题:         使⽤区组布局有用的管理区,每个区组固定管理256个区即      256MB      ,区组条⽬信息中会记录每个区的偏移并⽤双向链表连接                 衍生问题:             如何定位要查询的⽬标⻚?----后续内容说明           8.以上这些数据布局还有优化的空间吗?段
   分析过程:
  1.以上讲到的区、区组还有⻚这种都是物理布局,在磁盘上有对应的空间巨细
  2.在物理布局的基础上,界说了⼀个逻辑上的概念,也就是"段"
     "段"并不对应表空间中的一连的物理地区,可以看做是 "区" 和 "⻚" 的⼀个附加标注信息,段的重要作⽤是区分差异功能的区和在碎⽚区中的⻚,重要分为"叶⼦节点段"和"⾮叶⼦节点段"等,这两个段和我们常说的B+树索引中的叶⼦、⾮叶⼦节点对应,可以简单的明确为"⾮叶⼦节点段" 存储和管理索引树,"叶⼦节点段"存储和管理现实数据,从逻辑上讲,最终由 "叶⼦节点段" 和 "⾮叶⼦节点段" 等段构成了表空间    .ibd    ⽂件,如下图所⽰   

   解答问题 :
     InnoDB使⽤"段"这个逻辑布局区分差异功能的区和在碎⽚区中的⻚,并按功能分        为"叶⼦节点段"和"⾮叶⼦节点段",做为B+树索引中的叶⼦、⾮叶⼦节点,从⽽进⼀步提升查询服从       以上就是InnoDB存储引擎管理数据时使⽤的⼀些数据布局         衍⽣问题:       1.   上⾯讲的全部操作是在哪⾥进⾏的?           全部的数据库操作都是在内存中进⾏的,最终会把修改结果刷回磁盘中对应的⻚中          2.查询数据时MySQL会⼀次把表空间中的数据全部加载到内存吗?               固然不是,使⽤InnoDB存储引擎创建表,在查询数据时会根据表空间内部界说的数据布局(⼀般为索引),定位到⽬标数据⾏所在的⻚,只把符合查询要求的⻚加载到内存             3.每查询⼀条数据都要进⾏⼀次磁盘I/O吗?                   不⼀定,每次查询都会把磁盘中数据⾏对应的数据⻚加载到内存中,假如当前查询的数据⾏已经在内存中,则直接从内存中返回结果,从⽽提⾼查询服从                     总结:                       1.段是⼀个逻辑概念,作⽤是管理差异功能的区和碎⽚区中的⻚。                    2.       段重要分为"叶⼦节点段"和"⾮叶⼦节点段",对应索引中的叶⼦、⾮叶⼦节点。                      以上数据布局之间的联系图 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表