之前,有一年多的工作客户端领域的工作经验。
后来,也在字节做了一年多的后端业务。
现在希望做一些MySQL
总结,丰富一下自己在后端领域的积累。
目录如下:
MySQL 基础技术(一) —— MySQL 是如何查询的?
MySQL 基础技术(二) —— MySQL 是如何更新的?
MySQL 基础技术(三)—— MySQL 如何保证数据不丢失?
MySQL 基础技术(四)—— MySQL 如何保证高可用?
一、引子
上一篇文章,我们讲述了:《MySQL 是如何查询的?》
那么,如果我们执行了一条更新语句,MySQL 是如何工作的呢?
例如:
select * from <table_name> set <table_column> = "test" where id = 647;
首先,上篇文章:我们讲述了 MySQL
的设计架构。
从MySQL
的流程上来说,依然会
先经过 Server
层:
- 连接器:(连接/校验权限)
- 分析器:(词法/语法分析)
- 优化器:(选择索引)
- 执行器:(调用
engine
层接口,执行更新操作)
再到 Engine
层:调用具体的更新接口。
我们知道,磁盘的I/O是有瓶颈的。
如果每次更新都直接写磁盘,MySQL
很容易就会忙不过来。
因此,为了解决这个问题。
MySQL
采用了WAL
技术(Write-Ahead Logging
),即先写日志,再写磁盘。
忙的时候,先写日志。等闲下来,一起刷到磁盘。
因此,需要会两个特殊的日志模块,也是今天的主角:binlog
和 redo log
。
其中,
binlog
对应Server
层的日志。(Server
层通用)
redo log
对应Engine
层 innoDB
引擎的日志系统。(因为 innoDB
最常用,也是 MySQL
默认的存储引擎。别的存储引擎会不一样)
接下来,我们会重点介绍这两个日志系统。
二、binlog
binlog
是MySQL
的Server
层通用归档日志。
Engine
层的所有存储引擎都可以使用binlog
。
binlog
是逻辑日志。顺序记录了数据库的DDL
和DML
语句。binlog
日志是可以被无限追加写入的,当binlog
文件写到一定大小后,会自动切换到下一个文件。并不会覆盖原来的binlog
文件。
binlog 的作用:
1. 数据恢复
只要我们有数据库在某个时刻的备份,以及这个时刻后的所有 binlog
。那么,我们就能恢复数据库的数据。
我们日常工作中, 我们的DBA同学经常可以帮我们恢复数据库的数据到任何一秒。
他们用的就是 binlog
。
2. 主从复制
为了提高 MySQL
的效率,我们经常会做读写分离,即一主多从。
一个主库(写库),多个从库(读库)。
这时,从库可以监听主库的 binlog
日志,同步写库的所有更改操作。
三、redo log
redo log
是MySQL
Engine
层,InnoDB
存储引擎特有的日志。又称为“重做日志”。
问:为什么称作“重做日志”呢?
答:因为它保证了MySQL
的Crash-Safe
能力。
即使MySQL
发生了异常,重启后,数据也不会丢失。
redo log
是物理日志。可以理解成一个固定空间大小的队列,会被无限循环复写。
每当 MySQL 闲下来,或者 redo log
文件空间被写满了。
那么,MySQL 就会将 redo log
队头的一些数据刷入磁盘,并且清除已经刷入磁盘的redo log
日志。
然后,继续更新工作,将更新的数据写入队尾。
四、两阶段提交
所谓两阶段提交,就是
MySQL
为了保证一致性,在 innoDB 引擎下,会将写 binlog 与 redo log 作为一个事务一起提交。
不会出现先写binlog
或者先写redo log
的情况。
最后,
问:binlog 和 redo log 的区别是什么?
binlog 是 MySQL 的 Server 层实现的逻辑日志,所有引擎都可以使用。
而 redo log 是 InnoDB 引擎特有的物理日志。binlog 是逻辑日志,记录了所有
DDL
、DML
语句的原始逻辑。
而 redo log 是物理日志,记录了某个数据页做了什么修改。binlog 不限空间,可以追加写入。
而 redo log 限制空间大小,只能循环复写。
结束语:
那么,MySQL
是如何保证数据不丢失呢?让我们期待下篇文章。
参考与致谢:
1.《MySQL实战45讲》(林晓斌老师)
2.《带你了解 MySQL Binlog 不为人知的秘密》