【总结】InnoDB存储引擎

该文章为知识总结的文章,如果是初学者,建议先从专栏学习:数据库专栏

一、InnoDB存储引擎工作方式

  • 将数据库文件按页(每页16k)读取到缓冲池,然后按照最近最少使用的算法(LRU)保留缓存数据。
  • 如果数据发生更改,总是先修改缓存池的页(脏页),然后再保存在磁盘中

二、关键特性

1. 插入缓存

  • 因为主键是表唯一标识,所以插入顺序按照主键递增(自增主键)的顺序插入。
  • 因此,插入的聚集索引一般是顺序的,不需要对磁盘随机读取,所以速度很快。
  • 但是一个表不止有聚集索引,索引的插入不再是顺序的
  • 插入索引对于非聚集索引,不是一次性插入到索引页,先判断索引页是否在缓存池。如果在,直接插入;如果不在,先放入插入缓存,将多个插入合并在一个中(因为都是在一个索引页中),在根据磁盘IO情况更新到磁盘中。
  • 索引必须是辅助索引,索引不是唯一的
  • 默认最多占一半缓存池空间

缺点

  • 由于并没有及时把索引更新到磁盘中,如果数据库宕机,则需要很多的时间恢复数据

2. 两次写

  • 当数据库宕机时,数据库可能正在写一个页面,而这个页面只写了一部分,则称之为部分写失效,从而导致数据丢失
  • 如果此时直接使用Undo日志,由于页出现了损坏,所以此时是无意义的
  • 在执行Undo日志之前,先需要一个页副本用来恢复的没有写之前的状态,再进行重做。

  • doublewrite由两部分组成:内存中的doublewrite buffer,物理磁盘共享表中的两个区
  • 在缓冲池脏页刷新时,先将数据拷贝到内存中的doublewrite buffer,然后在写入物理磁盘共享表中的两个区,然后在更新磁盘数据
  • 由于doublewrite是连续的,所以对其的IO操作时顺序写的,开销不大

3. 自适应哈希索引

  • 哈希是一种查找办法,常用于join连接操作
  • 会监控表上索引的查找,如果建立哈希索引可以提供速度,则建立哈希索引。
  • 哈希索引通过缓存池中的B+数构造而来,因此建立速度很快
  • 并不是整个表都需要建立哈希索引,InnoDB会根据访问的频率为某些页单独建立哈希索引

三、redo log、binlog和undo log

1. 什么是redo log?

  • redo log是InnoDB存储引擎层的日志,又称重做日志文件,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。在实例和介质失败(media failure)时,redo log文件就能派上用场,如数据库掉电,InnoDB存储引擎会使用redo log恢复到掉电前的时刻,以此来保证数据的完整性。

  • 在一条更新语句进行执行的时候,InnoDB引擎会把更新记录写到redo log日志中,然后更新内存,此时算是语句执行完了,然后在空闲的时候或者是按照设定的更新策略将redo log中的内容更新到磁盘中,这里涉及到WALWrite Ahead logging技术,他的关键点是先写日志,再写磁盘。

  • 有了redo log日志,那么在数据库进行异常重启的时候,可以根据redo log日志进行恢复,也就达到了crash-safe

  • redo log日志的大小是固定的,即记录满了以后就从头循环写,并且会暂停当前的所有数据更改操作,先将redo log日志同步到磁盘中。

2. 什么是binlog?

  • 可以作为数据恢复,在MySQL层面保证数据一致性的
  • 属于逻辑日志,是以二进制的形式记录的是这个语句的原始逻辑
  • 也可以用于主从之间保证数据一致性

3. redo log和binlog区别

  • redo log是属于innoDB层面,binlog属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性的要求。

  • redo log是物理日志,记录该数据页更新的内容;binlog是逻辑日志,记录的是这个更新语句的原始逻辑

  • redo log是循环写,日志空间大小固定;binlog是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。

  • binlog可以作为恢复数据使用,也可以用于主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。

4. 回滚日志(undo log)

  • 属于InnoDB层面保证事务的原子性

  • 保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读

5. redo log和undo log的区别

  • redo log是保证事务持久性的,undo log是保证事务原子性的
  • undo log用于备份一个事务开始前的数据,不会影响原本的数据,都是先在备份中更改,最后写入磁盘
  • redo log用于记录每一个数据更新的内容,用于在二次写中恢复破损的数据

6. 一条更新语句执行的顺序

update T set c=c+1 where ID=2;

  • 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  • 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  • 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  • 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  • 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
全部评论

相关推荐

11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务