技术分析 | 通过DML语句浅谈binlog和redo log

2021-12-23  本文已影响0人  GreatSQL

欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答

1. 导言

我们在采用InnoDB引擎的情况下,编写SQL语句WHERE条件的时候,可以通过AND操作符来提高数据的过滤能力,当然,在使用AND操作符也有许多需要注意的地方,就好比一条更新语句:

mysql>update testtable set price = 52.0,name = 'test_name';

本意是将表内对应字段重置为指定信息,可是现在不小心写成了:

mysql>update testtable set price = 52.0 and name = 'test_name';

这个时候,我们查看表发现:

mysql> select * from testtable;
+----+----------+------------+
| id | name     | price      |
+----+----------+------------+
| 1  | old_name |  0.00      |
| 2  | old_name |  0.00      |
+----+----------+------------+

显然,系统会把AND当做判断条件进行逻辑判断,这里所有列都不满足条件,所以结果为0。此时,我们可以利用事务回滚特性,回滚这个update,而为了更好地理解,我们需要重新来看看这一条update语句

2. binlog和redo log

现有一条SQL语句:

mysql>update testtable set price = price + 1 where id = 5;

我们知道,这条语句在分析器是进行词法和语法解析,并且知道这是一条更新语句。并由优化器决定要使用id这个索引。然后,执行器负责具体执行,找到这一行,然后更新。说到更新流程,说到更新操作,我们不得不提到两个日志模块:binlog和redo log

2.1 binlog

先来说一说binlog,该日志存在于Server层次中,是使用存储引擎都可以使用的日志模块,binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给id=5这一行的price字段值加1”
binlog的日志文件是可以追加写入的。“追加写入”是指binlog日志文件写到一定大小后会切换到下一个文件进行写入,可以设置sync_binlog为1,让每次事务的binlog都持久化保存到磁盘中

2.2 redo log

而重做日志redo log是MySQL中InnoDB引擎才有的日志,它是物理日志,即记录的内容是“在某个数据页上做了什么修改“

MySQL对于每一次的更新操作如果都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,过程中的IO成本、查找成本都很高。redo log有效的提升了更新效率

redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么总共就可以有4GB的空间去记录我们进行的操作。从头开始写,写到末尾就又回到开头循环写,如下图:

file

write pos是当前记录的位置,一边写一边后移,写到第log_3文件末尾后就回到log_0文件开头。checkpoint是当前要释放的位置,也是往后推移并且循环的,释放记录前要把记录更新到数据文件。如果write pos追上checkpoint,那就表明全部空间都满了,这时候不能再执行新的更新,得停下来先释放掉一些位置,让checkpoint继续推进

当有一条记录需要更新的时候,InnoDB引擎就会先将数据更新到内存,再把记录写到redo log里面,这个时候更新就算完成了。同时,InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做,可以设置 innodb_flush_log_at_trx_commit为1,表示每次事务的redo log都直接持久化到磁盘中

2.3 binlog和redo log的区别

file

3. InnoDB引擎下模拟执行过程

可参考下图:

file

Enjoy GreatSQL :)

本文由博客一文多发平台 OpenWrite 发布!

上一篇下一篇

猜你喜欢

热点阅读