mysql8.0查询操作(MySQL 8.0 redo log的深入解析)
mysql8.0查询操作
MySQL 8.0 redo log的深入解析前言
最开始了解mysql实现的时候,总听到redo log, wal(write-ahead logging),undo log这些关键词,了解到redo log主要是用于实现事务的持久化的。为了进一步了解redo log,看了下相关代码(源码版本: mysql 8.0.12),这里简单总结下,主要介绍redo log是如何产生,如何落盘,以及最终通知用户的。
redo log的产生
读写事务在执行的过程中,会不断的产生redo log。申请数据页、修改数据页、记录undo log等,都会产生redo log。mysql将用户事务拆分成一个个mtr(mini transaction),redo log最初产生时就是被记录到mtr中的,并伴随着mtr的提交而提交,最终落到硬盘上。
redo log 的提交
mtr在提交时,会将mtr中的redo log写到系统变量log_sys的log buffer中。mysql8.0一个新特性就是redo log提交的无锁化。在8.0以前,各个用户线程都是通过互斥量竞争,串行的写log buffer,因此能保证lsn的顺序无间隔增长。8.0时用户线程可以并发写log buffer,如果某个用户线程写log buffer成功后,就将自己写的lsn以前的log buffer刷盘,则有可能导致其他用户线程写log buffer还没完成就被刷盘。
为了解决这个问题,mysql 8.0引入了link_buf这个数据结构来避免log buffer的空洞。link_buf实际是一个定长数组,像滑动窗口一样跟踪log buffer一段区间的写入情况,随着log buffer中写入连续redo log不断向前推进。
link_buf的数据结构如图:
当用户在log buffer的start_lsn-end_lsn间写下redo log时,会标记link_buf相应的位置,即将m_link[start_lsn%m_capacity]赋值为为end_lsn-start_lsn。
redo log记录到log buffer的过程如下:
1.首先,各用户线程写redo log时,先根据redo log长度,向系统全局原子变量log_sys.sn获取本次redo log日志的start_lsn, end_lsn。原子变量sn能保证各线程获得的start_lsn-end_lsn区间连续无空洞;
2.用户线程申请到start_lsn-end_lsn区间后,需要先等待到link_buf推进到自己可以使用的位置。
如图所示,start_lsn0-end_lsn0,start_lsn2-end_lsn2, start_lsn3-end_lsn3为三个用户线程新申请的lsn区间;start_lsn1-end_lsn1对应的区间已经标记到link_buf上;start_lsn3-end_lsn3距离tail太远,需要等待link_buf推进才能使用;
3.写入log buffer后,再将start_lsn->end_lsn的范围标记到link_buf(注意:因为只在start_lsn%capacity的位置标记link_buf,所以即使end_lsn超过(m_tail, m_tail+m_capacity)也不影响);
4.用户线程提交事务时设置事件log_sys.writer_event,触发log_writer线程将日志从redo log buffer写到系统缓存(log_writer线程自己也会轮询link_buf判断是否写入了新的日志);
5.log_writer线程推进m_tail,并将m_tail前的log buffer落盘。
redo log 的落盘及通知
前面简述了redo log是如何提交的,在redo log提交以及落盘时,涉及多个线程,他们的关系如下:
用户线程在读写事务提交时,会产生一些redo log,并随着mtr提交而记录到redo log buffer中,随后用户线程尝试设置writer_event触发log_writer线程写日志,并监听属于自己的flush_events[i]事件;
log_writer线程推进link_buf.m_tail,将最大连续lsn前的redo log写入系统缓存,并设置flusher_event触发log_flusher线程;
log_flusher线程将已写入系统缓存的日志刷盘,并设置flush_notifier_event触发log_flush_notifier线程通知用户;
log_flush_notifier根据已刷盘的lsn换算出需要触发的事件,通知用户线程。
具体实现时,通过log_sys中的几个成员变量,跟进redo log的写入情况。其中log_sys.recent_writtern.m_tail表示log buffer最大连续范围;log_sys.write_lsn表示写入到系统缓存的位置;log_sys.flushed_to_disk_lsn表示已落盘的位置。各标记的推进过程如下:
通知用户线程
用户提交事务时,会根据innodb_flush_log_at_trx_commit参数,调用log_wait_for_write或log_wait_for_flush,来等待redo log写入到系统缓存或刷到硬盘。用户线程的通知是通过log_sys.flush_events事件数组来实现的,为了避免一次通知的flush_events过多,flush_events会像桶一样划分给不同的用户线程:redo log是以一个个log block划分的,假设log_sys.flush_events数组长度为m,则第n个log block的刷盘,由flush_events[n%m]事件监听。当log buffer的第l1个log block到第l2个log block被刷盘时,会设置l1-l2之间的log block所属的flush_events,从而redo log在l1-l2之间的用户线程都会收到通知。
总结
mysql8.0通过redo log无锁化,解决了用户线程写redo log时竞争锁带来的性能影响。同时将redo log写文件、redo log刷盘从用户线程中剥离出来,抽成单独的线程,用户线程只负责将redo log写入到log buffer,不再关心redo log的落盘细节,只需等待log_writer线程或log_flusher线程的通知。
以上就是mysql 8.0 redo log的深入解析的详细内容,更多关于mysql 8.0 redo log的资料请关注开心学习网其它相关文章!
原文链接:https://cloud.tencent.com/developer/article/1800303
- mysql8.0关键字段使用(MySQL 8.0新特性之隐藏字段的深入讲解)
- mysql8.0使用(MySQL 8.0新特性 — 检查性约束的使用简介)
- mysql8.0.18.0安装详细教程(mysql 8.0.22 下载安装配置方法图文教程)
- mysql8.0查询操作(MySQL 8.0 redo log的深入解析)
- win10下安装mysql8.0.23 及 “服务没有响应控制功能”问题解决办法(win10下安装mysql8.0.23 及 “服务没有响应控制功能”问题解决办法)
- mybatis为什么还用mysql(关于MyBatis连接MySql8.0版本的配置问题)
- mysql8.0详解(MySQL 8.0 的 5 个新特性,太实用了!)
- mysql8.0安装版安装详细教程(mysql 8.0.24版本安装配置方法图文教程)
- mysql8.0.23.0官方安装手册(MySQL8.0.23安装超详细教程)
- mysql连接navicat报错1045(Navicat 连接MySQL8.0.11出现2059错误)
- mysql8.0.23的安装步骤(mysql 8.0.22 下载安装配置方法图文教程)
- mysql8.0安装教程win10(Windows10下mysql 8.0.22 安装配置方法图文教程)
- mysql8.0.21的安装步骤(mysql8.0.23 msi安装超详细教程)
- mysql8.0如何配超时时间(解决MySQL8.0时区的问题步骤)
- mysql常用存储方案及基本原理(详解分析MySQL8.0的内存消耗)
- mysql8.0.12安装教程图解(mysql 8.0.22 zip压缩包版免安装下载、安装配置步骤详解)
- 郭麒麟(郭麒麟)
- 古人十句 戒骄 名言,醍醐灌顶,受益匪浅(古人十句戒骄名言)
- 《道德经》:功成不局,泰而不骄(道德经:功成不局)
- 每日一典 过江之鲫(每日一典过江之鲫)
- 红色代表什么(红色代表什么意义和象征)
- 菲律宾安全吗(菲律宾安全吗2023)
热门推荐
- linux部署flask项目(用uWSGI和Nginx部署Flask项目的方法示例)
- html5页面强制刷新(移动端html5判断是否滚动到底部并且下拉加载)
- apache服务器配置https(Apache Rewrite url重定向功能的简单配置)
- python全局变量设置(Python3.5局部变量与全局变量作用域实例分析)
- dockerfile的镜像原理(dockerfile制作apache镜像的方法)
- sql版本号处理并发(SQL server高并发生成唯一订单号的方法实现)
- mysql dateformat(MySQL的DATE_FORMAT函数的使用)
- python编辑redis(python使用pipeline批量读写redis的方法)
- pyqt一键部署python环境(python使用PyQt5的简单方法)
- Ext.MessageBox.show()的用法及参数配置
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9