一条更新SQL语句是如何执行的?MySQL的三个日志的具体作用及区别

        SQL的更新流程和查询流程有什么区别呢?其实基本流程是一致的,也就是说,都需要经过Server层(服务层)的解析器,优化器处理,最后交给执行器。
        区别就在于拿到符合条件的数据后的操作。

   缓冲池 buffer pool 

MySQL的 InnoDB 存储引擎来说,数据都是放在磁盘上的,存储引擎要操作数据,必须先把磁盘里面的数据加载到内存里面才可以操作。

是不是我们需要的数据有多大,就一次从磁盘加载多少数据到内存?答案是否定的,磁盘的  I/O  的读写相对于内存的操作来说很慢的,如果我们需要的数据分散在磁盘的不同地方,即意味着需要进行多次  I/O  操作。

所以,操作系统和存储引擎都有一个预读取的概念,当磁盘上的一块数据被读取的时候,很可能它附近的数据也会被读取到,这就是局部性原理。这样我们每次读取磁盘数据的时候,能多取就多取,而不是用多少取多少。

InnoDB 设定了一个存储引擎从磁盘读取数据到内存的最小单位,页,操作系统也有页,操作系统的页默认大小是4K,InnoDB 的页默认是 16K,它是逻辑单位,如果需要修改这个默认值,必须修改源码并重新进行编译。

我们要操作的数据,就存放在这样的页里面,存放数据的页叫做数据页。

如果我们每次操作数据页,都操作磁盘,进行IO操作,那速度是非常慢的。

InnoDB  使用了一种缓冲池技术,即把从数据页读取的数据放到一块内存区域里面,下次读取相同数据页的内容时,先判断在不在这个内存区域里面,如果有就直接取,不再去进行磁盘数据页IO读取。

这个内存区域就叫做 buffer pool (缓冲池)。

 

修改数据的时候,先修改内存缓冲池(buffer pool) 里面的页,当内存的数据页和磁盘数据不一致时,我们把它叫做脏页;InnoDB 里面有专门的后台线程把buffer pool的数据写入到磁盘,每隔一段时间就一次性将多个修改写入磁盘,这个动作叫做刷脏

InnoDB 内存结构和磁盘结构

内存结构

内存结构里面主要有:Buffer Pool , Change Buffer , Log Buffer , AHI .

Buffer Pool : 缓存的是 page 页面信息,默认大小是 128M(134217728字节) ,可以调整。

Log Buffer(redo log): 因为刷脏不是实时进行的,假如buffer pool 里面的数据还没有刷入磁盘时, 数据库宕机或者重启时,这些数据会丢失。

因此内存的数据必须要有一个持久化的措施。

为了避免数据丢失,innoDB 把所有对数据页的修改操作专门写入一个日志文件中,如果有位同步到磁盘的数据,数据库在启动时,会从这个日志文件进行恢复操作(实现 crash-safe),我们说的事务ACID 的 D (持久性),就是用这个日志文件来实现的。

这个日志文件就是磁盘的 redo log (重做日志),主要用于数据崩溃恢复。对应于 /var/lib/mysql 目录下的 ib_logfile0 和 ib_logfile1 文件,默认 2 个文件,每个 48M 。

 

相同的写入数据,直接写到 DB file 文件,和写到日志文件有什么区别?

如果数据是直接写道 DB file 文件,假如我们需要的数据是随机分散在磁盘不同页的不同扇区,找到相应的数据需要等到c磁臂旋转到指定的页,然后盘片寻找到对应的扇区,才能找到我们所需要的一块数据,一次进行此过程直到找到所有数据,这个就是随机的 IO ,读取速度较慢。

假设我们已经找到了第一块数据,并且其他所需的数据就在这一块数据后面,那么就不需要重新寻址,可以依次拿到我们所需的数据,这个就是顺序的 IO 。

刷盘是随机 IO ,记录日志是顺序 IO  (连续写的),顺序 IO 效率更高,因此先修改写入日志文件,在保证了内存数据的安全前提下, 可以延迟刷盘时机,进而提升系统吞吐。

 

redo log 有什么特点?

1、redo log 是 InnoDB 存储引擎实现的,并不是所有存储引擎都有。支持崩溃恢复是  InnoDB 的一个特性。

2、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”。

3、redo log 的大小是固定的,前面的内容会被覆盖,一旦写满,就会触发 buffer pool 到磁盘同步,以便腾出空间记录后面的修改。

