文章目录
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200619153609467.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTI0MDE2OQ==,size_16,color_FFFFFF,t_70)
上图是mysql官方文档中提供的InnoDB架构图,左侧是内存架构,右侧则是磁盘架构。本文主要对磁盘架构简单分析下。
如上图右侧所示,可以看到InnoDB的磁盘结构由6部分组成:
1.系统表空间(System Tablespace)
默认所有表都会共享的表空间,对应磁盘文件ibdata1。里面包含四部分:
(1)InnoDB Data Dictionary:数据字典,记录表和索引的元信息。
(2)Doublewrite Buffer:双写缓冲,下边详细会说。
(3)change Buffer:写缓冲区,上文中说过。
(4)undo log:实现mysql事务的原子性,后边会单独说。
双写缓冲(Doublewrite Buffer)
上篇文章中我们知道了InnoDB每次IO默认为1页即16kb,但是操作系统的页一般是4kb,所以InnoDB的一个页要写入到磁盘就要分四次了。
那么问题来了。
问
:如果数据写入到磁盘的时候发生了宕机,而InnoDB只写入了第一个4kb的时候。那剩下的12kb没写进去,这就叫做“部分写失效”,这就会导致数据丢失。注意redo log日志进行数据恢复时发现这个页已经不完成了,所以是恢复不了的。怎么解决?
答
:很直观的答案,保证数据页的完整性
就好了。那怎么保证。它是这么做的,在要刷盘之前,也就是redo log应用到磁盘之前,会先拷贝一个副本到doublewrite buffer中。如果出现了部分页失效,就可以用这个副本还原这个数据页的内容,然后在恢复数据。这个页的副本就成为双写缓冲技术
,主要靠它来实现数据页的可靠性
和完成性
。
查看Doublewrite Buffer信息的命令:show variables like '%innodb_doublewrite%';
,默认就是开启状态。
2.独占表空间(File-Per-Table Tablespace)
因为系统的表空间是共享的,为了防止系统表空间越来越大,才有的独占表空间。该文件为每个表的表空间提供了一种更灵活的选择,其中,每个InnoDB表被存储在其自己的表空间的数据文件(.ibd文件)。也就是有一个表就有一个ibd文件,该文件只存放数据和索引。
show variables like '%innodb_file_per_table%';
,可以查看信息,默认就是开启状态。
3.通用表空间(General Tablespaces)
也是共享的表空间,跟系统表空间类似。不过它可以自己创建并使用。使用CREATE TABLESPACE语法创建。
4.临时表空间(Temporary Tablespace)
存储临时表的数据,对应文件ibTmp1。在正常关闭或初始化中止时,将删除临时表空间,并在每次启动服务器时重新创建
5.重做日志(redo log)
提供崩溃恢复。上一篇文章中说过。
6.撤销表空间(undo Tablespaces)
也就是undo log,默认配置中,是放在系统表空间的,也可以独立出来。
redo log + undo log合起来就是mysql的事务日志,redo log 实现持久性,undo log实现原子性。
查看undo log信息的命令:show global variables like '%undo%';
undo log
undo log又叫回滚日志,记录了我们事务发生前的一个状态,比如,我们在修改的时候发生了异常,就可以用undo log 来实现回滚的操作。
有了redo log 和undo log后,那么一条更新语句的执行流程为:
(1)从内存或磁盘读取到这条数据,返回给server层
(2)执行器把这条数据修改
(3)记录undo log
(4)记录redo log并将这条数据状态设为 prepare
(5)调用存储引擎的api,在buffer pool修改数据
???????????(总感觉这里少点啥)??????????????
(6)事务提交将redo log中这条数据的状态改为commit,再由后台线程刷到磁盘
那么问题来了。
问
:如上述流程中,如果事务正在提交的时候mysql挂了咋办?
这就引出了新的东西 binary log
binary log
又称 binlog,二进制日志。主要记录了我们所有的DDL(创建表库和删除表库的操作)、DML(增删改的操作)语句。
作用:
(1)数据恢复,可以将binlog日志解析出来,应用到全量备份中。必须依赖全量备份,不然很难恢复
(2)主从复制,主从之间数据如何保持同步的?就是基于binlog去实现的。
上个问题的解答
:有了binlog,那么在commit之前先将更新语句写入到binlog中。就算在提交事务的时候mysql崩溃重启了,那也会以binlog为准,将语句在执行commit一次就行了。所以只要写入到binlog后,就意味着语句执行成功了。