MySQL笔记六-innodb引擎的关键特性
时间:2021-07-11
本文章向大家介绍MySQL笔记六-innodb引擎的关键特性,主要包括MySQL笔记六-innodb引擎的关键特性使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本节内容同 MySQL笔记六-innodb存储引擎是一起的,由于内容比较多,排版不想弄,就单独放一节,但是大序号不变,都是六
insert buffer
insert buffer需要满足的条件 :insert的 索引是非唯一辅助索引。
什么是insert buffer?简单的说就是当insert一条数据,在更新辅助索引树时,如果需要插入的数据页不在内存里,则将数据放到insert buffer里,并返回insert成功(实际上没有),等到一定条件下,将多个insert命令一起执行,减少与磁盘的交互,提高insert性能。
为什么需要insert buffer?由于主键一般是自增的,当insert一条数据时是按照主键顺序存放,这是insert数据是很快的,因为只需要顺序存放即可。可是对于表中的辅助索引而言,insert的数据可就不是顺序的了,innodb需要一个个的比对索引数据的大小,再将索引数据存放在合适的位置(这里插入的不是数据,而是索引字段的数据和对应的主键值),如果每一条数据都插入都落盘,就存在大量的随机io,将严重的拖慢insert速度,更严重的是一张表上很可能不止一个辅助索引,更更严重的是,还会存在页分裂,这都会对insert效率产生负面的影响。所以,需要insert buffer
insert buffer 为何需要满足以上的条件 以上的条件有两个关键,1,非唯一索引;2,辅助索引。
关于第一的关键点,假设索引是唯一的,那么再插入索引数据时,为了保证唯一性,需要将整个索引树的数据都遍历一遍,而此操作就会伴随着大量的io;问:这些io都是顺序io啊,辅助索引表的存放是顺序的,顺序io不是很快么。答,1,顺序io确实很快,但是如果数据量很大,即使是顺序io也会耗时久;2,既然已经把索引数据都load 进内存了,哪还有使用insert buffer的必要么,直接insert不就行了。
关于第二个关键点,假设不是辅助索引,那就是主键,主键都是有唯一性要求,同第一点要求。
PS:主键是UUID类型呢,那不是更不行,又唯一,又无序
insert buffer是怎么是实现的?insert buffer的实现是通过一颗 B+ tree实现,该树存放在共享表空间,即ibdata1里。它的非叶子节点的结构是,
space id
|
marker
|
offset
|
其中space id是表的唯一表示,marker是兼容老版本的标志,offset是表示该页的偏移量,这三个字段结合在一起称之为 search key。这个search key可以用于标识 某个具体的页。而非叶子节点的结构是
space id
|
marker
|
offset
|
metadata
|
secondary index record
|
前面三个字段一样,metadata字段记录了每个记录进入insert buffer的顺序。secondary index record 字段记录了实际insert的记录。
那么insert buffer的流程就是这样,一条insert sql进来,首先判断是否满足使用insert buffer的条件,是则生成对应的 search key,放进tree里,然后再将这条记放到这个search key下的叶子节点中。
什么时候merge insert buffer呢?
1,当辅助索引页被读到内存里时,这是可以去insert buffer B+ tree里查找是否有属于此页的insert buffer 记录,如果有则merge,等同与搭顺风车。
2,当辅助索引页空间紧张时,当检测到某个辅助索引页可用空间小于1/32时,需要强制将其读进内存进行页分裂,此时又可以搭便车
3,在Master thread 中会主动机进行merge insert buffer 操作,不同的是,此次merge会一次随机merge多个页,具体由srv_innodb_io_capacity参数控制。
ps 还有个特殊页名为 insert buffer bitmap,每个此种页追踪16384个辅助索引页,它会记录每个辅助索引页的剩余空间和是否有记录在insert buffer里。所以merge insert buffer 的三种场景其实都需要 insert buffer bitmap页参与,它很重要。
insert buffer 的发展 目前insert buffer已经升级成change buffer,innodb可以对DML操作,比如insert ,update,delete都进行缓存,对应的就是insert buffer,update buffer ,delete buffer,实现和关键都一样,就不深入了。其中提一嘴delete buffer,还记得之前提到过的隐藏字段么,每一行都有个类似is_delete的隐藏字段,当update/delete 删除一条数据时,实际上修改is_delete字段来标识删除,实际时通过purge thread 完成实际的删除操作。
doublewrite
什么是doublewrite 如果innodb正在写入某个页到表中时,发生宕机,此时页只写了一半,这种情况称之为 partial page write(部分写失效),是有可能导致数丢失的。crash recover时,由于页本身已经损坏,即使是rodo log页无法修复,因为redo log记录的是对页的物理操作,比如在page 1 offset 100的位置写 "a"
但此时页本身已经损坏,其他位置的数据已经丢失,所以仅有redo log无法修复。所以再使用redo log 恢复之前,需要先找到该页的副本,然后还原该页,最后再apply redo log恢复数据。这种操作就是 double write
为什么需要doublewrite 上文说了
怎么实现 doublewrite? doublewrite 由两部分组成,第一部分是 doublewrite buffer,大小是2MB,这是在内存里的。第二部分在共享表空间里,大小也是2MB,这是在磁盘里的。当需要flush dirty page时,不是直接刷进磁盘,而是通过 memcpy 函数将脏页 cpoy到 doublewrite buffer里,这是内存操作,很快;然后通过doublewrite buffer分两次,每次1MB的,顺序的将数据写入共享表空间,这是顺序写,也很快;最后立即调用fsync函数刷新磁盘,这是随机写,就慢了,注意fsync到磁盘的数据是 doublewrite buffer里的数据,不是原来脏页里的数据。如果发生宕机导致页损坏,就可以使用共享表空间里的数据来恢复数据页,然后用redo log 恢复数据。
AHI 自适应哈希索引
AHI是由innodb自己为了加速某些查询条件建立的索引,自适应是因为此操作只能由innodb控制,人工无法干预,当然你有关闭此功能的权利,哈希索引就是哈希索引,是一种如果合适那就最快的索引。
建立AHI的条件 1,以某种查询条件 连续 执行了 100次,比如where a= 1234,注意是连续,不是总共。2,页通过 某种查询条件连续访问了 N次,N=页中的记录/16,注意是连续,不是总共。
性能上使用AHI 将提高2倍的读写性能。
异步IO
异步io可以类比下merge insert buffer,异步IO也有个 merge io操作,就是将多个io合并成一个,比如io1 访问page 1 offset 100~200,io 2 访问page 1 offset 300~400,io3 访问 page 1 offset 200 ~300,那么就可以merge 这三个io操作合成 io 访问page 1 offset 100~400,此功能可手动关闭
刷新临接页
如名字所示,就是在刷新某个脏页时,检查下同区(extent)的所有页有没有页需要刷新,如果有就一起刷新,好处是将多个io操作合并成一个。但是有一下两个问题,1,顺带刷新的页可能很快又脏了,2,现在普遍使用ssd,iops足够高。归根结底,启用此功能弊大于利,故可以考虑关闭此功能。如果使用sas,可以开启,不过应该很少了吧。
原文地址:https://www.cnblogs.com/zzyhogwarts/p/14999753.html
- Android置底一个View后运行报错
- 温故而知新:设计模式之抽象工厂(AbstractFactory)
- mysql操作命令梳理(1)-索引
- Linux下对lvm逻辑卷分区大小的调整(针对xfs和ext4不同文件系统)
- centos6.5虚拟机安装后,没有iptables配置文件
- 温故而知新:设计模式之Builder
- 温故而知新:设计模式之单件模式(Singleton)
- sudo命令使用的几个场景
- .NET Core系列 : 2 、project.json 这葫芦里卖的什么药
- 关闭与恢复visual studio实时调试器
- linux系统下的权限知识梳理
- c#如何启动/干掉/查找 进程
- Android中Application的应用
- 孟昭莉博士:大数据大道之行
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- Android Notification.Builder通知案例分享
- SimpleCommand实现上传文件或视频功能(四)
- SimpleCommand框架ImageLoader API详解(三)
- Android PopupMenu弹出菜单的实现
- SimpleCommand实现图片下载(二)
- Android中menu使用详解
- SimpleCommand框架介绍以及简单使用(一)
- Android开发中使用achartengine绘制各种图表的方法
- Android开发中Listview动态加载数据的方法示例
- Android自定义实现顶部粘性下拉刷新效果
- Android开发使用自定义view实现ListView下拉的视差特效功能
- Android打造炫酷进度条效果
- Android开发实现自定义新闻加载页面功能实例
- Android下Activity间通信序列化过程中的深浅拷贝浅析
- Android升级支持库版本遇到的两个问题详解