redo log 的主要作用是用于崩溃恢复,磁盘的数据文件,数据来自 buffer pool (只有redo log 写满了,不能再记录更多的内存数据时,才把 buffer pool 刷盘,然后覆盖  redo log)。

 除了 redo log 之外,还有一个跟修有关的日志,叫 undo log 。redo log 和 undo log 与 事务密切相关,统称为事务日志。

 undo log 有什么特点?

undo log (撤销日志或回滚日志)记录了事务发生之前的数据状态(不包括 select)。如果修改数据时出现异常,可以用undo log 日志来实现回滚操作(保持事务的原子性)。

在 执行 undo log 的时候,仅仅是将数据从逻辑上恢复到事务之前的状态,而不是从物理页面上操作实现的,属于逻辑日志

undo log  的数据默认在系统表空间 ibdata1  文件中,因为共享空间表空间不会自动收缩,也可以单独创建一个 undo  空间。

 

了解了这些日志文件后,我们总结一下一条更新sql的的操作流程,这是一个简化的过程,假设   name 的原值是 ’张泽‘,表名是 user,

update user set  name = '吴京' where id = 1;

1、事务开始,内存(buffer pool)或磁盘(data file)取到这条数据, 返回给server的执行器。

2、server的执行器修改这一行数据的值为 ’吴京‘ 。

3、记录 name = ’张泽‘ 到 undo log 日志文件。

4、记录 name = ’吴京‘ 到 redo log 日志文件。

5、调用存储引擎接口,在内存(buffer pool)中 修改 name =  ’吴京‘ 。

6、事务提交(commit)

 

内存和磁盘之间,进行着很多后台线程。

后台线程

后台线程的主要作用是负责刷新内存池中的数据和把修改的数据页刷新到磁盘。后台线程主要分为: master thread ,IO thread ,purge thread ,page cleaner thread。

除了 InnoDB 架构中的日志文件,MySQL 的 Server 层也有一个日志文件,叫做 binlog,它可以被所有的存储引擎使用。

 

bin log  有什么 特点 ?

bin log 以事件的形式记录了所有的 DDL 和 DML 语句,因为它记录的是操作而不是数值,所以 bin log r日志属于逻辑日志。bin log 的主要作用可以用来做主从复制和数据恢复。

和redo log 的区别是,它的文件内容是可以追加的,没有固定大小的限制。

在开启了 bin log 功能的情况下,我们可以把binlog 导出成 SQL 语句,把所有的操作重放一遍,来实现数据的恢复(归档)

binlog 的另一个功能就是用来实现主从复制,它的原理就是从服务器读取主服务器的binlog文件,再重新执行一遍,原理如下图。

有了这三个日志以后,我们来看一下一条更新语句是怎么执行的(下图省略了 undo log 日志文件)

 

例如一条更新sql 语句 

      update user set  name = '吴京' where id = 1;

1、先从内存或磁盘拿到这条数据。

2、把 name 改成 ’吴京‘,然后调用存储引擎 API 接口,写入这一行数据到内存,同时记录 redo log日志文件和undo log日志文件 。这时 redo log 进入 prepare (准备)状态,然后发送一个状态码告诉 Srever 层的执行器,执行完成了,可以随时提交。

3、执行器收到通知后记录 bin log 日志文件。

4、然后调用存储引擎接口,设置 redo log 日志为 commit 状态,更新完成。

 

总结:

          1、先记录到内存(buffer pool) ,再写日志文件。

          2、记录 redo  log 日志文件分两个阶段 (prepare 和 commit)。

          3、存储引擎(redo log 和 undo log)和 Srever(bin log) 层分别记录不同的日志文件。

          4、先 记录 redo log 再 记录 bin  log 。

  1. 为什么写入 redo log 和 bin log 要用两个阶段提交(XA)呢 ? 或者说,如果直接写入 redo log 成功,再去写 bin log ,可能会出现什么问题?

read log 日志和 bin log日志是在存储引擎中,防止数据丢失用的,而bin log 日志是在Server层记录sql的DDL和DML用的,主要用于数据恢复和主从数据同步。在持久化的物理日志 redo log 提交前一定要bin log 日志已提交完成,如果redo log 先提交完成在提交bin log日志前,数据库崩溃,就会导致主库在根据redo log日志恢复数据时,是已更改后的数据,而从库数据由于Bin log日志没有写入,恢复数据是根据bin log日志恢复更改前的数据,结果就是主从数据交替错误,无法保持数据一致性。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值