什么网站做学校设计,黄州做网站的,石家庄网站营销,哪家做外贸网站好爱可生开源社区 2024 全新技术专栏《MySQL 核心模块揭秘》第一期。 作者#xff1a;操盛春#xff0c;爱可生技术专家#xff0c;公众号『一树一溪』作者#xff0c;专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品#xff0c;原创内容未经授权不得随意使用操盛春爱可生技术专家公众号『一树一溪』作者专注于研究 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 更新一条记录。 这个步骤中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 个事务对象并放入事务池的事务队列。 本期问题运行过程中创建一个新的事务池会分配多少内存初始化多少个事务对象关于本期主题如果大家有任何疑问欢迎留言交流 下期预告BEGIN 语句会马上启动事务吗 更多技术文章请访问https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库为开发和运维提供流程自动化能力提升上线效率提高数据质量。
SQLE 获取
类型地址版本库https://github.com/actiontech/sqle文档https://actiontech.github.io/sqle-docs/发布信息https://github.com/actiontech/sqle/releases数据审核插件开发文档https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse