MySQL InnoDB Architecture 简要介绍
MySQL InnoDB 存储引擎整体架构图:
一、内存存储结构
1、Buffer Pool
buffer pool 是主内存中的一块儿存储区域,用于存储访问的表及索引数据。这样从内存中直接访问获取使用的数据可以极大的提升访问效率。在一些特殊专用的服务里,几乎 80% 的内存区域都被赋于 buffer pool。
为了提升大数据量读操作效率,buffer pool 被设计划分为能够存储多条记录的数据页。同时,基于链表结构存储实现,LRU算法支持,能够极大的提高缓存管理的效率。
Buffer Pool LRU 算法
buffer pool 使用基于LRU算法的列表数据结构实现。当需要添加新的数据页,最近最少使用的数据页会淘汰,新的数据页会被插入到列表的中间。
中间插入策略会把列表当成两个子列表:
头部用于存储新的最新访问的数据页。
尾部用于存储旧的最少访问的数据页
如下图:Buffer Pool List
算法会将频繁访问的数据页放在新的子列表;最少访问的记录存放在旧列表,并逐渐淘汰。
通常 LRU 算法按如下方式运行:
buffer pool 总量的 3/8 会分配给旧列表。
列表的中间包括新列表的尾部和旧列表的头部。
当 InnoDB 读入一个新的数据页时,会先将其插入列表中间(旧列表的头部)。
旧的子列表数据访问会改变其数据特性,并将其移动到新的子列表头部(预读操作除外)。
- 随着数据库操作的执行,buffer pool 中未被访问的页数据会逐渐移动到列表的尾部,并淘汰。
通常情况下,被访问的数据会转移到新的子列表,这样就能在 buffer pool 中待更长的时间。一些特定的情景,如 mysqldump 操作导致的表扫描或者没有附加 where 条件的 select 查询会导致大量的数据写入 buffer pool,并淘汰旧的记录。但是这些新的记录可能永远不会被使用。
2、Change Buffer
change buffer 用于缓存那些不在 buffer pool 存储的二级索引页数据变化。并最终会合并到 buffer pool(当这些页数据被其它读操作载入后)。
如下入示意 Change Buffer:
和聚簇索引不同的是,二级索引通常都非唯一,并且写入顺序随机。同样的,删除和更新操作可能会影响不相邻的多个索引页数据。因此,在其它读操作将受影响的索引页数载入 bufer pool 时合并缓存的索引变更,可以避免再次从磁盘随机IO读取二级索引页数据。
purge operation 会周期性的把更新的页数据批量写入磁盘,这样比即时单条写入更有效率。
当涉及二级索引变更记录比较多时,Change buffer 数据合并可能会花费几个小时。在此期间,磁盘 IO 会增加,进而会影响磁盘密集型查询。
在内存中,change buffer 会占用一部分的 buffer pool 存储使用。在磁盘里,change buffer 是 system tablespace 的一部分,用以存储数据库服务器关机时产生的索引变化数据。
3、 Adaptive Hash Index
自适应哈希索引使得 InnoDB 支持基于内存的数据库,通过 innodb_adaptive_hash_index
配置启用。
基于当前的搜索模式,哈希索引使用索引键前缀来构建。前缀可长可短,根据实际查询需求而定。
4、Log Buffer
存储内存日志数据,用于磁盘日志文件数据写入。配置:innodb_log_buffer_size。默认大小 16MB。log buffer 的数据会周期性的刷盘。较大的 log buffer 有利于较大的事务日志数据写入需求。对于执行大批量更新、写入或删除操作的事务可以适当调高 log buffer 以减少磁盘IO。
二、磁盘存储结构
1、Index 索引
a)聚簇索引及二级索引
基于 InnoDB 引擎的表使用一种称之为聚簇索引的特殊索引来存储行数据。通常情况下,聚簇索引等同于主键索引。
- InnoDB 会使用表上定义的主键来作为聚簇索引,如果当前表没有能够作为主键的列(数据逻辑唯一非空的单列或者多列组合),则可以添加自增列作为非业务主键。
- 如果表未定义主键,则 InnoDB 会使用首个唯一索引(所有列非空)作为聚簇索引。
- 如果表既没有主键也没有合适的唯一索引,则 InnoDB 会为表创建一个隐藏的聚簇索引 GEN_CLUST_INDEX,该索引基于 InnoDB 为表自动添加的包含行ID值的列,所有表数据会基于该ID值排序。行ID值是一个6字节数值,会随着数据的插入单调递增,因此基于此列排序的表在物理上保持着数据插入顺序。
除了聚簇索引,其它的索引都是二级锁索引,二级索引除了设置的索引列外,还包含主键,最终 InnoDB 都要通过主键来查找聚簇索引里的数据。
如果主键过长,那么二级索引就会占用更大的空间,所以,通常我们都建议设置较短的主键。
B 树索引使用:
- 支持列 =、>、>=、<、<= 及 BETWEEN 操作。
- like 操作支持:like 后面的参数需要为常量并且不能以通配符起始。
//可以命中索引
SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%'; //无法使用索引
SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
SELECT * FROM tbl_name WHERE key_col LIKE other_col;
- 对于 is NULL 条件,如果条件列有索引,则查询会使用到索引。
- 对于多列复合索引,如果要使用它们,则在每一个 and 条件分组里都必须使用它们:
如下使用到了索引:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3 /* index = 1 OR index = 2 */
... WHERE index=1 OR A=10 AND index=2 /* optimized like "index_part1='hello'" */
... WHERE index_part1='hello' AND index_part3=5 /* Can use index on index1 but not on index2 or index3 */
... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3; 如下未使用到索引 /* index_part1 is not used */
... WHERE index_part2=1 AND index_part3=2 /* Index is not used in both parts of the WHERE clause */
... WHERE index=1 OR A=10 /* No index spans all rows */
... WHERE index_part1=1 OR index_part2=10
- 一些特殊情况,如优化器测算使用索引会需要访问表中大量的数据,那么即使条件列命中了索引使用条件也不会使用索引。
b)InnoDB 索引物理结构
除了空间索引(基于 R-trees,用以组织存储多维数据),InnoDB 索引都是基于 B-tree 结构。数据存储于树的叶子结点。
索引数据页默认大小为 16KB,可以通过 mysql 实例初始化时的 innodb_page_size 参数来调整。
当向聚簇索引插入新的记录时,InnoDB 会保留1/16页空间用以应对将来可能的插入和更新。如果是顺序插入,则索引页空间会保持差不多15/16大小。如果是随机的,则页空间大小会在1/2 到 15/16之间。一般低于1/2(MERGE_THRESHOLD 配置)会触发索引树压缩。
c)Sorted Index Builds
InnoDB 使用 bulk load 方式执行索引创建或重建,我们称之为 Sorted index build(不支持空间索引)。
索引重建通常分为三步:
- 扫描聚簇索引,生成索引记录并添加到 sort buffer。sort buffer 满了之后,记录会被排序并写入一个临时的中介文件
- 随着多个第一步这个过程写入数据到临时中介文件,文件里的索引记录会执行合并。
- 排序的索引记录写入 B-tree。
在 Sorted index builds 引入之前,B-tree 索引写入使用特定的写入API。首先需要打开一个 B-tree 游标并找到写入位置,然后使用 optimistic 方式将索记录写入 B-tree。当遇到当前写入页满时,optimistic 会执行相应的 B-tree 节点的分裂或者合并操作来满足写入空间需求。这种自上而下的构建方式存在一定的缺点,包括寻址及经常性的节点分裂及合并成本。
Sorted index builds 基于自底而上的方式来构建索引。从 B-tree 每层最右侧的叶子节点开始,基于索引记录顺序写入。当一个节点页写满,则向其父节点添加一个新的子节点用于新的写入。
2、table space 表空间
system table space |
用以存储包括 InnoDB data dictionary、the doublewrite buffer、the change buffer 及 undo logs,也可以存储用户主动创建于此的表及索引数据。 可以有一个或多个数据存储文件,默认为一个 ibdata1,大小和数量可以通过 |
File-Per-Table Tablespaces |
file-per-table tablespace 包括一张表的数据和索引,以单个数据文件形式存储在文件系统。
file-per-table tablespace 数据文件形式 table_name.ibd,存储于 MySQL data 文件夹下。 优势:
劣势:
|
General Tablespaces | 共享的 InnoDB 表空间。 |
Undo Tablespaces | undo logs 存储。 |
The Temporary Tablespace | 非压缩的,用户创建的临时表及磁盘上的内部临时表存储。 |
3、double buffer
具体介绍见前文链接:mysql 优化之 doublewrite buffer 机制
4、Redo Log
redo log 是一种基于磁盘的数据结构,用于修正数据库崩溃恢复期间未完成事务造成的数据脏写。
redo log 磁盘存储数据文件为 ib_logfile0
和 ib_logfile1
,MySQL 以环形方式写入。
配置修改:1、配置文件 my.cnf;2、大小 innodb_log_file_size
;3、数量:innodb_log_files_in_group
.
5、Undo logs
记录单个事务中的一系列记录变更,用以恢复对聚簇索引记录的最新变更。如果有其它事务基于一致性读操作需要查看原始数据,可以从 undo log 记录里查询。
6、InnoDB Data Dictionary
包括一系列系统表,存储包括表、索引及表列等相关元数据,物理存储在系统表空间。由于一些历史原因,data dictionary metadata 部分存储在 InnoDB 表空间文件 (.frm
files)。
MySQL InnoDB Architecture 简要介绍的更多相关文章
- mysql innodb存储引擎介绍
innodb存储引擎1.存储:数据目录.有配置参数为“ innodb_data_home_dir ” .“ innodb_data_file_path ” 和 “innodb_log_group_ho ...
- MySQL · 引擎特性 · InnoDB 事务子系统介绍
http://mysql.taobao.org/monthly/2015/12/01/ 前言 在前面几期关于 InnoDB Redo 和 Undo 实现的铺垫后,本节我们从上层的角度来阐述 InnoD ...
- MySQL InnoDB Cluster介绍
目录 一.MySQL InnoDB Cluster介绍 二.环境准备 三.将MGR节点加入MySQL Cluster 四.问题汇总 五.性能测试 六.个人总结 一.MySQL InnoDB Clust ...
- Mysql InnoDB 共享表空间和独立表空间
前言:学习mysql的时候总是习惯性的和oracle数据库进行比较.在学习mysql InnoDB的存储结构的时候也免不了跟oracle进行比较.Oracle的数据存储有表空间.段.区.块.数据文件: ...
- Mysql InnoDB行锁实现方式(转)
Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...
- Mysql InnoDB行锁实现方式
Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...
- 从一个死锁看mysql innodb的锁机制
背景及现象 线上生产环境在某些时候经常性的出现数据库操作死锁,导致业务人员无法进行操作.经过DBA的分析,是某一张表的insert操 作和delete操作发生了死锁.简单介绍下数据库的情况(因为涉及到 ...
- 大并发大数量中的MYSQL瓶颈与NOSQL介绍
NoSQL在2010年风生水起,大大小小的Web站点在追求高性能高可靠性方面,不由自主都选择了NoSQL技术作为优先考虑的方面.今年伊始,InfoQ中文站有幸邀请到凤凰网的孙立先生,为大家分享他之于N ...
- MySQL InnoDB 修改表列Online DDL
概述 一般来说数据库结构一经设计,不能轻易更改,因为更改DDL(Data Definition Language)操作代价很高,所以在进行数据库结构设计时需要谨慎. 但是业务发展是未知的,特别是那些变 ...
- 搞懂MySQL InnoDB事务ACID实现原理
前言 说到数据库事务,想到的就是要么都做修改,要么都不做.或者是ACID的概念.其实事务的本质就是锁和并发和重做日志的结合体.那么,这一篇主要讲一下InnoDB中的事务到底是如何实现ACID的. 原子 ...
随机推荐
- MacOS 使用UnblockNeteaseMusic解锁网易云灰色歌曲(主要是想听杰伦)
最近想听杰伦的音乐 但是网易云木有版权 于是在github上找到了UnblockNeteaseMusic这个项目 不多废话 直接上教程! 第一步 找到该项目的地址 并使用git克隆到本地: https ...
- JVM-创建一个对象的详细过程
Person person=new Person(): 1.现在栈中申请一个自己的栈空间 2.类加载检查 每当使用new操作符创建一个对象时,类加载器都会从常量池中寻找该对象的符号引用,如果找到,则根 ...
- Nginx常用经典配置|反向代理、HTTPS重定向、端口转发
二级目录映射 目前前后端项目分离场景多了以后,一般是前端一个端口,后端一个端口. 如前端是https://example.com/index.html,调用的接口是https://example.co ...
- 持续集成环境(2)-Jenkins插件管理
Jenkins本身不提供很多功能,我们可以通过使用插件来满足我们的使用.例如从Gitlab拉取代码,使用 Maven构建项目等功能需要依靠插件完成.接下来演示如何下载插件. 修改Jenkins插件下载 ...
- MySQLdb安装
yum seach MySQL-Python sudo yum install MySQL-python.x86_64 import MySQLdb
- EL表达式 总结
EL表达式,全称是Expression Language.意为表达式语言.它是Servlet规范中的一部分,是JSP2.0规范加入的内容.其作用是用于在JSP页面中获取数据,从而让我们的JSP脱离ja ...
- IBM 双队列管理器,双向传输
1. 建立队列管理器 建立[test01][test02]两个队列管理器,一直下一步即可,端口号不能一致(需要记住设置的端口号,后面会用到) [test01]端口号 1414 [test02]端口号 ...
- 虚拟环境 venv的使用--(venv 一)
一.引言最近在学习<Flask Web Development 2nd Edition>的时候,作者开篇就介绍如何使用 venv 来管理 Python 环境 .自我觉得作者讲的非常好,想要 ...
- 在Vim编辑器中查找选定文本
按照任意选定文本查找: 1. 进入visiual模式选定文本, 按 y 键复制: 2. 按 / 键进入查找模式: 3. 按 Ctrl + r 打开vim寄存器: 4. 按 " 键将寄存器内容 ...
- Spring--案例:测试业务层接口万次执行效率
案例来袭 这样,并不能够分辨出哪个的效率是哪个 可以利用pjp进行这样的操作: 结果: