Mysql(四)-日志系统
Mysql为什么会有日志系统?
我们知道,mysql的数据是存储在磁盘的,每次更新数据需要先进入磁盘,然后在磁盘中找到需要更新的数据,这样会产生IO成本以及查找成本,这样会大大降低Mysql的性能。
所以mysql就采用先存入日志文件,当系统空闲的时候,mysql再通过日志文件将数据存入磁盘。当然日志文件还要其他的作用,比如主从模式下,保证主库和丛库的数据一致性,
也会用到日志文件(binlog),Mysql的两大日志模块分别为redo log以及binlog,redo log是InnoDB引擎独有的,而binlog是Server自带的。下面我们来详细讲讲这两个日志模块。
redo log
redo log是InnoDB存储引擎独有的,它记录的是物理操作,比如在某个数据页上做了什么修改。
redo log是固定大小的,比如可以配置一组4个文件,每个文件大小为1G,它会循环写入。也就是说这种配置最多只能保存4个G的日志,当日志满了之后,会从第一个
文件开始覆盖以前的日志。覆盖日志之前,要保证被覆盖的日志对应的数据已经更新到磁盘。
有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。
binlog
binlog是Server提供的归档日志,所以的存储引擎都支持,它记录的是语句的原始逻辑,比如给id=1的一行的a字段加2。
binlog可以实现数据库的数据恢复,比如恢复到指定的某个时刻的数据,还可以通过binlog实现主从数据库的数据一致性。
redo log和binlog比较
- redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
- redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
- redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
从简单语句的执行流程来看redo log和binlog的存储逻辑
有了对这两个日志的概念性理解,我们再来看执行器和 InnoDB 引擎在执行这个简单的 update 语句时的内部流程。我们以mysql> update T set c=c+1 where ID=2;为例
- 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
- 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
- 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
- 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
- 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
· golang自带的死锁检测并非银弹
· 一个适用于 .NET 的开源整洁架构项目模板
· AI Editor 真的被惊到了
· API 风格选对了,文档写好了,项目就成功了一半!
· 【开源】C#上位机必备高效数据转换助手
· .NET 9.0 使用 Vulkan API 编写跨平台图形应用