【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用

Change Buffer

当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InnoDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。

在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。

需要说明的是,虽然名字叫作 change buffer,实际上它是可以持久化的数据。也就是说,change buffer 在内存中有拷贝,也会被写入到磁盘上。

将 change buffer 中的操作应用到原数据页,得到最新结果的过程称为 merge。

除了访问这个数据页会触发 merge 外,系统有后台线程会定期 merge。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作。

显然,如果能够将更新操作先记录在 change buffer,减少读磁盘,语句的执行速度会得到明显的提升。

而且,数据读入内存是需要占用 buffer pool 的,所以这种方式还能够避免占用内存,提高内存利用率。

那么,什么条件下可以使用 change buffer 呢?

对于唯一索引来说,所有的更新操作都要先判断这个操作是否违反唯一性约束。

比如,要插入unique_key = 4这个记录,就要先判断现在表中是否已经存在 unique_key=4 的记录,而这必须要将数据页读入内存才能判断。如果都已经读入到内存了,那直接更新内存会更快,就没必要使用 change buffer 了。

因此,唯一索引的更新就不能使用 change buffer,实际上也只有普通索引可以使用。change buffer 用的是 buffer pool 里的内存,因此不能无限增大。change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。

因此,对于数据本身就存在于内存中的情况,那么普通和唯一索引的性能差距不大。

但是如果数据不存在内存中,那么唯一索引由于需要把数据从磁盘读取到内存中,无法使用change buffer,因此性能差了很多。

通过上面的分析,我们已经清楚了使用 change buffer 对更新过程的加速作用,也清楚了 change buffer 只限于用在普通索引的场景下,而不适用于唯一索引。

那么,现在有一个问题就是:

普通索引的所有场景,使用 change buffer 都可以起到加速作用吗?

因为 merge 的时候是真正进行数据更新的时刻,而 change buffer 的主要目的就是将记录的变更动作缓存下来,所以在一个数据页做 merge 之前,change buffer 记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大。

因此,对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时 change buffer 的使用效果最好。 这种业务模型常见的就是账单类、日志类的系统。反过来,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新先记录在 change buffer,但之后由于马上要访问这个数据页,会立即触发 merge 过程。这样随机访问 IO 的次数不会减少,反而增加了 change buffer 的维护代价。所以,对于这种业务模式来说,change buffer 反而起到了副作用。

Buffer Pool

MySQL 中的 Buffer Pool 是为了优化磁盘 I/O 而引入的机制。MySQL 内部的页大小与操作系统的页大小可以不一致,MySQL 中的页大小通常是固定的,默认为16KB。

Buffer Pool 是一个内存区域,用于缓存从磁盘读取和维护的数据页。它的作用是减少磁盘 I/O 操作,提高数据库的性能和响应速度。当查询或修改数据时,MySQL 首先检查缓冲池中是否存在所需的数据页,如果存在,则可以直接从内存中读取或写入数据,从而避免了频繁的磁盘读写操作。

缓冲池的大小可以通过配置参数 innodb_buffer_pool_size 来设置。合理设置缓冲池的大小非常重要,过小的缓冲池可能导致频繁的磁盘 I/O,而过大的缓冲池可能浪费宝贵的内存资源。

为了更好地使用缓冲池,可以考虑以下几个方面:

根据系统的内存大小和数据库的访问模式设置合适的缓冲池大小。这需要综合考虑系统中其他进程和服务的内存需求。

监控缓冲池的使用情况,例如使用 show global status like ‘Innodb_buffer_pool%’ 命令来查看缓冲池的命中率、使用率等指标。可以根据监控结果来调整缓冲池大小。

确保表的索引足够优化,以最大程度地减少对磁盘的访问。

对于 Buffer Pool 中的数据如何保证与磁盘的数据一致性,InnoDB 引擎采用了写前日志(Write-Ahead Logging)的机制。在修改数据之前,InnoDB 会先将修改的数据写入日志文件(Redo Log),然后再将数据页更新到 Buffer Pool。这样即使系统崩溃或重启,可以通过日志的恢复操作来保证数据的一致性。

(WAL)写前日志是一种常见的数据库事务处理策略,旨在保证数据的持久性和一致性。在MySQL中,当进行数据修改操作时,InnoDB存储引擎首先会将修改操作写入日志文件(称为重做日志或者写前日志),然后再将相应的数据页更新到Buffer Pool中。这样做的好处是,即使在更新到磁盘之前发生了系统崩溃或断电等故障,数据库可以根据重做日志来恢复数据,保证数据的完整性和一致性。

换句话说,写前日志机制确保了数据的持久性,而Buffer Pool则用于提高查询性能,缓存经常访问的数据页,减少对磁盘的I/O操作。两者是协同工作的,保证了数据的安全性和数据库的高性能运行。

在正常情况下,MySQL 会根据一定的策略将 Buffer Pool 中的数据刷新到磁盘,以确保数据的持久性。

正常情况下,MySQL会定期将Buffer Pool中的脏页(已被修改但尚未写入磁盘的数据页)刷新到磁盘,以保证数据的持久性。刷新策略可以通过配置参数进行调整,如innodb_max_dirty_pages_pct和innodb_io_capacity等。

Redo Log

一言以蔽之:减少磁盘随机写,使用内存高速顺序写。提供奔溃数据恢复机制。

Redo Log日志为mysql提供了crash-safe的能力,也就是奔溃恢复能力。

我们知道,我们使用mysql的时候,其性能瓶颈在于随机的磁盘IO操作,因此如果能减少对磁盘IO的操作,那么能极大的提高性能。

我们再使用增删改操作的时候,其实就是一种随机IO操作,如果我们每次都把对应的操作数据从磁盘中读取出来然后修改再写入,那么性能可想而知的低。

所以,能不能有一种办法,我们能先把数据写到缓存(内存)中,然后再合适的时机再把这些数据写入到磁盘呢?

是有的,也就是我们所谓的Redo Log日志了。

当我们需要写入数据的时候,我们并不是把这些数据直接写入到磁盘,而是先写到redo log这种更快速的内存文件中,那么对性能的影响就会小很多了。

redo log中记录的是对mysql中数据块的操作。

当我们的mysql出现奔溃的时候,我们再次重启进行数据恢复的时候,就可以从redo log中把这些还没有写道磁盘中的数据给他进行写入,从而保证了数据一致性。

Bin Log

一言以蔽之:提供数据恢复,数据回滚,主从同步等功能。

Binlog(二进制日志)是MySQL中的一种日志文件,用于记录数据库的所有修改操作,例如插入、更新和删除。Binlog具有以下几个重要的作用和意义:

数据恢复与备份:Binlog可以用于数据的恢复与备份。通过将Binlog文件应用到MySQL实例中,可以将数据库还原到特定的时间点或特定的事务状态。这在数据丢失或数据库崩溃时非常有用。

主从复制:Binlog是MySQL主从复制的基础。在主从复制中,主数据库上的所有修改操作都会被记录到Binlog文件中,并通过网络传送给从数据库。从数据库根据Binlog文件的内容来执行相同的修改操作,从而保持与主数据库的数据一致性。

数据库同步与高可用性:Binlog可以用于实时地将变更操作传播到其他MySQL实例,从而实现数据库的同步和高可用性。通过将Binlog文件传输给其他MySQL实例,这些实例可以将变更操作应用到自己的数据库中,从而保持数据的一致性。

数据分析与查询回放:Binlog记录了数据库的所有修改操作,因此可以用于数据分析和查询回放。通过分析Binlog文件,可以了解到数据库的历史修改操作,进行性能分析、数据统计等工作。对于需要重放历史查询的场景,可以将Binlog文件应用到测试环境中,模拟执行查询操作。

在MySQL中,Bin Log是用于记录数据库的更改操作的二进制日志。以下是会写入Bin Log日志的操作:

DML语句(Data Manipulation Language):包括INSERT、UPDATE和DELETE语句,用于对表中的数据进行增、删、改操作。

DDL语句(Data Definition Language):包括CREATE、ALTER和DROP语句,用于创建、修改和删除数据库对象,如表、索引等。

DCL语句(Data Control Language):包括GRANT和REVOKE语句,用于授权和撤销权限。

数据更改函数和存储过程:如果函数或存储过程中包含了会修改数据的操作,那么执行这些函数或存储过程也会写入Bin Log日志。

写入Bin Log日志的目的是为了实现数据库的持久性和数据恢复。通过将更改操作记录到Bin Log中,可以在发生故障或数据丢失的情况下进行数据恢复和同步。此外,Bin Log日志还可以用于数据库复制、数据备份、数据迁移等场景。

Undo Log

一言以蔽之:MVCC多版本并发控制的视图所能看到的数据依赖于此。

Undo log(回滚日志)是MySQL InnoDB存储引擎中的一部分,用于实现事务的原子性和一致性。它的作用是记录事务操作的反向操作,以便在事务回滚或系统崩溃时,可以恢复到事务开始前的状态。

当一个事务开始时,InnoDB会为该事务创建一个undo log。在事务执行期间,如果发生了数据修改(例如插入、更新、删除),则会在undo log中记录相应的反向操作,以便在回滚时可以撤销这些修改。

具体而言,对于插入操作,undo log记录了插入的数据和哪个位置需要删除该数据;对于更新和删除操作,undo log记录了被修改或删除的数据和如何还原到原有状态的操作。

当一个事务需要回滚时,InnoDB会根据对应的undo log中的反向操作,将之前的数据修改撤销,恢复到事务开始前的状态。这种能力是事务的基本特性之一,保证了事务的原子性和一致性。

