当前位置: 首页 > article >正文

MySQL有哪些日志?

MySQL主要有三种日志:undo log、redo log、binlog。前两种是InnoDB特有的,binlog是MySQL的Server层中的。

Buffer Pool

buffer pool是MySQL的缓冲池,里面存储了数据页、索引页、undo页等(与数据库不一致的即为脏页)。对数据库做的操作都会先在buffer pool中执行,后配合redo log持久化到磁盘。

undo log

事务回滚

undo log是回滚日志,用于保证事务原子性。在事务执行过程中会记录undo log日志(这里是先记录在buffer pool的undo页中,生成undo log,需要记录对应的redo log),若事务需要回滚,则根据undo log执行与原来相反的操作。

MVCC

我们知道数据库中的一条记录中包含了两个隐藏列:trx_id(事务ID)和roll_pointer(版本指针),undo log记录中也是如此,通过版本指针把记录的旧值连成链表(数据页中的数据就是最新版本),通过版本指针查找记录的旧版本,使用trx_id和Read View判断事务可见性。Read View是什么?

Read View : 快照,在可重复读级别下,每一个事务开始都会生成一个Read View,保证查看的数据一致。
重要字段:

  1. creator_trx_id:创建这个快照的事务ID
  2. m_ids:存储的是当前时刻活跃的事务ID(活跃事务指的是已已启动但未提交的事务)
  3. min_trx_id:活跃事务ID中的最小值
  4. max_trx_id:下一个事务分配的trx_id

如何判断事务可见性?

通过比较记录中的trx_id:

  • trx_id < min_trx_id:代表修改记录的事务早就提交,可见
  • trx_id >= max_trx_id:代表修改记录的事务在当前时刻还没启动,不可见
  • 分两种情况:
    • trx_idm_ids中:事务未提交,不可见
    • trx_id不在m_ids中:事务已提交,不可见

通过比较trx_id来控制并发事务,这就是MVCC(多版本并发控制)。

redo log

redo log是重做日志,使得MySQL具有crash-safe(崩溃恢复)能力,保证了事务的持久性
首先,redo log是一个循环文件组,写入为循环写。通过以下两个参数设置文件数量和文件大小:

innodb_log_files_in_group
innodb_log_file_size

事务执行时的操作会被写入redo log buffer中,记录的字段主要有:操作类型、修改的数据页号、修改数据的页内偏移量、修改的字段值。
write pos指向当前记录的位置,checkpoint指向当前要擦除的位置。
在这里插入图片描述

当write pos追上checkpoint时,说明redo log文件满了,这时不能再进行新的更新操作了,更新操作的SQL将被堵塞。此时会停下来把buffer pool中的脏页刷盘,让checkpoint后推,才可以进行操作。

