重新整理 mysql 基础篇————— 介绍mysql日志[二]
前言
对于后端开发来说,打交道最多的应该是数据库了,因为你总得把东西存起来。
或是mongodb或者redis又或是mysql。然后你发现一个问题,就是他们都有日志系统,那么这些日志用来干什么的呢?
举两个例子,回滚和同步。
回滚,这里的回滚是比如说一条语句增加了1,然后再减一吗?这里的回滚操作并不是这样的。
比如说我要更新一条语句,update test set a=1 where b=2,这样的语句,如果这条语句需要回滚,那么操作就应该是在执行前,先查询这条数据进行保存,如果执行完毕需要回滚,那么就直接把原来那条语句写回去。
又比如说,你的数据库要还原到一个小时前,那么你可以把2个小时前的备份拿出来,然后运行前两个小时到前一个小时的日志文件,那么这个时候就相当于回到了一个小时前了。
同步,比如说主从同步了,这样老生常谈的了,一般通过事务日志来同步。
总之,有了日志,那么可以帮我们实现很多功能的了。
那么mysql 在innodb 引擎下,有两个日志非常重要,那就是redo log(重做日志)和 binlog(归档日志)日志。
如果没有这两个日志,应该没啥人敢用mysql的了,因为这两个日志使用了保证mysql的数据完整性的,如果一个数据库连完整性都不能保证,那么是非常危险的。
正文
redo log
首先看下redo log,这个是什么呢? 这个是innodb存储引擎的日志。
说一个它的功能哈,前文提及到存储引擎就相当于我们操作系统的文件系统。
那么问题来了,我们的文件系统是有缓存的,比方说我们写入一个文件,当我们调用函数的时候,不会直接写入,而是写入缓存去,而后又文件系统自己判断啥时候应该写入进去。
判断啥时候应该写入进去,其中有一个标准就是这次要写入缓存的时候,判断缓存是否能够装的下,如果装不下,那么先写入文件,清除缓存,然后再写入缓存。
第二个判断标准就是根据时间某一段时间后进行写入。
同样存储引擎也要为这一段事情操心啊。如果我们更新一条语句,存储引擎就直接给我们操作正在存储数据的地方,那效率可想而知。
所以说,存储引擎就想到一个方法,把更新记录记录到redo log 中,等redo log 快写满,然后就操作到磁盘,或等空闲时间更新进去。
写完redo log 之后,就会告诉执行器,执行完毕了。这个时候我们的应用程序得到更新成功的回调。
如果单纯只写入redo log是不行的,因为存储过程不仅要写,还要读啊,如果写完redo log 通知我们的应用程序更新成功,这个时候还没写入到数据文件,那么我们的应用程序去读的时候就读到了旧的数据。
那么这个时候,存储引擎是这么干的。 反正你给我查询的时候要先查询内存,内存中没有才去查询数据文件。那么存储引擎,先更新到内存中,然后更新到redo log。这样对于存储引擎外部来说,是更新了的,毕竟对于外部来说存储引擎是一个整体。
这就是MySQL里经常说到的WAL技术,WAL的全称是Write-Ahead Logging。
那么这个redo log 是一个什么样的机制呢?难道就一直记录到一个文件中,然后当要写入数据文件的时候,全部写入,然后删除?
如果这么干效率自然是低了。redo log的机制是这样的。
redo log 是由四个文件组成,每个文件大小为1G左右,这个都是可以设置的。
有两个参数,分别为checkpoint 和 write pos。
write pos 是当前记录的位置。checkpoint 是当前写入到数据文件的位置。
比如说:
一开始的时候write pos 写的了第二个文件的问题,如果为位置1000。
这个时候还没有去正在写入数据文件,那么这个时候checkpoint 位置就是0。要往数据文件中写入数据的部分就是checkpoint 到 write pos这一段区间,也就是0-1000位置。
那么这个时候存储引擎感觉可以更新了,然后开始写入到正在的数据文件中,那么这个时候开始checkpoints 开始往右移动,假设更新800条。
那么就到了下面这个位置:
这个时候存储引擎感觉比较忙了,那么就更新800条后,继续接执行器的任务,那么write pos 往右继续移动。
那么这个时候就有一个问题出现,比如说文件大小不变,write pos 一直往右移动,这样会超出啊。
那么这个时候write pos 发现自己到了末尾,人家又从第一个开始写,覆盖写入。
如下:
绿色横线部分是要更新到数据文件部分。
redo log 还有一个重要的作用,保证数据正在的写入到数据文件中。
比如说这个时候正在写入数据文件,然后数据库异常重启了,这里理解异常重启,简单点理解就是内存都没了。
那么我们知道写入文件是有缓存的,如果写入到一半异常了,那么数据其实是丢了的。
有了redo log之后,只有数据文件flush了,那么这个时候checkpoint才开始偏移,否则就如果异常了内存没了,那么继续覆盖更新,因为checkpoint 没有变化,那么还是从原来那个异常前的位置开始同步。
那么问题来了,这时候就会想,数据文件是文件,redo log也是文件啊。如果写入的时候在缓存区,然后宕机这个时候也没了啊。
没错,的确有这个问题,这个时候为了数据安全,redo log直接不使用缓存区。
redo log用于保证crash-safe能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘。
binlog
binlog 是每个mysql都有的,而不是存储引擎的东西,属于mysql 的server 层的东西。
对比一下binlog 和 redo log。
这两种日志有以下三点不同。
redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。
redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。
redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
一条更新语句在innodb引擎下的更新过程:
1. 执行器先找引擎取ID=2这一行。ID是主键,引擎直接用树搜索找到这一行。如果ID=2这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
2. 执行器拿到引擎给的行数据,把这个值加上1,比如原来是N,现在就是N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态。然后告知执行器执行完成了,随时可以提交事务。
4. 执行器生成这个操作的binlog,并把binlog写入磁盘。
5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交(commit)状态,更新完成。
这个时候有人可能会问,如果第3步骤先更新到内存,这个时候要是读取操作而之后redo log没有写入就宕机怎么办?因为是写入是有锁的,如果没有提交事务,这个时候有写锁。
这时候就发现一个细节,那就是redo log 一条记录有两个状态一个是prepare,一个是commit状态。
那么为什么要两个状态呢?
我们知道mysql 主从,其实是通过binlog 一条一条发送给从数据库,让从数据库执行binlog里面的操作。
假设没有这两个状态。
假如innodb 写入redo log之后呢,这个时候数据库突然宕机了,这个时候redo log 是有的记录的,这个时候binlog 没有记录。
那么innodb 通过redo log 进行写入到数据文件后,binlog 依然没有这一条记录。那么从库就少了一条操作了。
这个时候主从永远不可能一致。
如果有了两个状态,数据库重启后,innodb存储引擎还是会通知binlog。这时候两个状态就保证了binlog里面的数据完整性。
那么这个时候又会问了,假如上面第四步执行了,第五步没有执行怎么办?比如宕机了。
是啊,这个时候bin log 中有记录但是redo log没有记录。
那么从库就少了一条操作记录了。
这个时候主从永远不可能一致。同样,我们如果数据库退回到某个时间点,如果binlog 和 redolog不一致的话,同样适用binlog进行回滚一样的会遇到这个问题。
如果有了redo log 的prepare 状态,那么如果数据库重启的时候检测到宕机,这个时候redo log里面prepare 状态的数据就会和binlog里面的数据进行校验,进而进行恢复。
这种有两个状态的提交,叫做两阶段提交。他们起到的作用是如果宕机检测到异常,就会对比恢复。
同样binlog也是文件,同样存在缓存的问题,sync_binlog这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。
结
以上只是个人整理,如有错误,望请指点。
下一节事务。
重新整理 mysql 基础篇————— 介绍mysql日志[二]的更多相关文章
- 重新整理 mysql 基础篇————— 介绍mysql[一]
前言 准备整理mysql的基础篇了,前面整理了sql语句序列的的<sql 语句系列(八百章)>,感觉很多用不上,就停下来了,后续还是会继续整理. mysql 基础篇主要是对一些基础进行整理 ...
- 【目录】mysql 基础篇系列
随笔分类 - mysql 基础篇系列 mysql 开发基础系列22 SQL Model(带迁移事项) 摘要: 一.概述 与其它数据库不同,mysql 可以运行不同的sql model 下, sql m ...
- mysql 基础篇5(mysql语法---数据)
6 增删改数据 -- ********一.增删改数据********* --- -- 1.1 增加数据 -- 插入所有字段.一定依次按顺序插入 INSERT INTO student VALUES(1 ...
- 「MySQL高级篇」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- 「 MySQL高级篇 」MySQL索引原理,设计原则
大家好,我是melo,一名大二后台练习生,大年初三,我又来充当反内卷第一人了!!! 专栏引言 MySQL,一个熟悉又陌生的名词,早在学习Javaweb的时候,我们就用到了MySQL数据库,在那个阶段, ...
- MySQL基础配置之mysql的默认字符编码的设置(my.ini设置字符编码) - 转载
MySQL基础配置之mysql的默认字符编码的设置(my.ini设置字符编码) MySQL的默认编码是Latin1,不支持中文,那么如何修改MySQL的默认编码呢,下面以设置UTF-8为例来说明. 需 ...
- MySQL基础配置之mysql的默认字符编码的设置(my.ini设置字符编码)
MySQL基础配置之mysql的默认字符编码的设置(my.ini设置字符编码) MySQL的默认编码是Latin1,不支持中文,那么如何修改MySQL的默认编码呢,下面以设置UTF-8为例来说明. 需 ...
- [MySQL实战-Mysql基础篇]-mysql的日志
参考文章: https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html https://dev.mysql.com/doc/ ...
- 《MySQL 基础课程》笔记整理(基础篇)
一.尝试MySQL 1.打开MySQL # 启动MySQL服务 sudo service mysql start # 使用 root 用户登录,这里密码为空,直接回车登录 mysql -u root ...
随机推荐
- 机器视觉-EasyDL商品检测-标准版-Demo
机器视觉-EasyDL商品检测-标准版 功能: EasyDL是百度大脑中的一个定制化训练和服务平台,EasyDL零售版是EasyDL针对零售场景推出的行业版,定制商品检测服务是EasyDL零售版的一项 ...
- 初探SQL注入需要知道的5个问题
SQL注入产生原理 可控变量(注入点,就是传参) 带入数据库查询 变量未存在过滤或过滤不严谨 例子: 获取admin表的pass里面的数据 select * from users where id=1 ...
- HBASE-使用问题-split region
问题描述: HBASE表的管理以REGION分区为核心,通常面临如下几个问题: 1) 数据如何存储到指定的region分区,即rowkey设计,region splitkey设计 2)设计的split ...
- c#私钥加密统一JAVA
public static string RSADecryptByPavKey(string pavKey,string strEncryptString) { string clearText = ...
- 在Visual Studio 中使用git——文件管理-下(六)
在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...
- C++ primer plus读书笔记——第13章 类继承
第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生 ...
- 浅尝js垃圾回收机制
局部作用域内的变量,在函数执行结束之后就会被js的垃圾回收机制销毁 为什么要销毁局部变量? => 为了释放内存 js垃圾回收机制何时会销毁局部变量 : 如果局部变量无法再得到访问,就会被 ...
- CRM系统如何改善企业业务流程
工作流管理是CRM客户管理系统的一个重要功能.当企业进行业务管理和处理时,会有一套自己的工作流程.使用CRM系统,可以帮助企业改进整个工作流程,利用系统的流程设置模块,将各个部门所处理的活动定义为过程 ...
- shell中的 “.”和source export
在shell脚本里面export的环境变量,在set里面竟然看不到.为什么在shell脚本里面用export设置环境变量之后,当shell执行完了,用set命令看不到呢?但是你如果直接在终端里expo ...
- [刷题] 300 Longest Increasing Subsequence
要求 给定一个整数序列,求其中的最长上升子序列长度 子序列元素可不相邻 元素相等不算上升 一个序列可能有多个最长上升子序列,但最长的长度只有一个 思路 暴力解法:选择所有子序列进行判断((2^n)*n ...