MySQL · 源码分析 · Subquery代码分析
MySQL中的码解子查询源码分析深入探讨
在了解了MySQL中衍生表的前篇内容后,现在我们将聚焦于条件和投影中嵌套的码解子查询,这些在MySQL内部是码解通过Item_subselect来处理的。子查询在SQL中分为相关和非相关两种,码解MySQL在解析和语义检查后能判断其相关性,码解并可能在后续优化中调整。码解python3爬虫源码
所有子查询都属于Item_subselect类的码解子类,这个类的码解继承结构展示了MySQL支持的子查询类型和它们的标记。执行方式则由Subquery_strategy枚举决定,码解总共分为五种可能的码解策略,尽管优化过程涉及复杂函数,码解但重点在于理解整体流程。码解
MySQL对查询处理分为三个阶段:prepare、码解optimize和execute。码解在prepare阶段,码解从抽象语法树(AST)构建开始,主要针对子查询进行转换,虽涉及规则和复杂函数,但核心思路清晰。在这个阶段,仅留下标记为CANDIDATE_FOR_IN2EXISTS_OR_MAT的子查询,其执行方式在优化阶段决定。
优化阶段则基于代价估算,选择子查询的执行方式,是物化执行还是EXISTS方式。这个阶段的逻辑相当丰富,但这里仅关注子查询部分。
到了execute阶段,执行逻辑相对简单,根据先前的分析,总结了执行子查询的几种方式。总的来说,子查询处理的复杂性高于衍生表,特别是prepare阶段的变换,这为深入源码研究提供了初步框架。轻博客系统源码
MySQL XA事务源码分析
事务类型外部 XA PREPARE 流程
省流版:
详细版:
外部 XA COMMIT 过程
省流版:
详细版:
外部 XA 2PC 阶段 Log 落盘顺序
------------------- XA PREPARE START -------------------------
------------------- XA PREPARE END -------------------------
.
.
.
.
.
.
------------------- XA COMMIT START -------------------------
------------------- XA COMMIT END -------------------------
本地事务 commit 流程
省流版
与外部 XA PREPARE 2PC 的不同
与外部 XA COMMIT 的不同
详细版:
------------------- PREPARE START -------------------------
------------------- PREPARE END -------------------------
------------------- COMMIT START -------------------------
------------------- COMMIT END -------------------------
外部 XA ROLLBACK 流程
省流版(Not Prepared Rollback 和 Prepared Rollback 的不同之处)
详细版
Not Prepared Rollback(在 end - prepare 之间 rollback)
Prepared Rollback(在 prepare 之后 rollback)
外部 XA RECOVERY 流程
省流版
详细版
本地事务 RECOVERY 流程
省流版
详细版
为什么只遍历最后一个binlog文件:
rotate 到新的 binlog 文件前,redo log 强制落盘,因此redo commit记录会落盘,保证老的binlog文件没有正在提交的事务
MySQL 核心模块揭秘 | 期 | 创建 savepoint
回滚操作,除了回滚整个事务,还可以部分回滚。部分回滚,需要保存点(savepoint)的协助。本文我们先看看保存点里面都有什么。
作者:操盛春,爱可生技术专家,公众号『一树一溪』作者,专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源
本文基于 MySQL 8.0. 源码,存储引擎为 InnoDB。
InnoDB 的事务对象有一个名为undo_no 的属性。事务每次改变(插入、更新、删除)某个表的一条记录,都会产生一条 undo 日志。这条 undo 日志中会存储它自己的序号。这个序号就来源于事务对象的 undo_no 属性。
也就是说,事务对象的 undo_no 属性中保存着事务改变(插入、更新、删除)某个表中下一条记录产生的 undo 日志的序号。
每个事务都维护着各自独立的 undo 日志序号,和其它事务无关。
每个事务的 undo 日志序号都从 0 开始。事务产生的第 1 条 undo 日志的序号为 0,第 2 条 undo 日志的序号为 1,依此类推。乐彩源码教程
InnoDB 的 savepoint 结构中会保存创建 savepoint 时事务对象的 undo_no 属性值。
我们通过 SQL 语句创建一个 savepoint 时,server 层、binlog、InnoDB 会各自创建用于保存 savepoint 信息的结构。
server 层的 savepoint 结构是一个SAVEPOINT 类型的对象,主要属性如下:
binlog 的 savepoint 结构很简单,是一个 8 字节的整数。这个整数的值,是创建 savepoint 时事务已经产生的 binlog 日志的字节数,也是接下来新产生的 binlog 日志写入 trx_cache 的 offset。
为了方便介绍,我们把这个整数值称为binlog offset。
InnoDB 的 savepoint 结构是一个trx_named_savept_t 类型的对象,主要属性如下:
创建 savepoint 时,server 层会分配一块 字节的内存,除了存放它自己的 SAVEPOINT 对象,还会存放 binlog offset 和 InnoDB 的 trx_named_savept_t 对象。
server 层的 SAVEPOINT 对象占用这块内存的前 字节,InnoDB 的 trx_named_savept_t 对象占用中间的 字节,binlog offset 占用最后的 8 字节。
客户端连接到 MySQL 之后,MySQL 会分配一个专门用于该连接的用户线程。
用户线程中有一个m_savepoints 链表,用户创建的多个 savepoint 通过 prev 属性形成链表,m_savepoints 就指向最新创建的 savepoint。
server 层创建 savepoint 之前,会按照创建时间从新到老,逐个查看链表中是否存在和本次创建的 savepoint 同名的 savepoint。
如果在用户线程的 m_savepoints 链表中找到了和本次创建的 savepoint 同名的 savepoint,需要先删除 m_savepoints 链表中的同名 savepoint。
找到的同名 savepoint,是 server 层的SAVEPOINT 对象,它后面的图片转源码网站内存区域分别保存着 InnoDB 的 trx_named_savept_t 对象、binlog offset。
binlog 是个老实孩子,乖乖的把 binlog offset 写入了 server 层为它分配的内存里。删除同名 savepoint 时,不需要单独处理 binlog offset。
InnoDB 就不老实了,虽然 server 层也为 InnoDB 的 trx_named_savept_t 对象分配了内存,但是 InnoDB 并没有往里面写入内容。
事务执行过程中,用户每次创建一个 savepoint,InnoDB 都会创建一个对应的 trx_named_savept_t 对象,并加入 InnoDB 事务对象的 trx_savepoints 链表的末尾。
因为 InnoDB 自己维护了一个存放 savepoint 结构的链表,server 层删除同名 savepoint 时,InnoDB 需要找到这个链表中对应的 savepoint 结构并删除,流程如下:
InnoDB 从事务对象的 trx_savepoints 链表中删除 trx_named_savept_t 对象之后,server 层接着从用户线程的 m_savepoints 链表中删除 server 层的SAVEPOINT 对象,也就连带着清理了 binlog offset。
处理完查找、删除同名 savepoint 之后,server 层就正式开始创建 savepoint 了,这个过程分为 3 步。
第 1 步,binlog 会生成一个 Query_log_event。
以创建名为test_savept 的 savepoint 为例,这个 event 的内容如下:
binlog event 写入 trx_cache 之后,binlog offset 会写入 server 层为它分配的 8 字节的内存中。
第 2 步,InnoDB 创建 trx_named_savept_t 对象,并放入事务对象的 trx_savepoints 链表的末尾。
trx_named_savept_t 对象的 name 属性值是 InnoDB 的 savepoint 名字。这个名字是根据 server 层为 InnoDB 的 trx_named_savept_t 对象分配的内存的地址计算得到的。
trx_named_savept_t 对象的savept 属性,是溯源码能查一个 trx_savept_t 类型的对象。这个对象里保存着创建 savepoint 时,事务对象中 undo_no 属性的值,也就是下一条 undo 日志的序号。
第 3 步,把 server 层的 SAVEPOINT 对象加入用户线程的 m_savepoints 链表的尾部。
server 层会创建一个SAVEPOINT 对象,用于存放 savepoint 信息。
binlog 会把binlog offset 写入 server 层为它分配的一块 8 字节的内存里。
InnoDB 会维护自己的 savepoint 链表,里面保存着trx_named_savept_t 对象。
如果 m_savepoints 链表中存在和本次创建的 savepoint 同名的 savepoint, 创建新的 savepoint 之前,server 层会从链表中删除这个同名的 savepoint。
server 层创建的 SAVEPOINT 对象会放入m_savepoints 链表的末尾。
InnoDB 创建的 trx_named_savept_t 对象会放入事务对象的trx_savepoints 链表的末尾。
MySQL源码阅读1-启动初始化
通过深入阅读MySQL源码,旨在学习并记录其内核知识。初次探索难免有错误或遗漏,欢迎指正,并期待在后续阅读中对笔记进行修正。
MySQL的启动初始化是关键步骤,涉及核心逻辑与执行流程。关注的入口函数位于`mysql-server-8.0/sql/mysqld.cc::mysqld_main`。
初始化阶段主要关注点包括启动MySQL中的线程,负责执行各种任务。MySQL在初始化时启动的线程种类多样,确保数据管理、查询执行与系统功能高效运作。
调用链显示了初始化过程中的函数调用关系,每个缩进代表一个函数调用,清晰地展示了初始化的执行流程。
总结而言,MySQL服务的初始化步骤复杂且关键,但通常不在日常关注范围内。初次阅读可能存在疏漏,期待在后续阅读中深入探索初始化与终止阶段的代码细节,持续优化理解。
MySQL全文索引源码剖析之Insert语句执行过程
本文来源于华为云社区,作者为GaussDB数据库,探讨了MySQL全文索引源码中Insert语句的执行过程。
全文索引是一种常用于信息检索的技术,它通过倒排索引实现,即单词和文档的映射关系,如(单词,(文档,偏移))。以创建一个表并在opening_line列上建立全文索引为例,插入'Call me Ishmael.'时,文档会被分为'call', 'me', 'ishmael'等单词,并记录在全文索引中。
全文索引Cache的作用类似于Change Buffer,用于缓存分词结果,避免频繁刷盘。Innodb使用fts_cache_t结构来管理cache,每个全文索引的表都会在内存中创建一个fts_cache_t对象。
Insert语句的执行分为三个阶段:写入行记录阶段、事务提交阶段和刷脏阶段。写入行记录阶段生成doc_id并写入Innodb的行记录,并将doc_id缓存。事务提交阶段对文档进行分词,获取{ 单词,(文档,偏移)}关联对,并插入到cache。刷脏阶段后台线程将cache刷新到磁盘。
全文索引的并发插入可能导致OOM问题,可通过修复patch #解决。当MySQL进程崩溃时,fts_init_index函数会恢复crash前的cache数据。
MySQL 优化器源码入门-内核实现 FULL JOIN 功能
本文以实现MySQL内核的FULL JOIN功能为目标,深入解析了MySQL源码的优化器工作流程。首先,作者通过环境和知识准备,明确将重点放在Server执行流程的探索上,从语法规则的修改开始,如在`sql_yacc.yy`中添加新支持,以及在`parse_tree_nodes.cc`中处理FULL JOIN的语法树解析和打印。接着,作者逐步解析了词法、语法分析后的Query_expression、Query_block和Query_term结构,并在关键函数中设置了断点以跟踪执行流程。
在探索了JOIN的优化工作流程后,作者选择在hypergraph_optimizer中实现FULL JOIN,该部分涉及RelationalExpression、JoinHypergraph的构建和AccessPath的生成。尽管过程复杂,但作者通过逐步调试和修改,成功在HashJoinIterator中添加了对FULL JOIN的支持,包括添加新数据成员和状态标记,以及在LEFT JOIN后执行ANTI JOIN流程。
在测试阶段,作者确认了FULL JOIN功能的正确性,通过在代码关键位置的断点观察,确认了FULL OUTER_JOIN的出现,并展示了改造后的迭代器结构。整个过程中,作者强调了在实现过程中面临的挑战和对MySQL历史的参考,最终决定以最少改动的方式完成任务,以保持代码的简洁和性能。
通过这个项目,作者不仅深入理解了MySQL源码,还实现了FULL JOIN功能,为读者提供了一个从零开始实现新功能的实例。
MySQL · 源码分析 · change master
分析MySQL源码中change master功能,需要理解其执行流程及权限要求。以mysql_execute_command()作为入口点,可以观察到change_master操作需要具备SUPER权限,确保安全执行。
change master的核心作用在于调整SQL和IO线程的配置参数,执行此操作时,系统可能会清除relay log。因此,在实际使用中,建议默认选择auto_position=1,以自动定位复制位置,避免手动指定可能导致的数据丢失风险。
在需要对change master进行调整时,务必在锁保护下进行变量修改,同时注意调整锁的顺序,以防止出现死锁情况。确保操作的稳定性和数据的一致性。
通过上述分析,我们可以明确change master的功能、执行过程中的关键点及最佳实践,从而在使用中更加高效、安全地进行数据库复制与配置调整。
深入理解MySQL数据库mysql
MySQL是一种开源的关系型数据库管理系统,被广泛应用于网站后台、企业级应用层等领域。尽管有不少人都能轻易地使用MySQL执行基本的查询、插入、更新等操作,但是如果想真正将MySQL用好,我们就需要深入了解MySQL的运行过程和工作原理。在这篇文章中,我们将会探讨一些MySQL数据库的核心概念和技术,并通过代码来说明其细节。
一、MySQL的基本部分
MySQL由几个基本组件构成:服务器,存储引擎以及客户端。服务器处理HTTP请求并与存储引擎通信,存储引擎负责存储和检索数据,客户端则负责处理用户和服务器之间的通信。每个MySQL实例都是由一个服务器和一个或多个存储引擎组成。MySQL的存储引擎是插件式的,这意味着它可以通过插件的形式对数据库进行优化,以满足不同的需要。
二、MySQL的存储引擎
MySQL默认使用的存储引擎是InnoDB,它是一个事务性存储引擎,可以锁定表或行、执行事务以及处理外键约束。InnoDB使用B+树结构进行索引文件的存储,以提高创建索引的效率。MyISAM则是另一个MySQL存储引擎,它使用B树进行索引文件的存储,并在存储表中具有更好的性能。但是,MyISAM不支持事务和外键约束,可能会出现一些数据损坏的问题。
三、MySQL的查询优化
对于任何数据库管理系统而言,查询优化都是一项至关重要的任务。MySQL查询优化的目的是提高查询处理器的性能,让查询结果能够更快地返回给客户端。MySQL的查询优化器包含许多基本组件,如文本扫描器、联接优化器、排序器等。通过分析分区表、使用正确的索引以及选择正确的存储引擎,我们可以大大提高MySQL查询的效率。
四、MySQL的性能优化
要提高MySQL的性能,需要考虑多种因素,例如服务器硬件、存储引擎、查询效率、系统资源等等。我们还可以通过修改配置文件、增加缓存大小、使用数据分区以及优化查询语句来提高MySQL的性能。在MySQL查询执行期间,我们可以通过查看进程、配置缓存和追踪查询等方式来监控感兴趣的任务,以便及时调整和提高MySQL的性能。
综上所述,MySQL数据库是一款非常强大和易于使用的工具。当我们了解MySQL的各个方面时,就可以更好地控制和优化它以满足各种不同的需求。MySQL的源代码非常稳健,易于修改,这也是它成为全球主流数据库管理系统的一个原因。无论你是新手还是专业人士,深入了解MySQL都能让你受益匪浅。
2024-11-30 13:20
2024-11-30 13:09
2024-11-30 11:52
2024-11-30 11:43
2024-11-30 11:25