数据库日志文件和内存刷新机制

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引擎存储是基于磁盘的,数据以页的形式存放,数据页从磁盘读到内存进行处理,之后写回磁盘。
  1. 缓冲池就是为了解决CPU和磁盘之间的速度差异,如图所示

  2. 管理缓冲池内存区域
    • 为了管理缓冲池InnoDB引擎使用了3个列表进管理。
    1. Free List :数据库刚启动时内存中还没有读入任何页,这时候这些内存就有Free List来管理,这些缓冲池中的页也叫作 free buffer。
    2. 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。
    3. 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语句进入数据库之后都会先写日志,再写数据库文件。
  1. 存储引擎工作线程 Master Thread 开始工作

    • Master Thread 一直处于线程有四个循环状态中。

      1. 主循环: loop
      2. 后台循环:background loop
      3. 刷新循环:flush loop
      4. 暂停循环 :suspend loop
    1. 主循环 loop : 有2种操作 每1s 和 每10s操作

      1. 每1s:

        • 重写日志缓存刷新到重写日志磁盘(总是)
        • 合并插入缓存(可能)
        • 最多刷新100个脏页到磁盘(可能)
        • 如果没有用户活动,则切换到后台循环(可能)
      2. 每10s:
        • 合并最多5个插入缓冲。(总是)
        • 将重写日志刷新到磁盘(总是)
        • 执行Full purge 操作 删除无用的 undo 页最多20个(总是)
        • 刷新100或者10个脏页到磁盘(总是)
  2. 将UNDO信息写入undo表空间的回滚段中;

  3. 修改缓存页并将redo日志数据刷新到磁盘。

    • 重写日志刷新触发有2个地方,一是主线循环每秒的刷新,而是 提交时的innodb_flush_log_at_trx_commit参数设置
    • 参数设置为0,则提交时不用将重做日志写入磁盘,而是等待主循环每秒刷新。
    • 参数设置为1,则提交时同步写入磁盘。默认为1
    • 参数设置为2,则异步写入磁盘。
  4. 写二进制日志

  5. Commit 完成

  6. 脏页刷新到磁盘

    • 2次写

9.InnoDB 引擎特性

  1. 插入缓冲

    • 插入缓冲是针对使用非聚集索引本身。
    • 他使对普通索引上的DML操作从随机IO变成了顺序IO
    • 要符合2个条件 
      • 索引是辅助索引
      • 索引不是唯一索引。
    • 对于聚集索引因为其叶子节点是连续的所以 并且叶子节点就是表数据,所以插入时可以顺序查找插入,插入的再多IO次数也较少,而且数据插入和索引插入是一起的速度比较快。
    • 而非聚集索引其叶子节点虽然是连续的,但是叶子节点不存数据只存数据指针,指向的数据在磁盘上并不一定是按顺序的,不能顺序插入。插入的多了IO次数也就多了。
    • 如果是唯一索引,那就要检查是不是唯一的这就增加了IO次数违背减少IO次数的初衷。
    1. 首先从磁盘查找要插入的索引页(索引也是表数据以页为单位存放),查到位置后不会执行插入操作(如果插入可能引起节点分裂,每次插入都会有随机IO)而是在判断索引页是否在缓存中。
    2. 如果在缓存中则直接插入缓存中的索引页,如果不在则 先放到一个 Change Buffer 中,在一定情况下再合并到叶子节点中。
    3. Change Buffer 也是一个B+树结构,它的叶子节点有一定规则,记录了磁盘中非聚集索引对应的叶子节点位置。
    4. 符合一定条件后会将Change Buffer中的叶子节点一次合并到磁盘非聚集索引的叶子节点上。这样的合并只会引起一次节点分裂,减少了IO次数。
    5. 由于在Change Buffer中会对插入节点
  1. 两次写

    • 插入缓冲带来了性能上的提高,而两次写则保证了数据页的安全性。
    • 脏页被写入磁盘时有可能一个页只写了一部分数据后发生宕机,造成数据丢失,这种情况被称为 部分写失效。
    • 发生部分写失效,无法使用重做日志恢复数据,这是因为 重做日志并没有记录一个页的全部数据,而只是记录了页的改变数据,比如 一个页数据为 1111 1111  修改后为 1110 1111,重做日志只记录 “偏移量4 修改为0”。
    • 由于发生部分写失效时 页本身已经被损坏,所以即使重做日志也不知道是什么样的数据 在 第四位改为0,所以重做日志无济于事。
    1. 脏页被写入磁盘前先写入一个doublewrite buffer
    2. doublewriter buffer 分2个每次1M写入共享表空间,共享表是连续的所以这个开销并不大。
    3. 之后再写入磁盘。
  1. 自适应哈希索引

    • InnoDB存储引擎自动根据访问频率和模式来自动的为某些热点数据建立哈希索引
    1. 访问频率不用多说,访问模式就是 根据某一相同的条件 访问,如: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-08-27 00:35:21

