事务的起源:事务池和管理器的初始化
爱可生开源社区 2024 全新技术专栏《MySQL 核心模块揭秘》第一期。
作者:操盛春,爱可生技术专家,公众号『一树一溪』作者,专注于研究 MySQL 和 OceanBase 源码。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文基于 MySQL 8.0.32 源码,存储引擎为 InnoDB。
1. 事务池和管理器
作为 MySQL 中支持事务的默认存储引擎,InnoDB 对表中数据的读写操作都在事务中执行。
MySQL 被设计为支持高并发,支持很多客户端同时连接到数据库,这些连接可以同时执行 SQL。
如果这些 SQL 都要读写 InnoDB 表,InnoDB 会为每个连接启动一个事务,这意味着需要同时启动很多事务。
对于 TP 场景,通常情况下,事务都会很快执行完成。启动事务、执行 SQL、提交事务的整个流程只会持续很短的时间。
TP 是 OLTP 的简称,表示在线事务处理;与之相对的另一个常用术语 AP,是 OLAP 的简称,表示在线事务分析。
以这样一个场景为例:
- 客户端连接到 MySQL。
- 客户端执行 begin 语句。
- 客户端执行一条 update 语句,按主键 ID 更新一条记录。<br /> 这个步骤中,InnoDB 会在执行 update 语句之前,真正启动一个事务。
- 客户端执行 commit 语句。
- 客户端关闭数据库连接。InnoDB 会在这一步释放事务。
在这个场景下,InnoDB 事务从启动到释放的整个生命周期,有可能只持续 1 ~ 2 毫秒(甚至更短)。
由于要存放事务 ID、事务状态、Undo 日志编号、事务所属的用户线程等信息,每个事务都有一个与之对应的对象,我们称之为事务对象。
每个事务对象都要占用内存,如果每启动一个事务都要为事务对象分配内存,释放事务时又要释放内存,会降低数据库性能。
为了避免频繁分配、释放内存对数据库性能产生影响,InnoDB 引入了事务池(Pool),用于管理事务。
顾名思义,事务池是一个池子,这个池子存放的东西既不是水,也不是酒,而是事务对象。
对比我们生活中的各种池子,例如:水池、洗手池、池塘,都是有大小限制的。
事务池也一样有大小限制,不能无限制的存放事务对象。数据库繁忙的时候,有很多很多事务对象,需要多个事务池来管理。
事务池多了之后,又会引发另一些问题,例如:
- 怎么创建新的事务池?
- 客户端创建了一个新的数据库连接,要获取一个新的事务对象,从哪个事务池获取?
- 其它问题...
为了解决这些问题,InnoDB 又引入了事务池管理器(PoolManager),用于管理事务池。
MySQL 启动过程中,InnoDB 先创建事务池管理器,然后,事务池管理器创建并初始事务池。
2. 创建事务池管理器
InnoDB 整个生命周期中,事务池管理器只有一个,它有个很重要的属性(m_size),用于指定每个事务池能用多大内存来存放事务对象。
这个属性值来源于一个硬编码的常量值,代码里是这样定义的:
/** Size of on trx_t pool in bytes. */ static const ulint MAX_TRX_BLOCK_SIZE = 1024 * 1024 * 4;
这意味着每个事务池能用来存放事务对象的内存是 4194304 字节,也就是 4M。
MySQL 启动过程中,事务池管理器只会创建并初始化一个事务池。
这个事务池会放入事务池管理器的 m_pools 属性。这个属性是个数组(vector),用于管理所有事务池。
创建事务池的过程中,InnoDB 会分配一块 4M 的内存用于存放事务对象。
每个事务对象的大小为 992 字节,4M 内存能够存放 4194304 / 992 = 4228 个事务对象。
3. 初始化事务池
事务池创建完成之后,就该初始化了。事务池的初始化,主要是为了得到一些事务对象。
事务池有一个队列,用于存放已经初始化的事务对象。我们称这个队列为事务队列。
一个事务池有 4M 内存可以存放事务对象,这块内存会被分隔成 4228 个小块。每初始化一块小内存,就会得到一个事务对象,这个事务对象会被放入事务队列。
InnoDB 初始化事务池的过程中,不会初始化全部的 4228 块小内存,只会初始化最前面的 16 块小内存,得到 16 个事务对象并放入事务队列。
初始事务池完成之后,事务队列中只有 16 个事务对象。
那么,剩余的 4212 块小内存什么时候会被初始化?
**它们会在这种情况下被初始化:**启动过程中初始化的 16 个事务对象都被取走使用了,事务队列变成空队列了。
此时,需要再分配一个事务对象用于启动新事务,InnoDB 就会把剩余的 4212 块小内存全部初始化,得到 4212 个事务对象并放入事务队列。
有一点需要说明,不管是启动过程中初始化的 16 块小内存,还是运行过程中初始化的 4212 块小内存,都是在循环里一个一个初始化的。每一轮循环都要干两件事:
- 初始化一块小内存,得到一个事务对象。
- 把事务对象放入事务池的事务队列中。
初始化小块内存的过程中,会初始化事务对象的各个属性。这里我们就不一一介绍这些属性了,等到该它们出场的时候,再按需介绍。
4. 总结
InnoDB 只有一个事务池管理器,用于管理 N 个事务池(N >= 1),每个事务池可以管理 4228 个事务对象。
MySQL 启动过程中,InnoDB 会先创建事务管理器。事务管理器会创建一个事务池,初始化 16 个事务对象放入事务池的事务队列。
MySQL 运行过程中,如果这 16 个事务对象都正在被使用,InnoDB 需要一个新的事务对象时,会一次性初始化剩余的 4212 个事务对象并放入事务池的事务队列。
本期问题:运行过程中,创建一个新的事务池,会分配多少内存?初始化多少个事务对象?<br />关于本期主题,如果大家有任何疑问,欢迎留言交流!
下期预告:BEGIN 语句会马上启动事务吗?
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
SQLE 获取

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
R 语言社区知名开发者“谢益辉”被 RStudio/Posit 公司解雇
R Markdown、knitr、blogdown 和 bookdown 等 R 软件包的创建者谢益辉于日前发布博客表示,自己已于 2023 年底被 Posit (原 Rstudio) 公司解雇,并于 2024 年 1 月 1 日正式离开该公司。 在写了这么多年的 “*down” packages 后,我在这里宣布“Yihui-down”。 谁倒下了?我。在 RStudio/Posit 工作了 10 多年之后,现在是我探索其他机会的时候了。两个多星期前,我被告知被裁员了,最后一天是 2023-12-31。坦率地说,我感到非常惊讶,但只是短暂的惊讶。我完全尊重 Posit 的决定,并很快接受了我的贡献不再配得上这里的全职工作这一结论。一段关系的结束往往并不意味着任何一方做错了什么或失败了什么。相反,它可能只是表明双方不匹配,这很正常。人就是会变。回想起这些美好的岁月,我离开时大多怀着感激之情。 谢益辉表示,Posit 同时为他提供了一个合同工方案;因此这一离开并不意味着诀别,他后续将继续维护 R Markdown 系列包(暂定一年)。现有的 R 软件包仍将得到维护。但 DT 软件包是唯一...
- 下一篇
权威整理!2023年度数据库回顾:Databases in 2023: A Year in Review
StoneDB开源地址 https://github.com/stoneatom/stonedb 作者:Andy Pavlo 编辑:宇亭 今年和去年一样,我以服用抗生素的方式开始新的一年,因为我的亲生女儿从卡内基梅隆大学的幼儿园带回来一个讨厌的鼻窦问题。这发生在我第一任妻子背叛我并给我带来COVID之后。尽管如此,去年数据库领域发生了很多重大事件,是时候写一篇年度评论了。 我的目标是保持我的尖锐观点公正,避免哗众取宠的标题。如果你对这个游戏不熟悉,或者对我的无拘无束的机智不够了解,你也可以查看我其他针对2022年和2021年的年终数据库评论。 RiseofVectorDatabases 向量数据库的崛起 这无疑是向量数据库的一年。虽然其中的一些系统已经存在了几年,但对LLM和建立在它们之上的服务(例如ChatGPT)的广泛兴趣在去年把它们推向了最前沿。向量数据库承诺基于数据的语义而不是仅基于其内容来提供对数据的更深入的搜索。也就是说,应用程序可以搜索与主题相关的文档(例如“有关摆摊的歌曲的嘻哈团体”),而不是搜索包含确切关键词的文档(例如“武当派”)。 实现这些类型搜索的“魔法”是转换...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启