MySQL复习

54 阅读9分钟
  • Mysql的日志有几种,分别是做什么的?
  • 为什么有了bin-log日志还要redo-log日志?
  • bin-log日志和redo-log日志有什么区别
  • 日志是直接写入磁盘吗?
  • redo-log日志和bin-log日志的刷盘机制是什么?
  • bin-log日志格式有哪几种?
  • 如果在线上操作中不小心误删了大量表数据或库数据,你会怎么做?
  • redo-log日志的两阶段提交是什么?
  • 在线上环境中如何定位那些执行比较缓慢的查询语句?
  • mysql是基于磁盘工作的吗?
  • bufferPool缓冲区是什么?
  • innodb引擎如何管理缓冲页?
  • 一个磁盘数据被载入内存缓冲页,会一直停留在内存中吗?
  • 内存的数据页是如何被淘汰出去的?
  • 如果在缓冲区内存较大的情况下,如果数据页比较多,对于只使用了1-2次的数据,岂不是需要很久才会被淘汰吗?
  • 假设有一个查询操作,对一张千万级别的表走了全表查询,内存中的热点数据数据页全部被替换出去了应该怎么办?
  • innodb引擎内部的执行流程
  • 如果是insert语句,之前的磁盘没有数据,如何处理?
  • innodb的自适应哈希索引是什么?
  • mysql的内存中有什么?
  • innodb和myisam两款引擎有什么区别?
  1. mysql中日志的种类有很多,主要有6种
    • undo-log撤销日志:当有操作变更数据前,都会把老数据放入该日志中。
    • redo-log重做日志:该日志记录着innodb所有表的变更语句,也可用来做灾难恢复
    • bin-log变更日志:这里记录着所有对数据库会产生变更的语句
    • error-log错误日志:记录着mysql启动,运行期间所有的报错、警告信息
    • slow-log慢查询日志:记录着所有执行时长超过指定阈值的查询语句
    • relay-log中继日志:主从集群中,从节点用于存储主节点bin-log数据日志的日志
  2. 这两个日志都会记录数据库的写操作,但redo-log日志是inoodb引擎所独有的,主要功能是用来做灾难的恢复,每条写入语句在执行前都会先记录一条prepare状态的日志,然后再执行sql语句,执行完成后会先记录bin-log日志,接着再把redo-log日志的状态从prepare变更到commit。如果一个事务提交后,数据在内存中还未刷盘,此时mysql宕机了,后续重启时也可以根据redo-log的日志来恢复数据。
  3. 对于bin-log日志和redo-log日志的区别要从这几个方面入手
    • 生效范围不同:redo-log日志是innodb独享的,bin-log是所有引擎通用的
    • 写入方式不同:redo-log日志使用两个文件循环写,而bin-log日志是采用不断创建新文件追加写的方式。
    • 文件格式不同:redo-log日志中记录的都是变更后的数据,而bin-log日志会记录变更后的sql语句
    • 使用场景不同:redo-log日志主要实现故障情况下的数据恢复,而bin-log日志则用于数据灾备和同步
  4. 日志不是直接写磁盘的,mysql专门在内存中设计了日志缓冲区,不同日志有不同的日志缓冲区,日志也是先写内存,再刷盘到磁盘。
  5. redo-log的刷盘机制是通过innodb_flush_log_at_trx_commit参数控制的,而bin-log日志的刷盘策略则可以通过sync_binlog参数进行控制
    • innodb_flush_log_at_trx_commit:
      • 0: 间隔一段时间后,然后再刷写一次日志到磁盘
      • 1:每次提交事务后,刷写一次日志到磁盘
      • 2:有事务提交的状态下,每隔一秒刷写一次日志到磁盘
    • sync_binlog:
      • 0: 有事务提交的状态下,每隔一秒刷写一次日志到磁盘
      • 1:每次提交事务后,刷写一次日志到磁盘 值得注意的是redo-log是通过两个日志进行循环写,而bin-log日志是通过多个日志文件追加写。
  6. bin-log日志一共有三种格式:
    • statement:记录每一条会对数据库产生变更操作的sql语句
    • row:记录具体出现变更的数据
    • mixed:statement和mixed的结合版,可复制的记录sql语句,不可复制的记录具体数据
  7. 由于bin-log日志是按顺序写的,一个日志文件满了之后会创建一个新的继续写,在本地会出现bin-log.0001、bin-log.0002。。。。这种形式,所以我们只需要找到误删命令执行前的日志文件,然后通过日志文件恢复数据。
  8. 主要是因为单阶段提交,如果放在bin-log前写入日志,可能会导致主从集群数据的同步不一致,但如果放在bin-log日志写入后,则无法实现灾难的恢复,所以被设计成了在bin-log日志写入前后都写入一次。
  9. 开启慢查询日志,通过long_query_time参数指定时间阈值,mysql会自动将超过阈值的查询语句记录进去。
  10. mysql的设计确实是基于磁盘的,但如果引擎是innodb情况就有所不同,innodb会在内存中构建一个BufferPool缓冲区,只要为其分配的内存足够大,innodb基本就会把所有的操作都放在内存中实现。
  11. bufferpool缓冲区是innodb引擎所独有的,它会将内存分为一个个页,每个页的大小默认为16kb,以页作为内存和磁盘交互的基本单位,这些缓冲页分为三种
    • 空闲页:指没有被使用过的内存缓冲页
    • 数据页:指已经使用过,用于存放磁盘表数据,索引数据以及其他各类的缓冲页
    • 变更页:指页中数据发生过变更,还未被后台线程刷写到磁盘的缓冲页 同时为了便于管理所有的缓冲页,每个缓冲页都会有一个控制块与其对应,其中记录着磁盘数据的表空间,页号,缓冲页地址,链表节点指针等信息,innodb可以通过控制块去控制管理每一块缓冲页。
  12. innodb会基于三个链表来管理所有缓冲页,所有的缓冲页会根据类型不同,分别加入到不同的链表中,每个缓冲页通过控制块中的指针,形成逻辑连续的链表结构:
      1. free list:负责记录空闲页,为了使用能更快的找到空闲缓冲页。
      • 当需要使用缓冲页时,会从空闲链表拿出一个空闲页使用
      • 当清空一个数据页后,又会将没有数据的缓冲页加入到空闲链表中
      1. Lru list:记录所有已使用过的缓冲页,为了方便淘汰已使用的缓冲页
      1. Flush List:负责记录所有变更页,为了刷盘时能够更快的找到变更的数据页
      • 当一个缓冲页中的数据发生变更后,会从lru链表移动到flush链表中
      • 当变更页的数据刷写完成后,又会从flush链表移回lru链表
  13. 不会的,因为这样做会导致内存占用无限增长,最终引发oom异常,有些数据页会被淘汰出内存。
  14. 这就需要用到lru链表了,innodb采用的是末位淘汰制,所有使用过的数据页都会进入到lru链表中,但每当一个数据页被访问后,都会将其移动到链表的最前面,这样就能保证热度较高的数据页长期留在内存中,及时淘汰掉那些热度较低的数据页。
  15. innodb将lru链表分成了两个部分一个是young区一个是old区比例为63:37,young区经常存放被访问的热点数据,old区存放刚从磁盘加载的数据页。从磁盘预读的数据页会被放入到old区的头部,当这个数据页被真正访问时,才会将其插入到young区的头部,如果预读的这页后续一直都没有被访问,就会从old区移除,从而不影响young区的热点数据。
  16. 首次载入的数据页,会先放到old区,而从old区到yound需要晋升,首先要在old区存活1000ms,然后是在old区中一秒后有线程再次访问了这个数据页。
  17. innodb在处理读写语句的时候有细微的差距
    • 读语句:首先会根据sql语句,将目标数据从磁盘载入内存,经过条件筛选后返回
    • 写语句:首先会将语句要操作的数据页载入到内存,然后更改内存数据页,由后台线程去把变更数据刷写到磁盘。
  18. innodb有一个插入缓冲区,5.6之后就叫做写入缓冲区,专门用来处理新增操作,insert的数据会被放到这个缓冲区中,然后由后台线程完成刷盘工作。
  19. 因为hash结构是所有数据类型中最快的,所以innodb会在运行期间,统计出一些经常走索引查询的热点数据,然后针对这些热点索引数据,去为其建立哈希索引,以此提升查询性能。
  20. mysql内存中主要有工作组件,共享内存和内存缓冲区
  21. innodb与myisam引擎之间主要有以下几类区别
    • 磁盘文件不同
      • myisam引擎的表会分成三个文件
        • table_name.frm:该文件主要存储表的结构信息
        • table_name.myd:该文件中存储表的行数据
        • table_name.myi:该文件中存储表的索引数据
      • 而innodb引擎只有两个文件
        • table_name.frm:该文件中主要存储表的结构信息
        • table_name.ibd:该文件主要存储表数据和索引数据
    • innodb支持聚簇索引,而myisam只支持非聚簇索引,因为它索引数据和表数据是分开存储的
    • innodb基于undo-log日志实现了事务机制,但myisam没有,所以不支持事务
    • innodb基于redo-log日志实现故障恢复机制,但myisam则只能依靠bin-log日志,因此会丢失数据风险
    • innodb可以基于聚簇索引实现行锁,同时还兼容表锁,但myisam仅支持表锁
    • innodb由于设计了bufferpool缓冲池,所以内存利用度会远超myisam引擎