1、缓冲池
update users set name='xxx' where id=10;
存储引擎要执行更新语句的时候,比如对“id=10”这一行数据,它会先看“id=10”这行数据是否在缓冲池里,如果不在,会直接从磁盘加载到缓冲池里,而且还会对这行数据加独占锁。
3、undo日志文件:如何让更新的数据回滚?
假设“id=10”这行数据的name原来是“zhangsan”,现在我们要更新为“xxx”,那么此时我们先要把原来的值“zhangsan”和“id=10”,写入到undo日志里。
如果我们执行一个更新语句,要是他在一个事务里的话,那么事务提交之前都是可以对数据进行回滚的,也就是把“xxx”回滚到之前的“zhangsan”。
4、更新buffer pool中的缓冲数据
当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时加上独占锁,并把更新前的数据写入undo日志。然后,我们就可以正式开始更新这行记录了,更新的时候,先会更新缓冲池中的数据,此时的数据就是脏数据了。这里所谓的更新内存缓冲池里的数据,就是把内存里的“id=10”这行数据的name列的值修改为“xxx”。
那为什么说此时这行数据是脏数据呢?因为这个时候磁盘上“id=10”这行数据name列的值还是“zhangsan”,但是内存里这行数据已经被修改了,所以被称为脏数据。
5、redo log buffer:万一系统宕机,如何避免损失?
如果内存中的数据被修改了,但是磁盘上的数据还没被修改,那么此时MySQL服务器宕机了,必然会导致内存里的数据丢失,这时候该怎么办?
这个时候,就必须要把对内存的修改写入到redo log buffer中,这也是内存里的一个缓冲区,是用来存放redo日志的。所谓redo日志,就是记录下对数据库做了什么修改,比如对“id=10”这行记录的name值修改为“xxx”。
6、如果还没提交事务,MySQL宕机了怎么办?
到目前为止,还没有提交事务,若此时MySQL宕机,必然会导致buffer pool中修改的数据丢失,同时写入redo log buffer中的数据也会丢失。
那么此时数据丢失要紧吗?其实是不要紧的。因为一条更新语句,没提交事务,就代表没有成功,此时MySQL宕机虽然导致内存里的数据都丢失了,但是磁盘上的数据还是原来的样子。
7、提交事务的时候将redo日志写入磁盘中
接下来要提交失事务了,此时会根据一定的策略把redo log buffer刷到磁盘文件。这个策略是通过innodb_flush_log_at_trx_commit配置的。
1)innodb_flush_log_at_trx_commit=0,事务提交的时候,不会把redo log buffer刷入到磁盘文件,此时即时提交事务,但是MySQL宕了,内存里的数据还是会丢失。
2)innodb_flush_log_at_trx_commit=1,事务提交的时候,redo log buffer必须刷入磁盘文件。
此时MySQL宕机,数据会丢失吗?不会!MySQL重启之后,可以根据redo日志去恢复之前做过的修改。
3)innodb_flush_log_at_trx_commit=2,事务提交的时候,先把redo日志写入os缓存里,而不是直接写入磁盘文件,1s后才把os 缓存里的数据刷入磁盘。
这种模式下,事务提交后,redo log仅仅停留在os缓存里,没有被刷入磁盘文件,此时如果服务器宕机,那么os缓存里的redo log就会丢失。