通过上一篇文章,我们简要了解了MySQL的运行逻辑,从用户请求到最终将数据写入磁盘的整个过程。当数据写入磁盘时,存储引擎扮演着关键的角色,它负责实际的数据存储和检索。在MySQL中,有多个存储引擎可供选择,每个存储引擎都具有不同的特性和适用场景,但目前最常用的存储引擎之一是InnoDB。今天,我们将了解InnoDB存储引擎的架构设计和核心特点。
InnoDB存储引擎几大特性:
缓冲池(Buffer Pool)
缓冲池是InnoDB内部的一个重要内存结构,用于高效管理数据库表的数据和索引的缓存。
它在内存中存储了常用的数据页,以加速数据的读取和写入。
例如,我们要更新一条sql
UPDATE users set name='张老三' WHERE id = 1
这个时候,它会先找 id = 1 这行数据是否在缓冲池中,如果不在,就将这条数据从磁盘加载到缓存池中。
undo log
执行这个更新语句的话,就需要考虑如果这次更新是在一个事务里,事务提交成功之前可能会对数据进行回滚。
为了方便回滚,写入新的数据到内存(缓冲池之前),会把更新之前的数据,也就是说原来的数据写入undo log文件。
当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时把更新前的旧值写入undo日志文件之后,就可以正式开始更新这行记录了。
Rodo Log
现在已经把内存里(缓冲池)的数据进行了修改,但是磁盘上的数据还没修改。
如果这时候MySQL机器宕机了,导致内存里修改过的数据丢失,应该怎么办呢?
为了防止这种情况发生,InnoDB 存储引擎在处理事务时采用了一种称为"write-ahead logging" (WAL) 的机制。
这意味着在更新 Buffer Pool(缓冲池,用于缓存数据页)时,会同时更新 Redo Log(重做日志)。
这是为了确保事务的持久性和一致性。
根据前面所讲,这时候Rodo Log的信息还存在内存中,当提交事务的时候,InnoDB会把Rodo Log中的内容写入到磁盘,目的是防止提交事务之后,发生意外宕机导致已提交事务的数据发生丢失。
把Rodo Log从内存写入磁盘由innodb_flush_log_at_trx_commit 参数进行控制:
1. innodb_flush_log_at_trx_commit = 0:
每个事务提交时,并不会立即将事务日志刷新到磁盘,而是每秒执行一次日志刷新操作。
也就是说,提交事务之后,mysql宕机,那么此时redo日志没有刷盘,导致内存(MySQL内存)里的redo日志丢失,我们提交的事务更新的数据就丢失了。
可能会丢失最多一秒钟的事务。
2. innodb_flush_log_at_trx_commit = 1(默认值):
每次事务提交时,都会将事务日志立即刷新到磁盘。
这种配置提供了 最高的事务持久性 ,因为在事务提交后,日志已经被写入磁盘,即使系统崩溃,也能够最小程度地丢失数据。
3. innodb_flush_log_at_trx_commit = 2:
每次事务提交时,事务日志会被写入到操作系统的缓存,而不是直接刷新到磁盘。
然后,日志会被每秒钟刷新到磁盘。这样可以提高性能,同时在机器崩溃时可能会丢失最多一秒钟的事务。
所以对于数据库这样严格的系统而言,一般建议redo日志刷盘策略设置为1,保证事务提交之后,数据绝对不能丢失。
当然,我们应该根据业务需要适当调整配置。
最后,我们来总结一下上述步骤:
检查缓冲池中是否存在数据:
首先,InnoDB 将检查缓冲池中是否已经存在需要更新的数据页。缓冲池是一个内存区域,用于存储数据库表的数据页,以提高读取和写入性能。
从磁盘读取数据页到缓冲池:
如果数据页不在缓冲池中,InnoDB 将从磁盘读取相应的数据页到缓冲池中。这是因为在更新操作之前,数据通常首先被读取到内存中进行修改。
更新 Undo Log:
在更新数据之前,InnoDB 会先将修改前的数据记录到 Undo Log 中。这是为了提供事务的回滚能力,在需要时可以撤销已提交事务的更改。
更新 Redo Log 和缓冲池中的数据:
数据页在缓冲池中被更新,同时相应的修改操作也会被记录到 Redo Log 中。这是为了确保即使在事务提交后,对数据的修改也能够在崩溃恢复时重新应用,维护数据的一致性。
数据在缓冲池中的修改是在内存中进行的,这样可以提高写入性能。而 Redo Log 的更新是在事务提交时进行的,确保已提交的事务更改被持久化。
提交事务:
当事务完成所有的更新操作,并且事务成功提交时,相关的修改将最终写入磁盘的数据文件,从而实现了事务的持久性。
更新 Redo Log 到磁盘:
在事务提交后,Redo Log 的最新内容也会被定期刷新到磁盘。这确保了即使在系统崩溃时,已提交的事务更改也能够被重新应用,维护数据的一致性。
综上所述,InnoDB 处理更新请求的过程包括检查和读取数据页,更新 Undo Log,修改缓冲池中的数据,记录 Redo Log,提交事务,并最终将 Redo Log 刷新到磁盘。这个过程保证了数据的一致性、持久性,同时通过事务日志的机制提供了崩溃恢复的支持。