数据库日志文件和内存刷新机制的相关文章

SQL Server 2008 R2 下如何清理数据库日志文件

USE [master] GO ALTER DATABASE [数据库名] SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE [数据库名] SET RECOVERY SIMPLE GO USE [数据库名] GO DBCC SHRINKFILE (N'[数据库日志文件名称]' , 0,TRUNCATEONLY) GO USE [master] GO ALTER DATABASE [数据库名] SET RECOVERY FULL WITH NO_

使用作业自动清理数据库日志文件

原文:使用作业自动清理数据库日志文件 在上一篇文章中介绍了如何删除数据库日志文件,但是想想还是不是不方便需要手工操作,于是想结合作业实现自动清理日志文件,在清理日志文件时我加上了条件,当磁盘控空间不足多少M才会清理,下面介绍如何实现该功能.没有阅读上一篇文章的,可以通过传送门阅读(删除数据库日志文件的方法)! 阅读目录 SQL查询磁盘空间大小 存储过程添加作业 示例下载 回到顶部 SQL查询磁盘空间大小  采用内置的存储过程,即可查看各个磁盘可用空间 exec master..xp_fixedd

数据库日志文件收缩

项目所使用的数据库通过备份还原来的,导致日志文件很大,占用了很大的空间,在网上搜索了日志收缩的信息,整理了下. --清空日志 DUMP  TRANSACTION  EWABOQDB  WITH NO_LOG --截断事务日志 BACKUP LOG EWABOQDB WITH NO_LOG --收缩日志 右键要收缩的数据库--任务--收缩--文件--文件类型选择日志--收缩方式中选择收缩至XXM输入确定 以上已完成日志文件的收缩,日志文件所占空间已减少 下面是对日志文件的增长规则进行了个限制 右键

删除数据库日志文件的方法

原文:删除数据库日志文件的方法 你曾经有在执行SQL的时候,数据库报事务日志已满,然后执行报错.然后纠结于怎么删除数据库日志,捣鼓半天吗,现在就提供两种删除日志文件的方法,希望能够帮到你! 阅读目录 方法一:手工操作 方法二:存储过程代替手工操作 示例存储过程下载 回到顶部 方法一:手工操作   1.数据库->右键->属性->选项-恢复模式->由完成切换成简单   2.数据库->右键->任务->收缩-文件->由完成切换成简单->文件类型->日志-

SQL 解决数据库日志文件已满的问题

出现数据库操作失败,查找原因,发现数据库日志已满: 解决此问题有两种方法: 1.压缩日志文件 1.数据库->属性->选项-恢复模式->由完成切换成简单 2.数据库->任务->收缩-文件->文件类型->日志->将文件收缩到 2.删除日志文件 分离数据库: 删除数据库日志文件 附加数据库时,出现找不到日志字样,删除数据库日志文件 点击保存,成功!

批量收缩数据库日志文件

declare @sql nvarchar(max),@paramDef nvarchar(100) declare dbname scroll cursor for select name,recovery_model from sys.databases where database_id>7 open dbname declare @dbname varchar(50),@recovery_model int,@db_log_file varchar(100) set @dbname=''

[SQL Server] 数据库日志文件自动增长导致连接超时的分析

1.现象.问题描述 客户反映某客户端登陆不了,客户端程序日志显示“连接数据库超时”:检查对应的数据库服务器,日志显示“Autogrow of file '某数据库日志文件' in database '某数据库' was cancelled by user or timed out after 2391 milliseconds.  Use ALTER DATABASE to set a smaller FILEGROWTH value for this file or to explicitly

数据库日志文件(收缩管理)

sqlserver数据库的日志文件其实是由很多个逻辑上的日志文件组成,我们可以通过命令看一下数据库日志文件 ?可以看到的是sqlserver数据库日志文件是由很多文件组成的,当数据库日志文件已满的时候,自动增长就会生成新的文件,这些文件叫做VLF(虚拟日志文件),所以说在这个层面上来说,我们可以简单的把数据库日志理解为一列火车,一节一节的车厢理解为数据库的虚拟日志文件,当然如果不够存的下事务日志的时候,就要扩充,就是加一个火车厢. 所以说数据库事务日志其实是由很多个独立的虚拟事务日志文件组成的,

sql点滴39—解决数据库日志文件过大的问题

原文:sql点滴39-解决数据库日志文件过大的问题 随着数据库使用时间增长,日志文件也在不停的增大,这里介绍几种方法减小这个文件的方法. 1.直接删除log文件 分离数据库.分离数据库之前一定要做好数据库的全备份,选择数据库——右键——任务——分离,如下图 将日志文件和数据文件复制粘贴到另外一个文件夹中以防万一.删除链接,如下图 直接删除日志文件,然后再附加数据库,如下图 附加的时候会自动将ldf文件和mdf文件都附加上,但是会提示找不到ldf文件,没关系,选中ldf文件这一行,点击下面的删除按