前言

可以说mysql的多数特性都是围绕日志文件实现,而其中最重要的有以下三种

  • redo 日志
  • undo 日志
  • binlog 日志

关注公众号,一起交流;微信搜一搜: 潜行前行

1 redo日志

innodb 为了提高磁盘I/O读写性能,存在一个 buffer pool 的内存空间,数据页读入会缓存到 buffer pool,事务的提交则实时更新到 buffer pool,而不实时同步到磁盘(innodb 是按 16KB 一页同步的,一事务可涉及多个数据页,实时同步会造成浪费,随机I/O)。事务暂存在内存,则存在一致性问题,为了解决系统崩溃,保证事务的持久性,我们只需把事务对应的 redo 日志持久化到磁盘即可(redo 日志占用空间小,顺序写入磁盘,顺序I/O)

Mini-Transaction (MTR)

  • sql 语句在执行的时候,可能会修改多个页面,还会更新聚簇索引和二级索引的页面,过程产生的redo会被分割成多个不可分割的组(Mini-Transaction)。MTR怎么理解呢?如一条 insert 语句可能会使得页分裂,新建叶子节点,原先页的数据需要复制到新数据页里,然后将新记录插入,再添加一个目录项指向新建的页子。这对应多条 redo 日志,它们需要在原子性的 MTR 内完成

redo 日志刷盘时机

MTR 产生的 redo 日志先会被复制到一个 log buffer 里(类似 buffer pool)。而同步到磁盘的时机如下:

  • 当 log buffer 的总容量达到 50% ,则刷新日志到磁盘
  • 事务提交时,也需要将同步到磁盘
  • 后台线程,每一秒同步一次
  • 关闭 mysql 服务
  • 做 checkpoit 的时候
    • redo 的空间是有限的。若 redo 日志对应的数据页如果被同步到磁盘,则 redo 日志也可被回收利用了。这回收的过程称之为 checkpoint

2 undo 日志

事务需要保证原子性,也是说事务中的操作要么全部完成,要么什么也不做。如果事务执行到一半,出错了怎么办-回滚。但是怎么回滚呢,靠 undo 日志。undo 日志就是我们执行sql的逆操作

  • undo 日志有两个作用:提供回滚和多个行版本控制(MVCC)
  • 数据页里一行数据的格式如下,其中 roll_point 会指向一个undo 日志

  • undo 日志一般会在事务提交时被删除,但是如果 undo 日志为 MVCC 服务 则暂时保留
  • 一个事务会产生多个 undo 日志,mysql有专门的 undo 页 保存 undo 日志。innodb 会为每一个事务单独分配 undo 页链表(最多分配 4 个链表)

事务ID 和 trx_id

  • mysql 会在内存中维护一个全局变量,每当为某个事务分配 trx_id,则先分配再自增 1
  • 对于只读事务,只有在它第一次创建的临时表执行增删改操作时,才会为事务分配 trx_id
  • 对于读写事务,只有它在执行增删改操作时(包括临时表),才会为事务分配 trx_id

roll_pointer

  • update、delete 语句对应的 undo 日志都会带 trx_id、roll_point 两个属性字段。多条 sql 并发执行时 undo 日志会根据 trx_id 顺序用 roll_point 连成 undo 日志版本链。MVCC 的原理则是靠 undo 日志版本链实现的

3 binlog日志

  • binlog 文件会随服务的启动创建一个新文件
  • flush logs 可以手动刷新日志,生成一个新的 binlog 文件
  • show master status 可以查看 binlog 的状态
  • reset master 可以清空 binlog 日志文件
  • mysqlbinlog 工具可以查看 binlog 日志的内容
  • 执行dml,mysql会自动记录 binlog

binlog 格式

binlog有三种格式:Statement、Row以及Mixed。

  • Statement

    • 每一条增删改数据的 sql 都会记录在 binlog 中
    • 优点:不需要记录每一行的变化,减少了binlog 日志量,节约了IO,提高性能
    • 缺点:由于记录的只是执行语句,为了这些语句能在 slave 上正确运行,因此还必须记录每条语句在执行的时候的一些相关信息。另外 mysql 的复制,像一些特定函数功能,slave 可与 master 要保持一致会有很多相关问题
  • Row
    • 5.1.5 版本的MySQL才开始支持 row level 的复制,它不记录 sql 语句上下文相关信息,仅保存哪条记录被修改
    • 优点:binlog 中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。所以rowlevel的日志内容会非常清楚的记录下每一行数据修改的细节
    • 缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容
  • Mixed
    • 在Mixed模式下,一般的语句修改使用statment格式保存binlog,如一些函数,statement 格式无法完成主从复制的操作,则采用 row 格式保存binlog

binlog 相关操作

  • 查看binlog日志文件内容
[root@root log]# mysqlbinlog 'log.000001'
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#181214 14:44:48 server id 1 end_log_pos 120 CRC32 0x79b6cd10 Start: binlog v 4, server v 5.6.40-log created 181214 14:44:48 at startup
ROLLBACK/*!*/;
BINLOG '
YDIUXA8BAAAAdAAAAHgAAAAAAAQANS42LjQwLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABgMhRcEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAARDN
tnk=
'/*!*/;
# at 120
#181214 14:45:20 server id 1 end_log_pos 199 CRC32 0x10dec193 Query thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1544827520/*!*/;
SET @@session.pseudo_thread_id=1/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 199
#181214 14:45:20 server id 1 end_log_pos 303 CRC32 0x9ec5f952 Query thread_id=1 exec_time=0 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1544827520/*!*/;
insert into t1 values('8','7')
/*!*/;
# at 303
#181214 14:45:20 server id 1 end_log_pos 334 CRC32 0xfd659542 Xid = 10
COMMIT/*!*/;
# at 334
#181214 14:45:35 server id 1 end_log_pos 413 CRC32 0x43929486 Query thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1544827535/*!*/;
BEGIN
/*!*/;
# at 413
#181214 14:45:35 server id 1 end_log_pos 517 CRC32 0x4f1284f2 Query thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1544827535/*!*/;
insert into t1 values('9','7')
/*!*/;
# at 517
#181214 14:45:35 server id 1 end_log_pos 548 CRC32 0x67231f2b Xid = 20
COMMIT/*!*/;
# at 548
#181214 14:45:39 server id 1 end_log_pos 627 CRC32 0x82b39b3e Query thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1544827539/*!*/;
BEGIN
/*!*/;
# at 627
#181214 15:00:48 server id 1 end_log_pos 1646 CRC32 0x7e89c8dc Stop
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
  • 查看binlog具体记录
mysql> show binlog events in 'log.000001';
+------------+------+-------------+-----------+-------------+---------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------+------+-------------+-----------+-------------+---------------------------------------------+
| log.000001 | 4 | Format_desc | 1 | 120 | Server ver: 5.6.40-log, Binlog ver: 4 |
| log.000001 | 120 | Query | 1 | 199 | BEGIN |
| log.000001 | 199 | Query | 1 | 303 | use `test`; insert into t1 values('8','7') |
| log.000001 | 303 | Xid | 1 | 334 | COMMIT /* xid=10 */ |
| log.000001 | 334 | Query | 1 | 413 | BEGIN |
| log.000001 | 413 | Query | 1 | 517 | use `test`; insert into t1 values('9','7') |
| log.000001 | 517 | Xid | 1 | 548 | COMMIT /* xid=20 */ |
| log.000001 | 548 | Query | 1 | 627 | BEGIN |
| log.000001 | 627 | Query | 1 | 732 | use `test`; insert into t1 values('10','7') |
| log.000001 | 732 | Xid | 1 | 763 | COMMIT /* xid=30 */ |
| log.000001 | 763 | Query | 1 | 842 | BEGIN |
| log.000001 | 842 | Query | 1 | 947 | use `test`; insert into t1 values('11','7') |
| log.000001 | 947 | Xid | 1 | 978 | COMMIT /* xid=40 */
+------------+------+-------------+-----------+-------------+---------------------------------------------+
23 rows in set (0.00 sec)

redo log 和 binlog 区别

  • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。redo log 是物理日志,记录的是“在某个数据页上做了什么修改”
  • binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”
  • redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志

redo log 记录事务是两阶段提交的

  • 如果 redo 不是两阶段提交;redo 先写,binlog 后写,会导致依赖 binlog 同步的从库数据缺失。binlog 先写,redo log 后写,则会导致从库多出未提交的脏修改。主从库数据会不一致

redo log 、bin log 和崩溃恢复

redolog 中的事务如果经历了二阶段提交中的prepare阶段,则会打上 prepare 标识,如果经历commit阶段,则会打上commit标识(此时redolog和binlog均已落盘)。崩溃恢复逻辑如下:

  • 按顺序扫描 redo log,如果 redo log 中的事务既有 prepare 标识,又有 commit 标识,就直接提交(复制redo log disk中的数据页到磁盘数据页)
  • 如果 redo log 事务只有 prepare 标识,没有 commit 标识,则说明当前事务在 commit 阶段crash了,binlog 中当前事务是否完整未可知,此时拿着 redolog 中当前事务ID(redolog 和 binlog 中事务落盘的标识),去查看 binlog 中是否存在此ID
    • 如果binlog中有当前事务ID,则提交事务(复制 redolog disk 中的数据页到磁盘数据页)
    • 如果binlog中没有当前事务ID,则回滚事务(使用undolog来删除 redolog 中的对应事务)

欢迎指正文中错误

参考文章

数据库篇:mysql日志类型之 redo、undo、binlog的更多相关文章

  1. 4种常见的MySQL日志类型

    4种常见的MySQL日志类型 .错误日志 记录启动.运行或停止mysqld时出现的问题 log-error=d:/mysql_log_err.txt .查询日志 记录建立的客户端连接和执行的所有语句( ...

  2. MySQL 日志系统之 redo log 和 binlog

    之前我们了解了一条查询语句的执行流程,并介绍了执行过程中涉及的处理模块.一条查询语句的执行过程一般是经过连接器.分析器.优化器.执行器等功能模块,最后到达存储引擎. 那么,一条 SQL 更新语句的执行 ...

  3. MySQL(五)中的redo&undo&binlog

    MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...

  4. MySQL日志系统:redo log与binlog

    日志系统主要有redo log(重做日志)和binlog(归档日志).redo log是InnoDB存储引擎层的日志,binlog是MySQL Server层记录的日志, 两者都是记录了某些操作的日志 ...

  5. mysql 日志类型

    mysql有四种日志: 所有日志:general log 慢查询日志:slow log 二进制日志:binary log 错误日志:error log windows下在my.ini里配置,linux ...

  6. mysql日志类型

    在MySQL中共有4中日志:错误日志.二进制日志.查询日志和慢查询日志 一.错误日志 错误日志名 host_name.err,并默认在参数DATADIR指定的目录中写入日志文件.可使用 --log-e ...

  7. MySQL——日志管理

    一.MySQL日志类型 1.错误:--log--error ---------------------*** host_name.err 2.常规: --general_log host_name.l ...

  8. MySQL表类型

    学习Mysql数据库,Mysql表类型都有哪些是一定需要知道的,下面就为您介绍七种Mysql表类型,希望能对您学习Mysql表类型有所帮助. MySQL作为当前最为流行的免费数据库服务引擎,已经风靡了 ...

  9. MySQL数据库日志文件(redo与undo)

    +++++++++++++++++++++++++++++++++++++++++++标题:MySQL数据库日志文件时间:2019年2月25日内容:MySQL数据库日志文件(redo日志和undo日志 ...

随机推荐

  1. MXNet源码分析 | Gluon接口分布式训练流程

    本文主要基于MXNet1.6.0版本,对Gluon接口的分布式训练过程进行简要分析. 众所周知,KVStore负责MXNet分布式训练过程中参数的同步,那么它究竟是如何应用在训练中的呢?下面我们将从G ...

  2. [LeetCode]1389. 按既定顺序创建目标数组

    给你两个整数数组 nums 和 index.你需要按照以下规则创建目标数组: 目标数组 target 最初为空. 按从左到右的顺序依次读取 nums[i] 和 index[i],在 target 数组 ...

  3. Acme-https证书申请

    Linux下使用acme.sh 配置https 免费证书 简单来说acme.sh 实现了 acme 协议, 可以从 let's encrypt 生成免费的证书. acme.sh 有以下特点: 一个纯粹 ...

  4. 轩辕展览-为什么要做VR虚拟展厅设计?

    沉浸感,有趣和互动体验VR虚拟展厅设计给客户带来高度的沉浸感和互动体验,给客户一种真实的感觉,让客户更愿意参与,使商家的宣传更加客观. 展示方式多样化 ,增加宣传优势在展示产品或企业时,VR全景可达到 ...

  5. 性能测试:k8s集群监控环境搭建(kube-prometheus)

    选择kube-prometheus版本 k8s集群版本是1.22.x 5个节点 说明:如果你电脑配置低,也可以1个master节点,2个node节点 3个节点 Kube-Prometheus地址:ht ...

  6. css文字超出指定行数显示省略号

    display: -webkit-box; overflow: hidden; word-break: break-all; /* break-all(允许在单词内换行.) */ text-overf ...

  7. [GAMEDEV] 个人开发如何找到合适的图片素材?

    1. 起因 起因是想找一些UI设计方面的素材(具体地说,类似于Web或者App上一些按钮/页签/进度条等元素),用到游戏GUI中来,毕竟扁平化的网页设计还是很清爽的. 本以为这方面的素材会比游戏中的图 ...

  8. BGP协议测试—信而泰网络测试仪实操

    关键词  BGP; 协议仿真; 测试原理. 前言:当前信息化时代之下,数据传输已经成为了日常工作和生活必不可少的重要组成部分,网络服务的易得性和可靠性也因此得到广泛关注.这其中负责网络正常工作的诸多协 ...

  9. Guided Anchoring:在线稀疏anchor生成方案,嵌入即提2AP | CVPR 2019

    Guided Anchoring通过在线生成anchor的方式解决常规手工预设anchor存在的问题,以及能够根据生成的anchor自适应特征,在嵌入方面提供了两种实施方法,是一个很完整的解决方案   ...

  10. Linux 查看网卡的MAC地址

    转至:https://www.cnblogs.com/kerrycode/p/13709537.html 如何使用命令查看网卡的MAC地址呢? 下面总结一下查看网卡MAC地址的方式. 1:ifconf ...