1.mysql的逻辑分层
Mysql分为Server层和插件式存储引擎层。不同的存储引擎共享一个Server层:
连接器:连接器负责跟客户端建立连接、获取权限、维持和管理连接。
查询缓存:mysql 8 已经删去,由于每次更新表都会刷新对应整个表的缓存,需要频繁更新消耗资源。
分析器:对SQL进行分析的。
优化器:主要查找最优的执行方法,例如是否走索引,走哪个索引等等。
执行器:将从存储引擎获取的数据进行处理,组成结果返回给客户端。
存储引擎层:提供读写数据的API
(一切的缓存为了减少IO,从而提交执行的速率,而log为了记录操作记录和异步写入数据库,提交写入的速率)
2.普通索引使用的changebuffer与redolog的联系
从innoDB获取数据不是以单条数据为单位读取是页为单位的,将整体读入内存再操作。
change buffer:
change buffer简单来说就是对更新数据起来加速作用的缓存的。
简单原理:
如果数据在内存的已经存在的数据页,则直接更新内存,如果没有则这些操作缓存在change buffer 中。然后下次查询需要访问这个数据页时候,就会将数据页读入内存,然后执行change buffer的操作,即merge合并到数据页再返回。
但是唯一索引更新,则直接更新在内存,不会缓存操作记录先。
change buffer和redo log的联系
插入两个数据,一个数据应该插入page1 一个在page2,而page1在buffer pool,则会先直接操作buffer pool的内存,然后等事务提交时候再写操作日志到redo log(写入磁盘看后面文章)。如果有读取page1,则直接内存返回,然后读取page2,则会先返回到bufferpool和缓存的操作merge,再将结果返回。
**好处:**更新不用马上直接io,提高更新的效率,和记录redolog,防止事务提交,系统崩溃,可以恢复数据。
3.redolog和binlog的区别和联系
WAL:Write-Ahead Logging ,它的关键点就是先写日志,再写磁盘,保证持久化到磁盘。
几个简单的问题:
为什么有了binlog还要有redolog?
binlog是属于MySQL的,redolog是属于innoDb的。
为什么需要redolog?
在 MySQL 中,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。为了解决这个问题,MySQL 的设计者就采用了日志(redo log)来提升更新效率。
redolog的概念:
原理:change buffer 的操作也记录到 redo log 里,并更新内存,这时候更新就算完成了,之后,引擎会在适当的时候(系统空闲时候),将这个操作记录更新到磁盘里面。
binlog的概念:
redo log 是InnoDB 引擎特有的日志,而 Server 层也有自己的日志,称为 binlog (归档日志)
区别:
1)redolog是innodb特有,binlog是mysql的server的
2)redolog是物理日志 记录多某个数据页做的修改,binlog是逻辑日志 记录对哪个数据操作。
3)redolog事务执行不断写入,binlog最终提交前才写入。
4)redolog是固定大小,binlog是不会覆盖之前的。
事务的两阶段提交:
事务分为两阶段:prepare和commit.
处在prepare阶段就会写入 redolog, 然后再写入binlog,然后在commit前再redolog添加commit的标识。这样操作,主要是为了保持binlog和redolog的日志是一致的。
如果发送崩溃,恢复时候,判断事务是否要提交:
如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交;
如果 redo log 里面的事务只有完整的 prepare ,则判断对应的事务 binlog 是否存在并完整:通过xid来联系起来。
4.redo和binlog的写入机制
redo的写入机制
事务在执行过程中,redolog会不断写入,这里先写入redo log buffer(内存块)的,不会直接持久化到磁盘。redo的日志会在这三个地方
redo log buffer:在mysql的内存。
**page cache:**Page cache是通过将磁盘中的数据缓存到内存中,从而减少磁盘I/O操作,从而提高性能。
**hard disk:**就是磁盘
写入的策略是可配置的,一般是事务提交时候将redo log持久到磁盘或者写到page cache。
另外写入的方式三种:
1)还有一个后台线程每秒会把redo log buffer写到page cache,然后调用fsync持久化到磁盘的。
2)其他事务提交,顺带将其他事务的redo log buffer持久到磁盘。
3)到达一半空间,就写到到page cache。
binlog的写入机制
事务执行过程,先把日志写到binlog cache,事务提交时候才会把binlog cache写到binlog文件,并且无论事务多大必须一次写入。
图中的 write ,指的就是指把日志写入到文件系统的 page cache(是操作系统的文件系统上的,属于操作系统的内存) ,并没有把数据持久化到磁盘,所以速度比较快。
图中的 fsync ,才是将数据持久化到磁盘的操作(由系统缓冲区写回磁盘的函数)。一般情况下,我们认为 fsync 才占磁盘的IOPS (IOPS (Input/Output Operations Per Second),即每秒进行读写(I/O)操作的次数)
而write 和fsync的策略是可配置的。fsync可以单个也可成组。还有相关组的提交机制。
mysql比较巧妙的一个设计,成组在fsync可以节省IO,所以将binlog的fsync放在redo的fsync之后再执行,这个时候在redo的fsync这个时间段就可以跟多binlog write到page,再成组提交,从而减少IO。
5.什么情况会引发数据库的flush过程呢?
场景1:
InnoDB的redo log写满了。这时候系统会停止所有更新操作,把checkpoint往前推进,redo log留出空间可以继续写。checkpoint可不是随便往前修改一下位置就可以的。把checkpoint位置从CP推进到CP’,就需要将两个点之间的日志(浅绿色部分),对应的所有脏页都flush到磁盘上。之后,图中从write pos到CP’之间就是可以再写入的redo log的区域
性能影响:出现这种情况的时候,整个系统就不能再接受更新了,所有的更新都必须堵住。
场景2:
系统内存不足。需要新的内存页,淘汰掉旧的,如果淘汰是脏页,需要flush脏页到磁盘。
6.undo log
undo log有两个作用:提供回滚和多个行版本控制(MVCC)。
在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。
innodb博大精深