MySQL存储引擎
    一个数据库系统可以切换不同的存储引擎,随意选择写磁盘或操作磁盘的方式,采用插件式的存储引擎体系结构,不同的存储引擎提供不同的存储机制,索引技巧等功能;
    个人理解存储引擎解决了怎样存储数据,存储数据到磁盘还是内存;存储引擎执行SQL语句,按照查询计划去查询内存数据,更新磁盘数据,查询磁盘数据,等等,执行诸如此类的一系列操作 常用的存储引擎有InnoDB,MyISAM,Memory等,现在的MySQL一般都是使用InnoDB存储引擎。


    binlog日志:
    日志是mysql数据库的重要组成部分,记录着数据库运行期间各种状态信息,mysql日志主要包括错误日志查询日志慢查询日志事务日志二进制日志几大类需要重点关注的是二进制日志(binlog) 和 事务日志(redo log, undo log)
    binlog用于记录数据库执行的写入操作信息(不包括查询),以二进制的形式保存在磁盘。binlog是mysql的逻辑日志,使用任何存储引擎的mysql数据库都会记录binlog日志;
    binlog是通过追加的方式进行写入的,可以通过max_binlog_size参数设置每个binlog文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志
    binlog使用场景:
    在实际应用中,binlog的主要使用场景有两个,分别是主从复制和数据恢复
    1.主从复制:在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致
    2.数据恢复:通过使用mysqlbinlog工具来恢复数据
    binlog的刷盘时机:
    通过设置 sync_binlog 参数控制binlog的刷盘时机
    逻辑日志和物理日志:
    逻辑日志:可以简单理解为记录的就是sql语句 ===> CameraLingo:update(0,’Kermera’=>’camera’)
    物理日志:mysql数据最终是保存在数据页中的,物理日志记录的就是数据页变更 ===> “Page 42:image at 367,2; before:’ke’;after:’ca’”

    顺序读写比随机读写速度更快,磁盘上随机读写操作是非常耗时的,每次修改一行数据就改磁盘文件,MySQL 的执行效率会非常低下。


    innodb_flush_log_at_trx_commit 和 sync_binlog 配置组合:

    innodb_flush_log_at_trx_commit
    当设置为0时,该模式速度最快,但不太安全,mysqld进程的崩溃会导致上一秒所有事务数据的丢失
    当设置为1时,该模式最安全但也是最慢的一种方式。在mysqld服务崩溃或者服务器主机宕机的情况下,日志缓存区只有可能丢失最多一个语句或者一个事务
    当设置为2时,该模式速度较快,较取值为0情况下更安全,只有在操作系统崩溃或者系统断电的情况下,上一秒所有事务数据才可能丢失
    sync_binlog=0 或者 N:默认说是0,但是我的是1;
    为0时,存储引擎不进行binlog的刷新到磁盘操作,由操作系统控制缓存刷新
    为1时,那么此时会强制在提交事务的时候,把binlog直接写入到磁盘文件里去
    当设置为0或者大于1时,事务被提交,而尚未同步到磁盘。因此,在电源故障或者系统崩溃时有可能丢失日志
    innodb_flush_log_at_trx_commit和sync_binlog都为1时是最安全的,但是双1会导致频繁的IO操作,因为该模式也是最慢的一种


    CheckPoint机制
    随着MySQL的运行,Buffer pool中的数据页会被修改成脏数据页,当你开启事务进行一系列的操作时MySQL会为你不停的记录一堆日志,拿redolog来说,redolog也需要先往内存里写,然后再以块的形式刷新回磁盘的。
    无论怎样都存在这样一个中间过程:内存中存在脏数据页和脏日志未来得及刷新回磁盘,CheckPoint机制就是将这些脏数据刷新回磁盘的机制,即只要发生ChechPoint,就要将脏数据刷新回磁盘,反过来,当MySQL重启时会去找CheckPoint,并且根据CheckPoint的特性,MySQL可以明确的知道CheckPiont之前的脏数据已经落过盘了,重启时没必要继续重做。
    总结:
    1.所谓的崩溃恢复,其实就是MySQL重启时只需要对CheckPoint之后的数据进行恢复,所以CheckPoint会缩短MySQL重启的时间
    2.因为CheckPoint会不断的更新,并且MySQL重启时只需要对CheckPoint之后的日志回放一遍
    3.因此每次进行CheckPoint时Buffer Pool中的脏数据页,redo log中的脏日志都会落盘。所以CheckPoint实际上起到了为这两者进行瘦身的作用
    CheckPoint种类及触发条件: fuzzy,模糊
    Sharp CheckPoint:当MySQL关闭时或者切换要写的redolog时,会一次性将所有的脏日志全部刷新到磁盘,这种模式下会对MySQL的性能带来较大影响
    Fuzzy CheckPoint:这种模式下的CheckPoint每次仅将部分日志刷新到磁盘。
    触发条件1:Master Thread Checkpoint 由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。
    触发条件2:FLUSH_LRU_LIST Checkpoint 从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,
    该线程的目的是为了保证lru列表有可用的空闲页。
    触发条件3:async/sync flush Checkpoint 同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘,这时候会选择同步刷到磁盘,但这很少出现;如果脏页 不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
    触发条件4:dirty page too much Checkpoint 脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量
    innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。


    LSN:log sequence number
    序列号,表空间中的数据页、内存中的缓存页、内存中的redo log、磁盘中的redo log、checkpoint它们五者都有记录LSN
    LSN作用:
    比如MySQL重启时会对比数据页的LSN和redo log的LSN的大小,如果前者比后者小,说明数据页缺失一部分数据,如果满足其他数据恢复的条件,MySQL就会将LSN之后的这些redo进行一次回放,完成数据的恢复。
    CheckPoint和LSN是两个维度的概念,CheckPoint是为了保持数据的一致性,触发CheckPoint的条件,会将当前内存所处的LSN序列号位置的数据全部落盘,然后Mysql宕机重启那就比较redolog的LSN和磁盘数据页的LSN位置,如果redolog的LSN > 磁盘数据页的LSN,说明磁盘数据页缺失,就把redolog的LSN位置后的数据回放到磁盘数据页。也就是说,一个是落盘用的,一个是记录位置的

    MySQL知识拓展-1 - 图1



    InnoDB会把存储的数据划分为若干个页

    WAL机制(Write Ahead Log):先将数据写入缓存,然后再写入日志文件,比如redo log日志,先将数据写入redo缓存池里,然后事务开始时再逐步将数据写入redolog文件中,事务结束后必须将该数据写入redolog文件中。

    预读机制是利用局部访问原理,加快数据的读取,触发MySQL预读的场景里提到“区”这个概念,什么意思? 可以理解为一个数据区域,包含很多个数据页。这一块区域的热点数据

    MySQL使用的是基于冷热数据区域的LRU链表,一个链表分成了冷热两个数据区域。LRU算法:最近最少使用算法,选择最近最久未使用的给予淘汰

    如果前一秒读取一个缓存页A 10次,这一秒读取另一个缓存页B 1次,那么缓存页B会排到缓存页A前面嘛?最近读的这个缓存页进入LRU链表头部,B是最近访问的,那么它就在前面。为了达到最大的性能优化,MySQL服务器其实还存在一个机制,前1/4的热数据区域被访问是不会移动链表位置的,只有后3/4的数据被访问了,才会链接位置的移动。热数据区满了,就会将热数据区域尾部缓存页移动到冷数据区域头部。

    问题:如果全表扫描的时候37%的冷数据区域一次性放不下从磁盘加载来的数据页会发生什么?
    处理会变慢,扫描一部分,淘汰一部分,再加载一部分页进来


    Free链表,Flush链表,LRU链表,他们是将不同状态的数据维护起来的,三个链表是操作的是同一块内存区域的Buffer Pool
    Free链表:标记哪些缓存页是空闲的,可以存放从磁盘读取的数据页
    Flush链表:标记哪些缓存页被修改,成为脏页,增删改。
    LRU链表:标记哪些是冷数据,哪些是热数据,lru链表存储了所有的缓存页,增删改查的缓存页都可能会有,当需要淘汰缓存页时,会去lru链表尾部淘汰缓存页,根据flush链表判断是否是脏页刷入磁盘,并且从flush链表中删除,如果是查询页直接释放掉,然后将空闲的缓存页对应的数据块地址加入到free链表中。

    知识点:LRU链表刷盘的时候会检查缓存页是否在flush链表中,如果发现存在,lru链表中对应的缓存页刷完盘,flush链表中同一描述数据也会被清理掉。