收藏小程序 玲轩阁 大量资源免费分享 假设我们有下面这样一条SQL语句:
这样一条SQL语句是如何执行的呢? 首先肯定的是我们的系统通过一个数据库连接发送到MySQL上,然后肯定会经过SQL接口、解析器、优化器、执行器几个环节,解析SQL语句,生成执行计划,接着去由执行器负责这个计划的执行;调用InnoDB存储引擎的接口去执行。 InnoDB的重要内存结构:缓冲池InnoDB存储引擎中有一个非常重要的放在内存里的组件,就是缓冲池(Buffer Pool),这里面会缓存很多的数据,以便于以后在查询的时候,万一你要是内存缓冲池里有数据,就可以不用去查磁盘了。 引擎要执行更新语句的时候,比如对"id=10"这一行数据,他其实会先将"id=10"这一行数据看看是否在缓冲池里,如果不在的话,那么会直接从磁盘里加载到缓冲池里来,而且接着还会对这行记录加独占锁。 在更新"id=10"这一行数据的时候,肯定是不允许别人同时更新的,所以必须要对这行记录加独占锁。 undo日志文件:如何让你更新的数据可以回滚接着下一步,假设"id=10"这行数据的name原来是"zhangsan",现在我们要更新为“xxx”,那么此时我们得先把要更新的原来的值"zhangsan"和"id=10"这些信息,写入到undo日志文件中去。 只要稍微对数据库有一点了解就应该知道,如果我们执行一个更新语句,要是他在一个事务里的话,那么事务提交之前我们都是可以对数据进行回滚的,也就是把你更新为"xxx"的值回滚到之前的“zhangsan”去。 所以为了考虑到未来可能要回滚数据的需要,这里会把你更新前的值写入undo日志文件。 更新buffer pool中的缓存数据当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对他加锁之后,而且还把更新的旧值写入undo日志文件之后,我们就可以正式开始更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据就是脏数据了。 这里所谓的更新内存缓冲池里的数据,意思就是把内存里"id=10"这行数据的name字段修改为"xxx",那么为什么说此时这行数据就是脏数据了呢? 因为这个时候磁盘上"id=10"这行数据的name字段还是"zhangsan",但是内存里这行数据已经被修改了,所以就会叫他是脏数据。 更新buffer pool中的缓存数据当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对他加锁之后,而且还把更新的旧值写入undo日志文件之后,我们就可以正式开始更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据就是脏数据了。 这里所谓的更新内存缓冲池里的数据,意思就是把内存里"id=10"这行数据的name字段修改为"xxx",那么为什么说此时这行数据就是脏数据了呢? 因为这个时候磁盘上"id=10"这行数据的name字段还是"zhangsan",但是内存里这行数据已经被修改了,所以就会叫他是脏数据。 这个redo日志其实是用来在MySQL突然宕机的时候,用来恢复你更新过的数据的。 如果还没提交事务,MySQL宕机了怎么办?到目前为止,其实还没有提交事务,那么此时如果MySQL崩溃,必然导致内存里Buffer Pool中的修改过的数据丢失,同时写入Redo Log Buffer中的redo日志也会丢失。 此时数据丢失其实是不要紧的,因为一条更新语句,没提交事务,就代表他没执行成功,此时MySQL宕机虽然导致内存里的数据丢失了,但是你会发现磁盘上的数据依然还停留在原样子。 也就是说"id=1"的那行数据的name字段的值还是老的值"zhangsan",所以此时你的这个事务就是执行失败了,没能成功完成更新,你会收到一个数据库的异常,然后当mysql重启之后,数据并没有任何变化。所以此时mysql宕机,不会有任何问题。 提交事务的时候将redo日志写入磁盘中接着我们想要提交一个事务,此时就会根据一定的策略把redo日志从redo log buffer里刷入到磁盘文件里去。此时这个策略是通过
|
|
来自: 新用户73336046 > 《待分类》