李多云 發表於 2025-11-7 22:16:00

MySQL 基础架构(一):SQL语句的执行之旅

<blockquote>
<p>MySQL系列文章</p>
<p>你是否好奇过,一条看似简单的SQL查询语句,在MySQL内部究竟经历了怎样的"奇幻之旅"?从连接建立到结果返回,MySQL是如何层层处理、优化执行,最终将数据呈现在我们面前的?</p>
<p>作为一名开发者,深入理解MySQL的内部工作原理,就像是获得了数据库性能优化的"上帝视角"。无论是连接池的配置、索引的设计,还是存储引擎的选型,都将变得有据可依。今天,就让我们一起揭开MySQL的神秘面纱,探寻其内部工作机制,为构建高性能数据库应用打下坚实基础!</p>
</blockquote>
<h2 id="一mysql整体架构设计">一、MySQL整体架构设计</h2>
<p>MySQL 采用经典的分层架构设计,整体可分为 Server 层和存储引擎层两大部分。这种设计实现了<strong>核心功能与存储实现的分离</strong>,为不同类型的应用场景提供了灵活的存储方案。</p>
<h3 id="mysql的基本架构示意图">MySQL的基本架构示意图</h3>
<p><img src="https://img2024.cnblogs.com/blog/3703499/202511/3703499-20251107221028983-273783486.png"></p>
<h3 id="11-server层核心服务枢纽">1.1 Server层:核心服务枢纽</h3>
<p>Server 层包含 MySQL 的核心服务组件,主要负责以下功能:</p>
<ul>
<li><strong>连接管理</strong>:处理客户端连接、身份认证和权限验证</li>
<li><strong>SQL 接口</strong>:接收并解析 SQL 命令,返回执行结果</li>
<li><strong>查询处理</strong>:包括查询解析、优化和执行</li>
<li><strong>所有的内置函数</strong>:提供日期、时间、数学、加密等各类函数</li>
<li><strong>跨引擎功能</strong>:实现存储过程、触发器、视图等高级特性</li>
</ul>
<blockquote>
<p><strong>或者说Server层包括连接器、查询缓存、分析器、优化器、执行器</strong>等</p>
</blockquote>
<h3 id="12-存储引擎层数据存储解决方案">1.2 存储引擎层:数据存储解决方案</h3>
<p>存储引擎层负责数据的物理存储和提取,采用<strong>插件式架构</strong>,支持多种存储引擎:</p>
<ul>
<li><strong>InnoDB</strong>:MySQL 5.5.5+ 的默认引擎,支持事务和行级锁</li>
<li><strong>MyISAM</strong>:适用于读密集型场景</li>
<li><strong>Memory</strong>:数据存储在内存中,读写速度极快</li>
<li><strong>其他引擎</strong>:如 Archive、CSV 等特定用途引擎</li>
</ul>
<blockquote>
<p><strong>存储引擎是基于表的,而不是数据库。</strong></p>
</blockquote>
<p><strong>架构特点</strong>:所有存储引擎共享同一个 Server 层,这意味着开发者可以根据业务需求选择合适的存储引擎,而无需修改上层应用代码。例如,可以通过以下方式指定存储引擎:</p>
<pre><code class="language-sql">CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50)
) ENGINE=InnoDB;

-- 或者使用Memory引擎
CREATE TABLE temp_data (
    id INT PRIMARY KEY,
    content VARCHAR(100)
) ENGINE=MEMORY;
</code></pre>
<h2 id="二连接器连接管理与权限控制">二、连接器:连接管理与权限控制</h2>
<h3 id="21-连接建立过程">2.1 连接建立过程</h3>
<p>连接器负责管理客户端与 MySQL 服务器的连接建立和维护:</p>
<pre><code class="language-sql">-- 查看连接超时设置(默认8小时)
SHOW VARIABLES LIKE 'wait_timeout';
</code></pre>
<p>连接建立流程:</p>
<ol>
<li>TCP 三次握手建立网络连接</li>
<li>身份认证(用户名密码验证)</li>
<li>权限信息获取和缓存</li>
<li>连接状态维护</li>
</ol>
<h3 id="22-连接权限特性">2.2 连接权限特性</h3>
<p><strong>权限缓存机制</strong>:连接建立时获取的权限信息会缓存在连接会话中。即使管理员修改了用户权限,已存在的连接仍然使用旧的权限设置,只有新建立的连接才会应用新的权限。</p>
<h3 id="23-连接策略优化">2.3 连接策略优化</h3>
<p><strong>长连接 vs 短连接</strong>:</p>
<ul>
<li><strong>长连接</strong>:连接建立后保持不关闭,适合频繁请求场景</li>
<li><strong>短连接</strong>:每次查询后断开连接,适合低频访问场景</li>
</ul>
<p><strong>推荐策略</strong>:由于建立连接的开销较大(网络握手、权限验证等),建议<strong>优先使用长连接</strong>。</p>
<h3 id="24-长连接内存管理">2.4 长连接内存管理</h3>
<p><strong>问题分析</strong>:长连接可能导致内存占用持续增长,因为每个连接会话会缓存权限信息、临时变量等资源,这些资源只有在连接断开时才会释放。</p>
<p><strong>解决方案</strong>:</p>
<ol>
<li><strong>定期断开重连</strong>:在程序中设置连接最大存活时间</li>
<li><strong>连接重置</strong>(MySQL 5.7+):使用 <code>mysql_reset_connection</code> 重置会话状态</li>
<li><strong>连接池配置</strong>:合理设置最大连接数和空闲超时时间</li>
</ol>
<pre><code class="language-java">// JDBC连接池配置示例
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20);
config.setIdleTimeout(600000); // 10分钟空闲超时
config.setMaxLifetime(1800000); // 30分钟最大存活时间
config.setConnectionTestQuery("SELECT 1");
config.setDataSourceClassName("com.mysql.cj.jdbc.MysqlDataSource");
config.addDataSourceProperty("url", "jdbc:mysql://localhost:3306/test");
config.addDataSourceProperty("user", "username");
config.addDataSourceProperty("password", "password");
</code></pre>
<h2 id="三查询缓存历史功能的演进与淘汰">三、查询缓存:历史功能的演进与淘汰</h2>
<h3 id="31-工作原理">3.1 工作原理</h3>
<p>查询缓存曾经是 MySQL 的性能优化特性:</p>
<ul>
<li>以 Key-Value 形式缓存查询结果</li>
<li>Key 为查询语句,Value 为查询结果</li>
<li>返回结果前进行权限验证</li>
</ul>
<h3 id="32-淘汰原因">3.2 淘汰原因</h3>
<p><strong>缓存失效问题</strong>:任何对表的更新操作都会导致该表的所有查询缓存失效。在更新频繁的生产环境中,缓存命中率极低,反而增加了维护开销。(通常使用查询缓存弊大于利)</p>
<p><strong>版本演进</strong>:MySQL 8.0 正式移除了查询缓存功能,建议开发者通过其他方式优化查询性能。</p>
<h2 id="四分析器sql解析与语法验证">四、分析器:SQL解析与语法验证</h2>
<h3 id="41-词法分析">4.1 词法分析</h3>
<p>将 SQL 字符串分解为有意义的标记(tokens):</p>
<p>示例语句:<code>SELECT id, name FROM users WHERE age &gt; 18</code></p>
<p>分解结果:SELECT、id、,、name、FROM、users、WHERE、age、&gt;、18</p>
<h3 id="42-语法分析">4.2 语法分析</h3>
<p>根据 MySQL 语法规则验证语句结构,生成抽象语法树(AST)。如果发现语法错误,会返回详细的错误信息:</p>
<pre><code class="language-sql">-- 错误示例
SELECT id, name FROM users WHRE age &gt; 18;

-- 错误信息
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'WHRE age &gt; 18' at line 1
</code></pre>
<p><strong>排查技巧</strong>:关注错误信息中 "use near" 后面的内容,这通常是语法错误的位置。</p>
<h2 id="五优化器执行计划生成与优化">五、优化器:执行计划生成与优化</h2>
<h3 id="51-优化决策">5.1 优化决策</h3>
<p>优化器负责生成最优的执行计划,主要决策包括:</p>
<p><strong>索引选择</strong>:根据统计信息选择最合适的索引</p>
<p><strong>连接顺序</strong>:决定多表连接的顺序和方式</p>
<p><strong>查询重写</strong>:对查询进行等价变换以提高性能</p>
<h3 id="52-执行计划分析">5.2 执行计划分析</h3>
<p>使用 EXPLAIN 命令查看优化器生成的执行计划:</p>
<pre><code class="language-sql">EXPLAIN
SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE o.amount &gt; 1000;
</code></pre>
<p><strong>关键指标</strong>:</p>
<ul>
<li><strong>type</strong>:连接类型(性能从优到差:const &gt; eq_ref &gt; ref &gt; range &gt; index &gt; ALL)</li>
<li><strong>rows</strong>:预估扫描行数</li>
<li><strong>key</strong>:实际使用的索引</li>
<li><strong>Extra</strong>:额外信息(如 Using where、Using index 等)</li>
</ul>
<h2 id="六执行器查询执行与结果返回">六、执行器:查询执行与结果返回</h2>
<h3 id="61-执行流程">6.1 执行流程</h3>
<p>执行器负责调用存储引擎接口执行查询:</p>
<ol>
<li><strong>权限验证</strong>:验证用户对目标表的操作权限</li>
<li><strong>引擎调用</strong>:根据表定义的存储引擎调用相应接口</li>
<li><strong>结果返回</strong>:处理结果集并返回给客户端</li>
</ol>
<h3 id="62-执行示例">6.2 执行示例</h3>
<p>以简单查询为例说明执行过程:</p>
<pre><code class="language-sql">SELECT * FROM users WHERE id = 100;
</code></pre>
<p>执行步骤:</p>
<ol>
<li>调用存储引擎接口获取第一行数据</li>
<li>判断 id 是否等于 100,符合条件则加入结果集</li>
<li>继续获取下一行,重复判断过程</li>
<li>遍历完成后返回结果集</li>
</ol>
<h3 id="63-性能监控">6.3 性能监控</h3>
<p><strong>慢查询分析</strong>:通过慢查询日志监控执行性能</p>
<pre><code class="language-sql">-- 查看慢查询配置
SHOW VARIABLES LIKE '%slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';

