1 MySQL 逻辑架构
MySQL 逻辑架构图:
大体来说,MySQL 可以分为 Server层 和存储引擎层两部分。
Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
存储引擎负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB。
2 MySQL 日志系统
2.1 redo log 重做日志
redo log是 InnoDB 引擎特有的日志。
MySQL 里的 WAL(Write-Ahead Logging) 技术,它的关键点是先写日志(内存中),再写磁盘。
具体就是,当一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log 里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是再系统比较空闲的时候做。
InnoDB 的 redo log 是固定大小的, 当日志写满之后,系统不能再执行新的更新,而是将日志写到磁盘中之后再继续更新。
有了 redo log, InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。
2.2 binlog 归档日志
Server 层的日志是 binlog(归档日志)。只依靠 binlog 是没有 crash-safe 能力的。
假如只有binlog,有可能先提交事务再写binlog,有可能事务提交数据更新之后数据库崩了,还没来得及写binlog。我们都知道binlog一般用来做数据库的主从复制或恢复数据库,这样就导致主从数据库不一致或者无法恢复数据库了。同样即使先写binlog再提交事务更新数据库,还是有可能写binlog成功之后数据库崩掉而导致数据库更新失败,这样也会导致主从数据库不一致或者无法恢复数据库。所以只有binlog做不到crash-safe。
binlog 有两种模式, statement 格式是记 sql 语句, row 格式会记录行的内容,记两条,更新前和更新后都有。
2.3 两种日志的不同点
- redo log 是 InnoDB 引擎特有的; binlog 是MySQL 的 Server 层实现的,所有引擎都可以使用。
- redo log 是物理日志,记录的是 ”在某个数据页上做了什么修改“; binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如 ”给 ID=2 这一行的 c 字段加 1 “。
- redo log 是循环写的, 空间固定会用完; binlog 是可以追加写的。 ”追加写“ 是指文件写到 binlog 文件写到一定大小后会切换到写一个,并不会覆盖以前的日志。
2.4 两阶段提交
一条更新语句的执行,浅色表示在 InnoDB 内部执行,深色表示在执行器中执行
提示
redo log 用于保证 crash-safe 能力。innodb_flush_log_at_trx_commit 这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘。这个参数建议设置为 1 ,这样可以保证 MySQL 异常重启后数据不丢失。
sync_binlog 这个参数设置成 1 的时候, 表示每次事务的 binlog 都持久化到磁盘。这个参数建议设置为 1 ,可以保证 MySQL 异常重启之后 binlog 不丢失。
参考文章:[https://time.geekbang.org/column/article/68633]
[https://www.jianshu.com/p/2f1585c7f2f3]