刷盘
  1. 写入方式:redo log文件是顺序写(性能好),而数据页是随机写。
  2. 刷盘时机:
    1. 数据库正常关闭
    2. InnoDB会有一个后台线程每隔一秒将redo log buffer持久化到磁盘
    3. 事务提交时(控制参数:innodb_flush_log_at_trx_commit

innodb_flush_log_at_trx_commit参数

  • 参数为0:留在redo log buffer中,不刷新到磁盘(可能会丢失上1秒的所有数据)。
  • 参数为1:直接刷新到磁盘(fsync)。
  • 参数为2:写入redo log文件(操作系统中的Page Cache)(操作系统不挂就不会丢失)。

参数0和2是通过上文说到的后台线程来刷盘的。

  • 0:redo log buffer (write) -> Page Cache (fsync) -> 磁盘
  • 2:Page Cache (fsync) -> 磁盘

binlog

binlog是归档日志。主要用于数据备份、主从复制。

与redo log的区别
  1. 适用范围不同:开篇就说了,redo log是InnoDB存储引擎特有的,binlog是都能使用的
  2. 日志格式:binlog有三种格式:ROW、STATEMENT(默认)、MIXED。
    1. STATEMENT记录操作的SQL(相当于记录了逻辑操作,所以针对这种格式binlog可以被称为逻辑日志),主从复制中根据SQL语句重现,但是当记录的SQL中使用了动态函数(uuid, now...),这样就会导致主从数据不一致。
    2. ROW记录行数据被修改成什么样了(这时就不能称为是逻辑日志了),产生记录多,导致binlog文件过大。
    3. MIXED:根据情况自动选择日志格式(STATEMENT, ROW)
    4. redo log物理日志,记录的是在某个数据页做了什么修改。比如对 XXX 表空间中的 XXX数据页 ZZZ 偏移量的地方做了 AAA 修改。
  3. 写入方式不同:binlog是追加写,写满一个文件就创建一个新文件接着写。
  4. 用途不同。
主从复制
  1. 主库写入binlog,提交事务,更新数据。
  2. 从库会创建一个专门的 I/O 线程连接主库的log dump线程,来接收主库的binlog日志,然后再把binlog信息写入一个relay log(中继日志),返回给主库“复制成功”的响应。
  3. 从库会创建一个用于回放binlog的线程,去读relay log,然后回放binlog更新存储引擎中的数据,最终实现主从的数据一致性。
什么时候刷盘

首先要知道的是一个事务的binlog不能被拆开(因为要保证原子性)。
在事务执行过程中,会先把binlog存储到binlog cache,binlog cache(通过binlog_cache_size控制单个线程中binlog cache的大小),满了需要暂存到磁盘。
事务提交时,会把binlog cache的日志writePage Cache(binglog文件) ,并清空binlog cache。通过sync_binlog参数控制fsync到磁盘的时机。
sync_binlog参数:

  • 0:不会fsync,后续由操作系统决定何时存储到磁盘
  • 1:立刻fsync
  • N:等存储了 N 个事务的binlog再调用fsync
两阶段提交

目的:防止在提交事务时, redo log和binlog有一个写入失败( 数据库宕机等原因 ),导致主从数据不一致。

主要方式就是先写redo log,后写binlog

阶段1:准备阶段(Prepare):写入redo log,将事务状态设为prepare

阶段2:提交阶段(Commit):写入binlog并持久化到磁盘,成功后,将redo log状态改为 commit

造成问题:

  1. 磁盘 I/O 次数多:一次事务提交至少需要两次刷盘
  2. 锁竞争激烈:为了保证多事务不发生顺序上的混乱

MySQL使用组提交的方式进行了优化,但是我在这里就不多说了。


http://www.kler.cn/a/421668.html

相关文章:

  • 《OpenCV 基础全攻略:从入门到精通》
  • PostgreSQLt二进制安装-contos7
  • 【北京迅为】iTOP-4412全能版使用手册-第三十二章 网络通信-TCP套字节
  • 顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Maltab)
  • zerotier实现内网穿透
  • SpringBoot集成Milvus|(实现向量的存储和查询)
  • AMEYA360:上海永铭电子全新高压牛角型铝电解电容IDC3系列,助力AI服务器电源高效运转
  • vue初始化脚手架
  • MySQL 事务和索引
  • 【Oracle11g SQL详解】INSERT INTO 的用法及插入数据注意事项
  • 2024前端面试经验分享
  • Nginx学习-安装以及基本的使用
  • Hadoop分布式文件系统(二)
  • JAVA |日常开发中数据集合详解
  • JAVA-响应报文转XML
  • 浅谈网络 | 应用层之流媒体与P2P协议
  • 给UE5优化一丢丢编辑器性能
  • Ubuntu 查看应用的版本列表和新版本
  • freeswitch通过bridge+定制化distributor,进行sip媒体的负载均衡代理
  • 开发者如何使用GCC提升开发效率GUI操作
  • el-select 修改样式
  • 光控资本:积极布局 跨年行情渐行渐近
  • SQL进阶——JOIN操作详解
  • Base 崛起,SynFutures 或成生态系统中最具潜力应用
  • 【C++】从零到一掌握红黑树:数据结构中的平衡之道
  • How to use the ‘git log‘ command to get change log for each file?