-- 查看MySQL运行状态
SHOW STATUS LIKE "%uptime%";
SHOW STATUS LIKE "Threads_connected";
SHOW STATUS LIKE "Threads_running";
</code></pre>
<p><strong>重要指标</strong>:<code>rows_examined</code> 表示实际扫描的行数,是查询优化的重要参考。</p>
<h2 id="七存储引擎层详解与选型指南">七、存储引擎层详解与选型指南</h2>
<h3 id="71-innodb事务安全首选">7.1 InnoDB:事务安全首选</h3>
<p><strong>适用场景</strong>:</p>
<ul>
<li>需要事务支持的业务系统</li>
<li>高并发读写场景</li>
<li>要求数据一致性和持久性的应用</li>
</ul>
<p><strong>核心特性</strong>:</p>
<ul>
<li>支持 ACID 事务</li>
<li>行级锁设计,支持高并发</li>
<li>外键约束支持</li>
<li>MVCC 多版本并发控制</li>
<li>崩溃恢复能力</li>
</ul>
<p><strong>存储结构</strong>:</p>
<ul>
<li>数据与索引聚簇存储</li>
<li>使用 Buffer Pool 缓存数据页</li>
<li>支持在线热备份</li>
</ul>
<h3 id="72-myisam读密集型应用">7.2 MyISAM:读密集型应用</h3>
<p><strong>适用场景</strong>:</p>
<ul>
<li>读多写少的业务</li>
<li>数据仓库和报表系统</li>
<li>不需要事务支持的日志记录</li>
</ul>
<p><strong>特点</strong>:</p>
<ul>
<li>表级锁设计,并发性能有限</li>
<li>数据和索引分离存储(.MYD 和 .MYI 文件)</li>
<li>不支持事务和外键</li>
<li>全文索引支持</li>
</ul>
<h3 id="73-memory内存临时存储">7.3 Memory:内存临时存储</h3>
<p><strong>适用场景</strong>:</p>
<ul>
<li>临时数据存储</li>
<li>高速缓存层</li>
<li>中间结果处理</li>
</ul>
<p><strong>特点</strong>:</p>
<ul>
<li>数据存储在内存中,读写极快</li>
<li>服务重启后数据丢失</li>
<li>不支持 TEXT 和 BLOB 类型</li>
<li>表级锁设计</li>
</ul>
<h3 id="74-存储引擎对比与选型">7.4 存储引擎对比与选型</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th>InnoDB</th>
<th>MyISAM</th>
<th>Memory</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>事务支持</strong></td>
<td>✅</td>
<td>❌</td>
<td>❌</td>
</tr>
<tr>
<td><strong>锁粒度</strong></td>
<td>行级锁</td>
<td>表级锁</td>
<td>表级锁</td>
</tr>
<tr>
<td><strong>外键支持</strong></td>
<td>✅</td>
<td>❌</td>
<td>❌</td>
</tr>
<tr>
<td><strong>崩溃恢复</strong></td>
<td>支持</td>
<td>不支持</td>
<td>不支持</td>
</tr>
<tr>
<td><strong>并发性能</strong></td>
<td>高</td>
<td>低</td>
<td>中</td>
</tr>
<tr>
<td><strong>存储限制</strong></td>
<td>64TB</td>
<td>256TB</td>
<td>RAM大小</td>
</tr>
<tr>
<td><strong>适用场景</strong></td>
<td>事务型应用</td>
<td>读密集型</td>
<td>临时数据</td>
</tr>
</tbody>
</table>
<p><strong>选型建议</strong>:</p>
<ol>
<li><strong>默认选择 InnoDB</strong>:适用于大多数业务场景</li>
<li><strong>读密集型考虑 MyISAM</strong>:但要注意锁机制限制</li>
<li><strong>临时数据使用 Memory</strong>:注意数据持久性问题</li>
<li><strong>混合使用</strong>:在同一数据库中根据表的特点选择不同引擎</li>
</ol>
<blockquote>
<p>绝大多数时候我们使用的都是MySQL默认的InnoDB存储引擎,在某些读密集的极特殊情况下,使用MyISAM也是合适的。不过,前提是你的项目不介意MyISAM不支持事务、崩溃恢复等缺点。</p>
</blockquote>
<blockquote>
<p>《MySQL 高性能》中有一句话这样写到:</p>
<p>不要轻易相信“MyISAM 比 InnoDB 快”之类的经验之谈,这个结论往往不是绝对的。在很多我们已知场景中,InnoDB 的速度都可以让 MyISAM 望尘莫及,尤其是用到了聚簇索引,或者需要访问的数据都可以放入内存的应用。</p>
</blockquote>
<p>因此,对于咱们日常开发的业务系统来说,你几乎找不到什么理由使用 MyISAM 了,老老实实用默认的 InnoDB 就可以了!</p>
<h2 id="八实践总结与优化建议">八、实践总结与优化建议</h2>
<h3 id="81-连接管理最佳实践">8.1 连接管理最佳实践</h3>
<ol>
<li><strong>使用连接池</strong>:减少连接建立开销,控制连接数量</li>
<li><strong>合理配置超时</strong>:根据业务特点设置连接超时时间</li>
<li><strong>监控连接状态</strong>:定期检查连接使用情况,避免泄漏</li>
<li><strong>连接重用</strong>:使用连接重置代替重新建立连接</li>
</ol>
<h3 id="82-查询性能优化">8.2 查询性能优化</h3>
<ol>
<li><strong>索引优化</strong>:为常用查询条件创建合适索引</li>
<li><strong>避免全表扫描</strong>:通过 EXPLAIN 分析执行计划</li>
<li><strong>分批处理</strong>:大数据量操作分批次进行</li>
<li><strong>查询重写</strong>:优化复杂查询,避免不必要的连接和子查询</li>
</ol>
<h3 id="83-存储引擎选择策略">8.3 存储引擎选择策略</h3>
<ol>
<li><strong>事务需求</strong>:需要事务支持时选择 InnoDB</li>
<li><strong>并发考量</strong>:高并发写入场景选择 InnoDB</li>
<li><strong>读性能</strong>:纯读场景可考虑 MyISAM</li>
<li><strong>数据量</strong>:大数据量场景选择 InnoDB</li>
<li><strong>临时数据</strong>:临时处理选择 Memory 引擎</li>
</ol>
<h3 id="84-监控与维护">8.4 监控与维护</h3>
<pre><code class="language-sql">-- 常用监控命令
SHOW PROCESSLIST; -- 查看当前连接
SHOW ENGINE INNODB STATUS; -- InnoDB状态
SHOW GLOBAL STATUS LIKE 'Handler_read%'; -- 索引使用情况
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%'; -- 缓冲池状态
</code></pre>
<h2 id="九结语">九、结语</h2>
<p>MySQL的内部工作机制就像一个精密的流水线,每个组件各司其职又相互协作。从连接管理到SQL解析,从查询优化到最终执行,每一个环节都蕴含着丰富的设计智慧。</p>
<p>深入理解 MySQL 的架构设计和工作原理,对于开发高性能数据库应用至关重要。通过合理配置连接参数、优化查询语句和选择合适的存储引擎,可以显著提升系统性能和稳定性。</p>
<p>MySQL 的插件式存储引擎架构为不同场景提供了灵活的解决方案,开发者应该根据具体的业务需求和数据特性选择合适的存储引擎。同时,定期的性能监控和优化是保持数据库健康运行的关键。</p>
<hr>
<p><strong>参考资料</strong>:</p>
<ul>
<li>《MySQL 官方文档》</li>
<li>《MySQL 实战45讲》-01 | 基础架构:一条SQL查询语句是如何执行的?</li>
</ul>
<blockquote>
<p>文章的最后,想和你多聊两句。</p>
<p>技术之路,常常是热闹与孤独并存。那些深夜的调试、灵光一闪的方案、还有踩坑爬起后的顿悟,如果能有人一起聊聊,该多好。</p>
<p>为此,我建了一个小花园——我的微信公众号「<strong>[努力的小郑]</strong>」。</p>
<p>这里没有高深莫测的理论堆砌,只有我对后端开发、系统设计和工程实践的持续思考与沉淀。它更像我的<strong>数字笔记本</strong>,记录着那些值得被记住的解决方案和思维火花。</p>
<p>如果你觉得今天的文章还有一点启发,或者单纯想找一个同行者偶尔聊聊技术、谈谈思考,那么,欢迎你来坐坐。<br>
<img src="https://img2024.cnblogs.com/blog/3703499/202601/3703499-20260105210259813-964799315.jpg"></p>
<p>愿你前行路上,总有代码可写,有梦可追,也有灯火可亲。</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/xzqcsj/p/19091959
頁: [1]
查看完整版本: MySQL 基础架构(一):SQL语句的执行之旅