对于MySQL的性能影响来说,undo log会占用一定的存储空间。每个事务的undo log都需要先写入磁盘,这可能引起一定的IO开销。同时,在事务并发执行时,undo log的管理和读写也会引起一些额外的开销,因此在高并发场景下,需要合理设置undo log的大小和管理策略,以保证系统性能的平衡。

Undo log在MySQL InnoDB存储引擎中与多版本并发控制(MVCC)密切相关,并且在MVCC中起到重要作用。MVCC是一种并发控制机制,用于实现高并发环境下的事务隔离性。

MVCC通过为每个事务分配唯一的事务ID(Transaction ID)和版本号来管理事务的并发访问。当一个事务开始时,会记录当前数据库中的快照版本。随着事务的进行,其他事务可以继续对数据库进行读操作,读取快照版本的数据,而不会受到当前事务所做的修改的影响。

这就引入了undo log的作用。在MVCC中,当一个事务正在对数据进行修改时,为了保证其他事务能够读取到一致的数据,InnoDB会将修改前的数据拷贝一份到undo log中,并在undo log中记录该操作的版本号。

当其他事务读取数据时,如果该数据被正在进行修改的事务修改了,InnoDB会根据事务的版本号和undo log中的信息,通过回滚操作将该数据还原到修改前的状态,然后读取这个被还原的数据,保证了读取的一致性。

因此,undo log在MVCC中的作用是提供了用于还原数据的历史版本,以确保事务读取的数据是一致的。它用于实现数据的回滚和回滚段的管理,为MVCC提供了必要的支持。

需要注意的是,MVCC不仅仅依赖于undo log,还与其他机制(如读视图、回滚段等)紧密结合,以实现事务的隔离性和并发控制。undo log作为其中的一部分,发挥了关键的作用。

这几个日志的协作流程

当根据修改请求对应的数据是否在内存中,分别对这些日志进行操作的执行流程如下:

Change Buffer:首先,修改操作会在内存的Change Buffer中进行记录。Change Buffer是MySQL的一种机制,用于延迟对磁盘上对应页的实际修改,以提高性能。修改操作在Change Buffer中被记录下来,而不是立即写入磁盘上的对应页。

Buffer Pool:数据在内存中的主要存储位置是Buffer Pool(也称为页缓存)。当修改操作需要读取数据页时,MySQL会先检查Buffer Pool中是否存在要修改的页。如果存在,就直接在Buffer Pool中进行修改操作。如果要修改的页不在Buffer Pool中,那么下次查询出来这条数据的时候,我们就会把他加载到Buffer Pool并且使用Change Buffer里面的修改操作来对他进行操作。

Undo Log:在修改操作执行过程中,MySQL会将对原始数据的修改操作记录到Undo Log中。Undo Log用于回滚事务或者恢复数据到之前的版本。通过记录修改前的数据,MySQL可以在需要时撤销或回滚修改操作。

Redo Log:同时,修改操作的日志也会写入到Redo Log中。Redo Log是用于崩溃恢复的重要日志。它记录了所有的修改操作,以保证即使在异常情况下数据的持久性。

Bin Log:最后,修改操作还会记录到Bin Log(二进制日志)中。Bin Log是用于复制和恢复的日志。通过记录修改操作,可以在主从服务器之间同步数据,并且可以用于在灾难恢复时恢复数据。

注意,最后写Bin Log日志以及Redo Log日志的过程涉及到两阶段提交。

也就是不论是否使用到Change Buffer,只要我们做了修改操作,我们就会写入数据到redo log中


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
15天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
1月前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。
|
2月前
|
SQL 存储 关系型数据库
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
老架构师尼恩在其读者交流群中分享了关于 MySQL 中 redo log、undo log 和 binlog 的面试题及其答案。这些问题涵盖了事务的 ACID 特性、日志的一致性问题、SQL 语句的执行流程等。尼恩详细解释了这些日志的作用、所在架构层级、日志形式、缓存机制以及写文件方式等内容。他还提供了多个面试题的详细解答,帮助读者系统化地掌握这些知识点,提升面试表现。此外,尼恩还推荐了《尼恩Java面试宝典PDF》和其他技术圣经系列PDF,帮助读者进一步巩固知识,实现“offer自由”。
美团面试:binlog、redo log、undo log的底层原理是什么?它们分别实现ACID的哪个特性?
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1697 14
|
2月前
|
存储 关系型数据库 MySQL
MySQL中的Redo Log、Undo Log和Binlog:深入解析
【10月更文挑战第21天】在数据库管理系统中,日志是保障数据一致性和完整性的关键机制。MySQL作为一种广泛使用的关系型数据库管理系统,提供了多种日志类型来满足不同的需求。本文将详细介绍MySQL中的Redo Log、Undo Log和Binlog,从背景、业务场景、功能、底层实现原理、使用措施等方面进行详细分析,并通过Java代码示例展示如何与这些日志进行交互。
212 0
|
12天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
81 15
|
5天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
12天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
16天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
24天前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
下一篇
DataWorks