欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL 笔记整理(2) --日志系统,一条SQL查询语句如何执行

程序员文章站 2022-08-21 17:17:52
笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》 2) --日志系统,一条SQL查询语句如何执行 MySQL可以恢复到半个月内任意一秒的状态,它的实现和日志系统有关。上一篇中记录了一条查询语句是如何执行的,对于更新语句,这一套流程也是同样会走一遍。与查询流程不一样的是,更新流程还涉及到两个重要 ......

笔记记录自林晓斌(丁奇)老师的《mysql实战45讲》

2) --日志系统,一条sql查询语句如何执行

  mysql可以恢复到半个月内任意一秒的状态,它的实现和日志系统有关。上一篇中记录了一条查询语句是如何执行的,对于更新语句,这一套流程也是同样会走一遍。与查询流程不一样的是,更新流程还涉及到两个重要的日志模块。redo log(重做日志) 和 binlog(归档日志)。

redo log:

  这里林老师举了一个很好的例子,摘录如下。

  《孔乙己》中的酒店掌柜有一个粉板,用来记录客人的赊账记录。如果赊账的人不多,他可以把顾客名和账目写在粉板上。如果赊账的人太多,粉板写不下了,掌柜的还会有一个专门记录赊账的账本。如果有人要赊账或者还账的话,掌柜的一般有两种做法:

    1. 一种做法是直接把账本翻出来,把这次赊账的记录加上去或者除掉。
    2. 另一种做法是先再粉板上记下这次的账,等打烊以后再把账本翻出来核算。

  如果客人太多,掌柜的一定会选择后者,因为前者的操作实在是太麻烦了。要在账本上翻上个几十页再一条条的查找,然后再用算盘计算。相比之下,在粉板上记录下来就简单的多。

  同样,在mysql里也会有这个问题。如果每次更新操作都要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程io成本及查找成本都很高。

 

  1. mysql中这种类似粉板和账本配合的过程就是wal技术(write-ahead logging)它的关键点是先写日志,再写磁盘。
  2. 当一条记录需要更新时,innodb引擎就会先把记录写到redo log里面,并更新内存(粉板)。同时,innodb引擎会在适当的时候将他更新到磁盘里(账单)。  
  3. redo log的大小是固定。因此如果系统繁忙,redo log很快就会写满。此时就不得不先把一部分记录更新到磁盘里,然后再进行后续的写入。
  4. 有了redo log, innodb就可以保证记录不会丢失,这个能力称为 crash-safe。(掌柜把记录写入了粉板,没写入账单。晚上掌柜的忘记这件事了(db异常重启),一看粉板(redo log)也可以重新写入账单)

binlog:

  1. 之前提到过mysql分为两层,一是server层,另一个是引擎层。redo log是innodb引擎特有的日志,而server层也有自己的日志,成为binlog(归档日志)
  2. redo log 与 binlog 有三点不同:
  • redo log是innodb引擎特有的日志,binlog是mysql的server层实现,所有引擎都可以使用。
  • redo log是物理日志,记录的是“在某个数据页上做了什么操作”;binlog是逻辑日志,记录是语句的原始逻辑,比如“给id=2这一行的c字段加1”.
  • redo log大小固定,循环写入。binlog可以追加写,不会覆盖以前的日志。

两阶段提交:

MySQL 笔记整理(2) --日志系统,一条SQL查询语句如何执行

 

(图片来源于 极客时间 林晓斌 《mysql 实战45讲》,如有版权问题请联系我删除)

  可以看到最后一部分把redo log拆成了两部分,prepare和commit,这就是“两阶段”提交。

  关于两阶段提交,如果不这样做的话则上述过程会演变成先写完redo log或者先写完binlog,假设在写完一个log,正在写第二个log时发生异常

  1. 先写redo log:前面有提到,由于redo log已经写完,仍能将redo log中的数据恢复回来。但由于binlog中没有这个记录,所以当你使用binlog来恢复临时库时,临时库便会少一次逻辑上的更新,即临时库认为没有这次的更新,故与原数据不同。
  2. 先写binlog:由于binlog已经写完,恢复临时库时会执行这次的操作,但redo log中并没有相关记录,这个事务无效也无法恢复,与=原数据不同。

另:innodb_flush_log_at_trx_commit这个参数设置为1表示把redo log直接持久化到磁盘,保证mysql异常重启之后数据不丢失。

sync_binlog设置为1时表示binlog持久化到磁盘,保证mysql异常重启后binlog不丢失。

 

上篇问题答案:

如果表t中没有字段k,而去执行这个语句 select * from t where k = 1,那么会报错“unknown column ‘k’ in ‘where clause’”。请问这个错误是在哪个阶段报出的?

答案是 分析器。笔记中有暗示啦,

分析器:分析器会先做“词法分析”,即从你输入的"select"这个关键字识别出来这是一个查询语句,把你输入的字符串“id”识别成“列id”。之后会进行“语法分析”,判断你输入的sql语句是否满足语法规则。

 

问题:

请问在什么场景下,一天一次备份会比一周一次备份更有优势?或者说,它影响了这个数据系统的哪些指标?