MySQL · 引擎特性 · InnoDB mini transation

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 前言InnoDB有两个非常重要的日志,undo log 和 redo log;通过undo log可以看到数据较早版本,实现MVCC,或回滚事务等功能;redo log用来保证事务持久性本文以一条insert语句为线索介绍 mini transactionmini transaction 简介mini transation 主要用于innodb redo log 和 undo log写

前言

InnoDB有两个非常重要的日志,undo log 和 redo log;通过undo log可以看到数据较早版本,实现MVCC,或回滚事务等功能;redo log用来保证事务持久性

本文以一条insert语句为线索介绍 mini transaction

mini transaction 简介

mini transation 主要用于innodb redo log 和 undo log写入,保证两种日志的ACID特性

mini-transaction遵循以下三个协议:

  1. The FIX Rules

  2. Write-Ahead Log

  3. Force-log-at-commit

The FIX Rules

修改一个页需要获得该页的x-latch

访问一个页是需要获得该页的s-latch或者x-latch

持有该页的latch直到修改或者访问该页的操作完成

Write-Ahead Log

持久化一个数据页之前,必须先将内存中相应的日志页持久化

每个页有一个LSN,每次页修改需要维护这个LSN,当一个页需要写入到持久化设备时,要求内存中小于该页LSN的日志先写入到持久化设备中

Force-log-at-commit

一个事务可以同时修改了多个页,Write-AheadLog单个数据页的一致性,无法保证事务的持久性

Force -log-at-commit要求当一个事务提交时,其产生所有的mini-transaction日志必须刷到持久设备中

这样即使在页数据刷盘的时候宕机,也可以通过日志进行redo恢复

代码简介

本文使用 MySQL 5.6.16 版本进行分析

mini transation 相关代码路径位于 storage/innobase/mtr/ 主要有 mtr0mtr.cc 和 mtr0log.cc 两个文件

另有部分代码在 storage/innobase/include/ 文件名以 mtr0 开头

mini transaction 的信息保存在结构体 mtr_t 中,结构体成员描述如下

成员属性 描述
state mini transaction所处状态 MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED
memo mtr 持有锁的栈
log mtr产生的日志
inside_ibuf insert buffer 是否修改
modifications 是否修改buffer pool pages
made_dirty 是否产生buffer pool脏页
n_log_recs log 记录数
n_freed_pages 释放page数
log_mode 日志模式,默认MTR_LOG_ALL
start_lsn lsn 起始值
end_lsn lsn 结束值
magic_n 魔术字

一个 mini transaction 从 mtr_start(mtr)开始,到 mtr_commit(mtr)结束

一条insert语句涉及的 mini transaction

下面涉及 mtr 的嵌套,在代码中,每个 mtr_t 对象变量名都叫 mtr,本文中为了区分不同 mtr,给不同的对象加编号

下面一般省略 mtr_t 以外的参数

第一个 mtr 从 row_ins_clust_index_entry_low 开始

mtr_start(mtr_1) // mtr_1 贯穿整条insert语句
row_ins_clust_index_entry_low


mtr_s_lock(dict_index_get_lock(index), mtr_1) // 对index加s锁
btr_cur_search_to_nth_level
row_ins_clust_index_entry_low


mtr_memo_push(mtr_1) // buffer RW_NO_LATCH 入栈
buf_page_get_gen
btr_cur_search_to_nth_level
row_ins_clust_index_entry_low


mtr_memo_push(mtr_1) // page RW_X_LATCH 入栈
buf_page_get_gen
btr_block_get_func
btr_cur_latch_leaves
btr_cur_search_to_nth_level
row_ins_clust_index_entry_low

	
	mtr_start(mtr_2) // mtr_2 用于记录 undo log
	trx_undo_report_row_operation
	btr_cur_ins_lock_and_undo
	btr_cur_optimistic_insert
	row_ins_clust_index_entry_low
	
	
		mtr_start(mtr_3) // mtr_3 分配或复用一个 undo log
		trx_undo_assign_undo
		trx_undo_report_row_operation
		btr_cur_ins_lock_and_undo
		btr_cur_optimistic_insert
		row_ins_clust_index_entry_low
		
		mtr_memo_push(mtr_3) // 对复用(也可能是分配)的 undo log page 加 RW_X_LATCH 入栈
		buf_page_get_gen
		trx_undo_page_get
		trx_undo_reuse_cached // 这里先尝试复用,如果复用失败,则分配新的 undo log
		trx_undo_assign_undo
		trx_undo_report_row_operation
		

 		trx_undo_insert_header_reuse(mtr_3) // 写 undo log header
		trx_undo_reuse_cached
		trx_undo_assign_undo
		trx_undo_report_row_operation
		
		
		trx_undo_header_add_space_for_xid(mtr_3) // 在 undo header 中预留 XID 空间
		trx_undo_reuse_cached
		trx_undo_assign_undo
		trx_undo_report_row_operation
		
		
		mtr_commit(mtr_3) // 提交 mtr_3
		trx_undo_assign_undo
		trx_undo_report_row_operation
		btr_cur_ins_lock_and_undo
		btr_cur_optimistic_insert
		row_ins_clust_index_entry_low
	
	mtr_memo_push(mtr_2) // 即将写入的 undo log page 加 RW_X_LATCH 入栈
	buf_page_get_gen
	trx_undo_report_row_operation
	btr_cur_ins_lock_and_undo
	btr_cur_optimistic_insert
	row_ins_clust_index_entry_low
	
	
	trx_undo_page_report_insert(mtr_2) // undo log 记录 insert 操作
	trx_undo_report_row_operation
	btr_cur_ins_lock_and_undo
	btr_cur_optimistic_insert
	row_ins_clust_index_entry_low
	
	
	mtr_commit(mtr_2) // 提交 mtr_2
	trx_undo_report_row_operation
	btr_cur_ins_lock_and_undo
	btr_cur_optimistic_insert
	row_ins_clust_index_entry_low
	
/*
	mtr_2 提交后开始执行 insert 操作
	page_cur_insert_rec_low 具体执行 insert 操作
	在该函数末尾调用 page_cur_insert_rec_write_log 写 redo log
*/


page_cur_insert_rec_write_log(mtr_1) // insert 操作写 redo log
page_cur_insert_rec_lowpage_cur_tuple_insert
btr_cur_optimistic_insert


mtr_commit(mtr_1) // 提交 mtr_1
row_ins_clust_index_entry_low	

至此 insert 语句执行结束后

一条 insert 是一个单语句事务,事务提交时也会涉及 mini transaction

提交事务时,第一个 mtr 从 trx_prepare 开始

mtr_start(mtr_4) // mtr_4 用于 prepare transaction
trx_prepare
trx_prepare_for_mysql
innobase_xa_prepare
ha_prepare_low
MYSQL_BIN_LOG::prepare
ha_commit_trans
trans_commit_stmt
mysql_execute_command


mtr_memo_push(mtr_4) // undo page 加 RW_X_LATCH 入栈
buf_page_get_gen
trx_undo_page_get
trx_undo_set_state_at_prepare
trx_prepare


mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state, MLOG_2BYTES, mtr_4) 写入TRX_UNDO_STATE
trx_undo_set_state_at_prepare
trx_prepare


mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS, TRUE, MLOG_1BYTE, mtr_4) 写入 TRX_UNDO_XID_EXISTS
trx_undo_set_state_at_prepare
trx_prepare


trx_undo_write_xid(undo_header, &undo->xid, mtr_4) undo 写入 xid
trx_undo_set_state_at_prepare
trx_prepare


mtr_commit(mtr_4) // 提交 mtr_4
trx_prepare




mtr_start(mtr_5) // mtr_5 用于 commit transaction
trx_commit
trx_commit_for_mysql
innobase_commit_low
innobase_commit
ha_commit_low
MYSQL_BIN_LOG::process_commit_stage_queue
MYSQL_BIN_LOG::ordered_commit
MYSQL_BIN_LOG::commit
ha_commit_trans
trans_commit_stmt
mysql_execute_command



mtr_memo_push(mtr_5) // undo page 加 RW_X_LATCH 入栈
buf_page_get_gen
trx_undo_page_get
trx_undo_set_state_at_finish
trx_write_serialisation_history
trx_commit_low
trx_commit


trx_undo_set_state_at_finish(mtr_5) // set undo state, 这里是 TRX_UNDO_CACHED
trx_write_serialisation_history
trx_commit_low
trx_commit


mtr_memo_push(mtr_5) // 系统表空间 transaction system header page 加 RW_X_LATCH 入栈
buf_page_get_gen
trx_sysf_get
trx_sys_update_mysql_binlog_offset
trx_write_serialisation_history
trx_commit_low
trx_commit


trx_sys_update_mysql_binlog_offset // 更新偏移量信息到系统表空间
trx_write_serialisation_history
trx_commit_low
trx_commit

mtr_commit(mtr_5) // 提交 mtr_5
trx_commit_low
trx_commit

至此 insert 语句涉及的 mini transaction 全部结束

总结

上面可以看到加锁、写日志到 mlog 等操作在 mini transaction 过程中进行

解锁、把日志刷盘等操作全部在 mtr_commit 中进行,和事务类似

mini transaction 没有回滚操作, 因为只有在 mtr_commit 才将修改落盘,如果宕机,内存丢失,无需回滚;如果落盘过程中宕机,崩溃恢复时可以看出落盘过程不完整,丢弃这部分修改

mtr_commit 主要包含以下步骤

  1. mlog 中日志刷盘
  2. 释放 mtr 持有的锁,锁信息保存在 memo 中,以栈形式保存,后加的锁先释放
  3. 清理 mtr 申请的内存空间,memo 和 log
  4. mtr—>state 设置为 MTR_COMMITTED

上面的步骤 1. 中,日志刷盘策略和 innodb_flush_log_at_trx_commit 有关

  • 当设置该值为1时,每次事务提交都要做一次fsync,这是最安全的配置,即使宕机也不会丢失事务
  • 当设置为2时,则在事务提交时只做write操作,只保证写到系统的page cache,因此实例crash不会丢失事务,但宕机则可能丢失事务
  • 当设置为0时,事务提交不会触发redo写操作,而是留给后台线程每秒一次的刷盘操作,因此实例crash将最多丢失1秒钟内的事务
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
存储 人工智能 OLAP
LangChain+通义千问+AnalyticDB向量引擎保姆级教程
本文以构建AIGC落地应用ChatBot和构建AI Agent为例,从代码级别详细分享AI框架LangChain、阿里云通义大模型和AnalyticDB向量引擎的开发经验和最佳实践,给大家快速落地AIGC应用提供参考。
128997 94
|
SQL 存储 OLAP
适用于即席查询(Ad-Hoc)的OLAP引擎
即席查询(Ad Hoc)是用户根据自己的需求,灵活的选择查询条件,OLAP系统根据用户输入的查询条件实时返回查询结果。OLAP的即席查询与普通查询的不同之处就是很难对前者进行预先的优化,因为即席查询所响应的大都是随机性很强的查询请求。一个OLAP系统的即席查询能力越强,其应对不同用户的随机性和探索性分析的能力就越强。
410 0
适用于即席查询(Ad-Hoc)的OLAP引擎
|
SQL 分布式计算 运维
开源大数据 OLAP 引擎最佳实践 | 学习笔记(二)
快速学习开源大数据 OLAP 引擎最佳实践
开源大数据 OLAP 引擎最佳实践 | 学习笔记(二)
|
4月前
|
Cloud Native 关系型数据库 新能源
|
运维 关系型数据库 OLAP
阿里云百炼 x AnalyticDB向量引擎, 搭积木式轻松开发专属大模型应用
对大模型应用跃跃欲试,但奈何技术栈复杂难以下手?已经进行试水,但缺乏调优手段无法保障召回率和问答准确度?自行搭建大模型、向量检索引擎、服务API等基础组件难以运维?大模型种类繁多,但缺乏行业模型和应用模板?阿里云百炼 x AnalyticDB向量引擎推出一站式企业专属大模型开发和应用平台,像搭积木一样轻松完成企业专属大模型应用的开发,提供应用API,可一键接入企业自己的业务应用对外提供服务。
1188 0
|
人工智能 Cloud Native 关系型数据库
阿里云数据库国际峰会首度在印尼召开,AnalyticDB向量引擎支持定制AIGC应用
阿里云瑶池数据库面向海外市场正式升级云原生一站式数据管理与服务平台
|
缓存 Cloud Native 关系型数据库
AnalyticDB向量化引擎
AnalyticDB向量化引擎
210 0
|
SQL 运维 OLAP
二、【计算】流|批|OLAP一体 的Flink引擎(下) | 青训营笔记
二、【计算】流|批|OLAP一体 的Flink引擎(下) | 青训营笔记
二、【计算】流|批|OLAP一体 的Flink引擎(下) | 青训营笔记
|
存储 分布式计算 大数据
二、【计算】流|批|OLAP一体 的Fllink引擎 (上)| 青训营笔记
二、【计算】流|批|OLAP一体 的Fllink引擎 (上)| 青训营笔记
二、【计算】流|批|OLAP一体 的Fllink引擎 (上)| 青训营笔记
|
存储 SQL 分布式计算
流/批/OLAP 一体的 Flink 引擎介绍|青训营笔记
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
258 0
流/批/OLAP 一体的 Flink 引擎介绍|青训营笔记

相关产品

  • 云数据库 RDS MySQL 版