MySql - 对update是怎么处理的

咱们select的时候,会把数据对应的数据页加载到缓冲池Buffer Pool,那修改的时候,其实就是修改缓冲池Buffer Pool里的缓存页数据,而不是直接修改磁盘的数据,这样性能就会有比较大的提高。可是这里会有几个问题:数据库

  1. 事务怎么回滚?
  2. 存在缓存里机器宕机了怎么办?缓存

    undo日志文件

    在修改缓存页数据以前,会先把数据写入undo日志文件,用来解决事务回滚。
    若是是INSERT操做,那undo日志文件就会记录主键,回滚的时候经过主键删除。
    若是是UPDATE操做,那undo日志文件就会记录修改以前的数据,回滚的时候就会用以前的数据进行恢复。
    若是是DELETE操做,那undo日志文件就会记录删除以前的数据,回滚的时候就会用以前的数据进行恢复。
    image.png服务器

    redo日志文件

    在Buffer Pool修改数据后,接下来就是把变化的值写入到redo日志文件。
    若是此时已经写入redo日志文件,事务已经提交了,可是数据还没写入磁盘,MySql服务器宕机了,Buffer Pool里修改的数据并不会修改到磁盘里。
    当MySql重启的时候,他会读取redo日志文件,把变化的值从新写入Buffer Pool,对于客户端来讲,他读取的时候,就是读取Buffer Pool的值,因此客户端读取到的数据就是新数据。
    对于写入redo和undo不同的是,他有一个redo缓存,首先把值写入redo缓存而后再写入redo日志文件。因此他这里会有几种策略:性能

  3. 数据写入缓存,事务提交。
  4. 数据写入磁盘文件,事务提交。
  5. 写入缓存后事务提交,一秒后写入磁盘文件。
    从数据的可靠性来说,咱们通常选择第二种,等写入磁盘才提交事务。
    image.png
    为何要写redo而不是直接写数据库文件呢?
    由于写入数据库文件是随机写,写入redo是顺序写,这边就有很大的性能差别。spa

    binlog日志文件

    实际上在redo写入后,并不会直接提交事务,而是会写入binlog归档日志,然后才会提交事务。
    与redo相似,他也提供了两种策略:线程

  6. 写入oscache后提交事务。
  7. 写入磁盘后提交事务。
    从数据的可靠性来说,咱们通常选择第二种,等写入磁盘才提交事务。
    image.png
    写入binlog后,他会对redo文件进行commit操做。
    好比咱们修改了10条数据,而后写入binlog是8条,那咱们实际提交成功的事务是多少呢?要怎么判断呢?
    此时就须要commit来判断了,当写入binlog写入后并进行commit后,才证实这条数据是成功的事务。若是没有进行commit操做,那么有多是写入redo文件可是没有写入binlog的时候宕机了,或者已经写入binlog可是没有commit的时候宕机了,那这样的事务其实就是没有成功的。日志

    flush链表

    在上面的流程中,咱们看到写入undo日志文件、redo日志文件、binlog归档日志,就是没有看到怎么写入磁盘的。
    在MySql中,他会有一个线程,按期的把缓存页的内容刷入到磁盘。
    那这里又有一个问题,咱们知道Buffer Pool有不少缓存页,那这个线程怎么知道应该刷入哪一个缓存页到磁盘呢?
    跟以前的free链表、LRU链表同样,MySql也提供了一个链表,flush链表,当缓存页的内容有修改的时候,描述数据就会加入到flush链表。
    因此这个线程每次从flush链表找到对应的缓存页,把数据刷到磁盘,而后再把他从flush链表移走。
    image.png事务

相关文章
相关标签/搜索