<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Database | 杨劲松 - Java后端 / AI应用开发工程师</title><link>https://1byteone.github.io/tags/database/</link><atom:link href="https://1byteone.github.io/tags/database/index.xml" rel="self" type="application/rss+xml"/><description>Database</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>zh-Hans</language><lastBuildDate>Fri, 21 Aug 2026 00:00:00 +0000</lastBuildDate><image><url>https://1byteone.github.io/media/icon_hu_1c0e9cb08cfb822a.png</url><title>Database</title><link>https://1byteone.github.io/tags/database/</link></image><item><title>MySQL 内部架构：SQL 层到 InnoDB</title><link>https://1byteone.github.io/blog/mysql-architecture/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>https://1byteone.github.io/blog/mysql-architecture/</guid><description>&lt;p&gt;&lt;em&gt;上图：MySQL Architecture 白板图；重点不是罗列名词，而是把一次真实请求如何穿过系统、在哪些边界失败画清楚。&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="为什么要从场景理解这张图"&gt;为什么要从场景理解这张图&lt;/h2&gt;
&lt;p&gt;这张图围绕“A read API uses a pool and EXPLAIN to ensure its query reaches an index instead of scanning the table.”展开。学习 MySQL Architecture 时，不能只记住组件名称：要能说明输入从哪里来、状态由谁持有、哪个组件承担失败、以及如何用指标证明系统仍然健康。白板中的箭头对应代码边界，红色感叹号对应需要显式处理的风险。&lt;/p&gt;
&lt;h2 id="逐层拆解"&gt;逐层拆解&lt;/h2&gt;
&lt;p&gt;主流程是：&lt;strong&gt;Connection → Parser → Optimizer → Executor → Storage Engine&lt;/strong&gt;。前半段是请求或数据的进入路径，后半段是运行时、存储或执行结果。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;边界契约&lt;/strong&gt;：先确定输入、输出和错误结构；不要让隐式类型、未校验参数或共享可变状态穿透多层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心机制&lt;/strong&gt;：Connection Layer → sessions + auth；SQL Layer → parse / optimize / execute。这些机制决定延迟、吞吐和可测试性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源与状态&lt;/strong&gt;：Cost model chooses access path；InnoDB → Buffer Pool + B+Tree。生产系统必须说明资源何时创建、何时释放，以及状态是否可恢复。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败路径&lt;/strong&gt;：Redo Log → crash recovery durability；必要时再结合 &lt;strong&gt;Undo Log → rollback + consistent reads&lt;/strong&gt; 做降级、重试或回滚。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="一个可落地的最小实现"&gt;一个可落地的最小实现&lt;/h2&gt;
&lt;p&gt;下面的片段只展示边界，不代表完整业务。它的价值在于把“可以替换、可以测试、可以观测”的位置固定下来。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;EXPLAIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;active&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在真实项目中，应把外部依赖封装在 adapter 或 repository 中；业务层只依赖稳定接口。这样本地测试可以使用 fake，压测可以替换慢依赖，线上故障也更容易定位。&lt;/p&gt;
&lt;h2 id="场景中的工程决策"&gt;场景中的工程决策&lt;/h2&gt;
&lt;p&gt;以白板右侧的生产场景为例：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先保护依赖&lt;/strong&gt;：连接池、线程池、并发信号量或缓存都要有上限，不能用无限队列掩盖下游过载。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再保证正确性&lt;/strong&gt;：幂等键、事务边界、版本号、锁或 schema 校验至少要有一种明确机制，避免重试带来重复写入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后优化性能&lt;/strong&gt;：先用 trace、慢查询、GC pause、队列长度、p99 延迟等数据定位，再选择索引、缓存、批处理或并发策略。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让故障可恢复&lt;/strong&gt;：超时、重试、限流、熔断、回滚和告警必须能在演练中被验证，而不是只写在文档里。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="常见误区"&gt;常见误区&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;只画成功路径，没有画超时、空数据、拒绝、回滚或副本延迟。&lt;/li&gt;
&lt;li&gt;把框架默认行为当成业务契约，升级依赖后才发现边界改变。&lt;/li&gt;
&lt;li&gt;用“加机器”替代测量，忽略连接池、锁竞争、慢 SQL、对象分配或事件循环阻塞。&lt;/li&gt;
&lt;li&gt;将日志当作唯一观测手段，缺少指标、trace、采样和敏感数据脱敏。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="生产检查清单"&gt;生产检查清单&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 输入、输出和错误响应有明确 schema&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 外部调用设置 timeout、retry 上限、rate limit 和 fallback&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 资源池有容量、排队和拒绝指标&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 关键状态有幂等、事务或恢复策略&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 日志、metrics、trace 可关联同一个 request id&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 用接近生产的数据做回归、压测和故障演练&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;真正掌握这张白板图，不是能背出每个框的定义，而是能从一次具体请求出发，解释每个箭头的输入输出、每个风险的处置方式，以及上线后用什么信号判断系统需要改进。&lt;/p&gt;</description></item></channel></rss>