1.错误日志 error log
- 错误日志 error.log :记录了MySQL启动、运行、关闭过程中出现的问题。
2.慢查询日志
- 记录超过阀值时间的所有SQL语句,默认10s,等于10s不记。
- 1.5.1记录到slow_log表中。
- log_output参数可以指定慢查询日志输出格式,默认FILE , 可以设置成TABLE,这样就可以查看表了。
3.查询日志
- 记录所有日志无论是否正确执行。
4.二进制日志 binary log
- 记录关于事务的具体操作内容,就是对事务操作的描述,并未记录数据,属于逻辑日志。
- 记录对MYSQL数据库执行更改的所有操作,但是不包括 SELECT和SHOW,这类没有进行更改的操作。
- 作用:恢复数据,复制数据,查看数据库是否被攻击, 主从复制。
5.重做日志redo log
- redo log 是是属于InnoDB引擎的文件(InnoDB引擎还有表空间文件),其他日志文件是属于MySQL的。
- 记录每个页的更改情况,为了压缩日志只记录了与原页不同的数据(这里埋下了2次写的隐患)属于物理日志。
- 重做日志至少2个,记录数据修改之后的值,无论事务是否提交都会记录。
- 写满一个重做日志接着写下一个,全写满之后再重写写第一个。
- 作用:当数据库宕机之后可以使用重做日志来恢复到宕机之前时刻。
6.回滚日志undo log
- 主要用于记录事务行为,属于逻辑日志。
- 用于回滚事务。
7.InnoDB内存
- InnoDB引擎存储是基于磁盘的,数据以页的形式存放,数据页从磁盘读到内存进行处理,之后写回磁盘。
- 缓冲池就是为了解决CPU和磁盘之间的速度差异,如图所示
- 管理缓冲池内存区域
-
- 为了管理缓冲池InnoDB引擎使用了3个列表进管理。
- Free List :数据库刚启动时内存中还没有读入任何页,这时候这些内存就有Free List来管理,这些缓冲池中的页也叫作 free buffer。
- LRU List : 管理已读页,从磁盘读入数据后,会从Free List中判断有没有可用的free buffer,如果有写入数据,此时该页数据和磁盘数据一致,该页也叫作 clean buffer ,这些与磁盘一致的页交由LRU List管理 。
- 之所以叫LRU List 是因为他采用LRU 最近最少使用算法,把clean buffer 缓存页管理起来,这样一来热点数据就在列表头部,不热点的页就在列表尾部。
- 如果遇到Free List没有能使用的 free buffer时,那么就把LRU List 末尾的数据释放,变为free buffer 以供新的page读入。之所以这样是因为这些页是不是热点数据,对这些数据的修改写入概率小,即使释放之后读取概率也不大,可以减少IO。
- Flush List : LRU List中的数据被修改,与磁盘不一致那么就叫做 dirty buffer 或者 脏页(dirty page)。Flush List 就是来管理脏页的,他和LRU List 管理方式一样,采用LRU 算法进行管理,频繁被修改的脏页放在列表头部,不频繁修改的脏页,一定时间刷入磁盘。
- 这三个列表结构是双向链表,他们是逻辑上的,并不是物理上存在的。所以出现脏页并不是从LRU List 复制到 Flush List,内存弥足珍贵。所以LRU 和 Flush List都有脏页。
- LRU List 是用来管理可用缓存页的可用性,而Flush 是将脏页刷新到磁盘。
- InnoDB 对LRU算法进行了改进,读入数据后并不是直接插入列表头部,而是插入列表的5/8处的minpoit点,这样做的好处就是如果读入大量的页但这些页不是热点数据,他们也不会把真正列表头部的热点数据刷新出去。并且设置了一个时间阀值,超过这个时间就把他加入链表热点数据部分。
8.InnoDB内存刷新机制
- 关系型数据库都讲究 日志先行策略,就是一条DML语句进入数据库之后都会先写日志,再写数据库文件。
-
存储引擎工作线程 Master Thread 开始工作
- Master Thread 一直处于线程有四个循环状态中。
- 主循环: loop
- 后台循环:background loop
- 刷新循环:flush loop
- 暂停循环 :suspend loop
- 主循环 loop : 有2种操作 每1s 和 每10s操作
- 每1s:
- 重写日志缓存刷新到重写日志磁盘(总是)
- 合并插入缓存(可能)
- 最多刷新100个脏页到磁盘(可能)
- 如果没有用户活动,则切换到后台循环(可能)
- 每10s:
- 合并最多5个插入缓冲。(总是)
- 将重写日志刷新到磁盘(总是)
- 执行Full purge 操作 删除无用的 undo 页最多20个(总是)
- 刷新100或者10个脏页到磁盘(总是)
- 每1s:
- Master Thread 一直处于线程有四个循环状态中。
-
将UNDO信息写入undo表空间的回滚段中;
-
修改缓存页并将redo日志数据刷新到磁盘。
- 重写日志刷新触发有2个地方,一是主线循环每秒的刷新,而是 提交时的innodb_flush_log_at_trx_commit参数设置
- 参数设置为0,则提交时不用将重做日志写入磁盘,而是等待主循环每秒刷新。
- 参数设置为1,则提交时同步写入磁盘。默认为1
- 参数设置为2,则异步写入磁盘。
-
写二进制日志
-
Commit 完成
-
脏页刷新到磁盘
- 2次写
9.InnoDB 引擎特性
-
插入缓冲
- 插入缓冲是针对使用非聚集索引本身。
- 他使对普通索引上的DML操作从随机IO变成了顺序IO
- 要符合2个条件
- 索引是辅助索引
- 索引不是唯一索引。
-
- 对于聚集索引因为其叶子节点是连续的所以 并且叶子节点就是表数据,所以插入时可以顺序查找插入,插入的再多IO次数也较少,而且数据插入和索引插入是一起的速度比较快。
- 而非聚集索引其叶子节点虽然是连续的,但是叶子节点不存数据只存数据指针,指向的数据在磁盘上并不一定是按顺序的,不能顺序插入。插入的多了IO次数也就多了。
- 如果是唯一索引,那就要检查是不是唯一的这就增加了IO次数违背减少IO次数的初衷。
- 首先从磁盘查找要插入的索引页(索引也是表数据以页为单位存放),查到位置后不会执行插入操作(如果插入可能引起节点分裂,每次插入都会有随机IO)而是在判断索引页是否在缓存中。
- 如果在缓存中则直接插入缓存中的索引页,如果不在则 先放到一个 Change Buffer 中,在一定情况下再合并到叶子节点中。
- Change Buffer 也是一个B+树结构,它的叶子节点有一定规则,记录了磁盘中非聚集索引对应的叶子节点位置。
- 符合一定条件后会将Change Buffer中的叶子节点一次合并到磁盘非聚集索引的叶子节点上。这样的合并只会引起一次节点分裂,减少了IO次数。
- 由于在Change Buffer中会对插入节点
-
两次写
-
- 插入缓冲带来了性能上的提高,而两次写则保证了数据页的安全性。
- 脏页被写入磁盘时有可能一个页只写了一部分数据后发生宕机,造成数据丢失,这种情况被称为 部分写失效。
- 发生部分写失效,无法使用重做日志恢复数据,这是因为 重做日志并没有记录一个页的全部数据,而只是记录了页的改变数据,比如 一个页数据为 1111 1111 修改后为 1110 1111,重做日志只记录 “偏移量4 修改为0”。
- 由于发生部分写失效时 页本身已经被损坏,所以即使重做日志也不知道是什么样的数据 在 第四位改为0,所以重做日志无济于事。
- 脏页被写入磁盘前先写入一个doublewrite buffer
- doublewriter buffer 分2个每次1M写入共享表空间,共享表是连续的所以这个开销并不大。
- 之后再写入磁盘。
-
自适应哈希索引
- InnoDB存储引擎自动根据访问频率和模式来自动的为某些热点数据建立哈希索引
- 访问频率不用多说,访问模式就是 根据某一相同的条件 访问,如:where name = "java" 访问100次可能为naem = java 建立哈希索引,如果 where name = "java" 访问50次where name = "java" and id = 2 访问50 可能并不会为name = java 建立哈希索引。
原文地址:https://www.cnblogs.com/mibloom/p/9622960.html
时间: 2024-11-05 14:47:32