视频地址:https://www.bilibili.com/video/BV1Kh41147RV/
文章目录- 一、前言
- 二、事物
- 三、undo log
- 四、redo log
- 五、binlog
- N、其他
- N-1、为什么要在内存中 *** 作,但对于日志还是写入硬盘呢?
- N-2、为什么有了redo log 还要binlog
上次我们讲过一条SQL从应用程序到数据库要经历哪些过程,想必大家都已经有了大致的了解。
但是在讲到buffer pool的时候,我们省略了其中的细节,只是说到数据会先从磁盘加载到内存中去,然后在内存中进行我们的 *** 作,今天我们就来具体看看它在缓冲池中具体要做哪些 *** 作。
二、事物
在具体讲解细节之前,我们先来明确一个概念 事物,大家应该都知道啥是事物,简单来说就是一组命令要么都执着成功,要么都不执行成功。
我们 *** 作数据库的时候,不管是一条SQl还是多条SQL都是以事物为维度去执行的。
假设一个这样的场景:A向B转500块钱,这时候我们要做两个 *** 作,在A的账户下 -500,在B的账户下 +500,并且这两个修改都必须同时成功或失败。
三、undo log
但是我们也知道 *** 作不管怎样都是有前后顺序的对不对?那么为了保证 *** 作的原子性,也就是如果后面的SQL执行失败了,我们可以把前面的 *** 作复原,那这就需要我们把前面的 *** 作记录下来。这个记录的地方就是 undo log
现在我们已经知道了undo log是用来存储修改之前的旧数据,它的作用主要是两个
- 用于事物的回滚
- 用于MVCC里面的读视图
undo log的类型也有两种 insert undo log 、 update undo log
- insert undo log 数据库在插入数据的时候产生,只有在当前事物回滚的时候才有用,所以在当前事物结束的时候它就没用了,就会被删除。
- update undo log 数据库在更新、删除的时候产生,除了当前事物会使用,在快照读的时候也会使用,所以不能随便删除,只有在快照读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除
四、redo log
刚刚我们已经把数据修改了,但只是在内存中进行修改的,这就存在如果系统宕机了,那修改不就丢失了吗?
这里我们就要引入一个新的日志 redo log 重做日志,对数据做的增删改都会记录到这个redo log里面去,如果我们的服务崩了,就可以拿这个redo log里面的数据进行恢复。
上面我们看到这个redo log是先写入内存中去的,只要是没落盘那么都存在数据丢失的可能,MySQl提供了redo log落盘策略,我们可以通过配置 innodb_flush_log_at_trx_commit 来控制
- 0:提交事物的时候不会把redo log buffer 里的数据刷入磁盘
- 1:提交事物的时候,必须把日志刷入磁盘中,可以严格保证数据不丢失 (默认、且推荐的)
- 2:提交事物的时候,先把日志刷入磁盘文件对应的 os cache 缓存里,隔一段时间再把数据刷入磁盘
五、binlog
在之前的学习中,我们或多或少的听过这样一个日志 binlog ,它是用来备份数据,或者主从之间复制数据的。
对数据的增删改也需要同步记录到这个 binlog里面去,binlog刷盘策略通过 sync_binlog 来配置
- 0: 它是写入os cache内存缓存,并不是写入磁盘 (默认的)
- 1: 同步将日志写入磁盘 (推荐的)
- N: 每写N次 *** 作系统缓冲就执行一次刷新 ***
通过上面的描述,我们知道不管是redo log 还是 binlog,都是推荐直接写入磁盘的。
这里还有一个问题,比如我们修改了一条数据,这个数据还存在内存中,查询的时候没关系反正查询的也是内存,但是数据不存入磁盘这肯定是不行的,所以还有一个线程会不定期的把这些修改过的数据刷入磁盘。
注:这个修改过的数据叫做脏页,至于为什么这么叫后续讲解。
经过上面的描述,我们最终的图应当是这样的
整个过程:读取数据到内存 > 写入undo log > 修改数据 > 写入redo log缓存 > 提交事物 > redo log 入盘 > binlog 入盘 > 数据入盘(不定时)
N、其他 N-1、为什么要在内存中 *** 作,但对于日志还是写入硬盘呢?
之所以要把数据读取到内存中进行 *** 作,和大家想的一样:内存 *** 作更快。
可能有小伙伴有疑问了,一顿 *** 作猛如虎,结果还是要把日志写入到硬盘中去,这里要和大家说明下,写入日志的时候是顺序写入的,也就是在之前的内容后面追加,这个写入的速度会非常的快,而进行数据修改写入是随机写入,这个就很慢了。
N-2、为什么有了redo log 还要binlog
- redo log 是属于InnoDB引擎的,binlog是属于MySQL数据库的
- redo log是物理日志,记录的是“在某个数据页上做了什么修改”(数据页上某个偏移量的值);binlog是逻辑日志,记录的是这个语句的原始逻辑(sql、数据行)
- redo log是循环写入的,当空间不足的时候,就会覆盖之前的数据,而binlog是追加方式写入,一块区域写满了,就会新开一个
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)