MySQL: 3 Innodb存储引擎的架构设计

本文深入解析了MySQL中update语句的执行过程,包括SQL接口、解析器、优化器和执行器的角色。重点介绍了InnoDB存储引擎的缓冲池、undo日志和redo日志在数据更新中的作用。在事务处理中,讨论了不同提交策略(innodb_flush_log_at_trx_commit)对数据一致性和安全性的影响。
摘要由CSDN通过智能技术生成

1.一条SQL语句在MySQL中的执行过程

update users set name='xxx' where id=10

上面这条SQL语句的执行过程如下:系统通过一个数据库连接发送到了MySQL上,然后经过SQL接口、解析器、优化器、执行器几个环节,解析SQL语句,生成执行计划,,接着去由执行器负责这个计划的执行,调用InnoDB存储引擎的接口去执行。

下面将深入去了解基于存储引擎完成一条更新语句的执行。

2.InnoDB的重要内存结构:缓冲池

InnoDB存储引擎中有一个非常重要的放在内存里的组件,就是缓冲池(Buffer Pool),这里面会缓存很多的数据,以便于以后在查询的时候,如果内存缓冲池里有数据,就可以不用去查磁盘了。

在 1 中的update案例SQL语句中,InnoDB存储引擎在执行该更新语句的时候,以“id=10” 为例,它会先查询“id=10” 这一行数据是否在缓冲池里,如果不在的话,就会直接从磁盘里加载到缓冲池里。

在更新“id=10” 这行数据的时候,是不允许别人(线程)同时更新的,所以会对这行记录加独占锁。

3.undo日志文件:让更新的数据可以回滚

在上一步中,在加锁之后,会更新数据。

写undo日志文件

在案例“id=10” 这行数据进行更新的过程中,当把原来的 "zhangsan" 更新为 “lisi” 的时候。需要把要更新的原来的值 "zhangsan" 和 “id=10” 这些信息写入到 undo 日志文件中去。

undo日志文件的作用

在数据库中,如果我们执行一个更新语句,要是它是在一个事务里的话,那么事务提交之前都是可以对数据进行回滚的。

体现在当前案例中,就是可以将 “lisi” 的值回滚到之前的 "zhangsan" 去。

4.更新buffer pool中的缓存数据

当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对它加锁之后,而且还把更新前的旧值写入undo日志文件之后,我们就可以正式开始更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据就是脏数据了。

之所以说是脏数据,从前面的例子来说,此时 "id=10" 这行数据在内存的缓冲池中被更新为 “lisi” 了,而在磁盘中依旧还是 “zhangsan” 。此时的内存与磁盘数据不一致。

5.Redo Log Buffer:系统宕机时,避免数据丢失的方案

MySQL存在的问题,万一MySQL所在的机器宕机了,必然会导致内存里修改过的数据丢失。

解决办法,把对内存所做的修改写入到一个Redo Log Buffer里去,该内存缓冲区是用来存放redo日志的。

Redo日志的作用,它会记录下来对数据做了什么修改,比如将 "id=10这行记录修改了name字段的值为xxx",这就是一个日志。

说明,这个redo日志就是用来在MySQL突然宕机的时候,用来恢复你更新过的数据的。

6.事务未提交,MySQL宕机了怎么办?

在数据库中,哪怕执行一条SQL语句,也可以算是一个独立的事务, 只有当你提交事务之后,SQL语句才算执行结束。

问题,在没有提交事务之前,此时MySQL崩溃,必然导致内存里的Buffer Pool中的修改过的数据都丢失,同时你写入Redo Log Buffer中的 redo日志也会丢失。

  此时数据丢失,是不要紧的。

因为在一条更新语句,没提交事务,就代表它没执行成功,此时MySQL宕机虽然导致内存里的数据都丢失了,但是磁盘上的数据依然还停留在原样子。

参考案例说明: 缓冲池中的都是“lisi” ,此时事务未提交就宕机了。那么这个事务算是执行失败了,没能成功完成更新,你会收到一条数据库的异常。当mysql重启之后,会发现磁盘中依旧是原来的 "zhangsan" ,并没有发生任何变化。因为回滚并抛出了异常,所以此时mysql的宕机不会有任何问题。

7.提交事务的时候将redo日志写入磁盘中

提交事务之后,会根据一定的策略来把redo日志从redo Log Buffer里刷入到磁盘文件里去。

redo日志写入策略通过 innodb_flush_log_at_trx_commit来配置,有几个选项,或者说有多个策略:0、1、2三种策略。

当参数值为0时,此时提交事务的时候,不会把redo log buffer里的数据刷入磁盘文件。此时如果提交事务了,结果mysql宕机了,会导致内存里的数据全部丢失。即使mysql重启了,也无法恢复数据,这是数据不一致的问题。

当参数值为1时,在 提交事务的时候,强制把redo log 从内存刷入到磁盘文件里去,只要事务提交成功,那么redo log 就必然在磁盘里。如果在提交事务之后,mysql系统突然宕机,在重启mysql服务后,可以根据redo日志去恢复之前做过的修改,就不存在数据丢失的问题了。

当参数值为2时,提交事务的时候,把redo日志写入磁盘文件对应的 os cache缓存里去,而不是直接进入磁盘文件,可能1秒后才会把os cache里的数据写入到磁盘文件里去。

这种模式下,在提交事务后,redo log 可能仅仅停留在os cache内存缓存里,并没有持久化到磁盘文件,万一机器宕机了,那么 os cache里的 redo log就会丢失,同样会让你感觉提交事务了,结果数据丢了。

                                                                           

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值