<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>数据库 on 吾爱主机</title><link>https://blog.waihost.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/</link><description>Recent content in 数据库 on 吾爱主机</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sat, 01 Aug 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://blog.waihost.com/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/index.xml" rel="self" type="application/rss+xml"/><item><title>PostgreSQL Autovacuum：触发机制、表膨胀与参数调优</title><link>https://blog.waihost.com/posts/postgresql-autovacuum-bloat-tuning/</link><pubDate>Sat, 01 Aug 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/postgresql-autovacuum-bloat-tuning/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/postgresql-autovacuum-bloat-tuning.svg" alt="Featured image of post PostgreSQL Autovacuum：触发机制、表膨胀与参数调优" /&gt;&lt;p&gt;PostgreSQL 使用 MVCC 让读写尽量互不阻塞，但它也带来一个容易被忽略的代价：&lt;code&gt;UPDATE&lt;/code&gt; 和 &lt;code&gt;DELETE&lt;/code&gt; 不会立刻从物理文件中移除旧版本。旧元组只有在不再可能被任何事务看到后，才能由 &lt;code&gt;VACUUM&lt;/code&gt; 清理并把空间标记为可复用。&lt;/p&gt;
&lt;p&gt;Autovacuum 不是“可有可无的后台整理器”，而是 PostgreSQL 稳定运行的基础设施。它同时承担回收死元组、更新优化器统计信息、维护可见性映射以及防止事务 ID 回卷等工作。本文从触发公式、监控 SQL和调优方法三个角度，解释如何避免表膨胀与查询性能逐步恶化。&lt;/p&gt;
&lt;h2 id="一为什么会产生死元组"&gt;&lt;a href="#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bc%9a%e4%ba%a7%e7%94%9f%e6%ad%bb%e5%85%83%e7%bb%84" class="header-anchor"&gt;&lt;/a&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;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&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;paid&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1001&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;PostgreSQL 通常不会在原位置覆盖旧行，而是创建新版本，并让旧版本在满足可见性条件前继续存在。这样，较早开始的事务仍可读取它应该看到的快照。&lt;/p&gt;
&lt;p&gt;当旧版本不再对任何事务可见时，它就成为 dead tuple。若清理速度长期低于写入速度，会出现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表和索引占用空间持续增加；&lt;/li&gt;
&lt;li&gt;顺序扫描需要读取更多数据页；&lt;/li&gt;
&lt;li&gt;缓存命中效率下降，磁盘 I/O 增加；&lt;/li&gt;
&lt;li&gt;优化器统计信息过旧，可能选择错误执行计划；&lt;/li&gt;
&lt;li&gt;维护操作耗时越来越长。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;需要注意：普通 &lt;code&gt;VACUUM&lt;/code&gt; 主要把空间交还给表内部复用，通常不会立即缩小操作系统看到的文件。&lt;code&gt;VACUUM FULL&lt;/code&gt; 会重写整张表并归还空间，但需要额外磁盘空间和排他锁，因此不适合作为日常维护手段。&lt;/p&gt;
&lt;h2 id="二autovacuum-的触发公式"&gt;&lt;a href="#%e4%ba%8cautovacuum-%e7%9a%84%e8%a7%a6%e5%8f%91%e5%85%ac%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;二、Autovacuum 的触发公式
&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-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vacuum 触发数 = autovacuum_vacuum_threshold
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; + autovacuum_vacuum_scale_factor × 表估算行数
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PostgreSQL 18 的默认值为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autovacuum_vacuum_threshold = 50
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autovacuum_vacuum_scale_factor = 0.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一张估算为 1000 万行的表，默认需要约 200 万个更新或删除元组才触发一次 vacuum：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;50 + 0.2 × 10,000,000 = 2,000,050
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这对小表通常没问题，但对高频更新的大表可能过于宽松。分析统计信息的触发方式类似：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;analyze 触发数 = autovacuum_analyze_threshold
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; + autovacuum_analyze_scale_factor × 表估算行数
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;默认 &lt;code&gt;autovacuum_analyze_threshold&lt;/code&gt; 为 50，&lt;code&gt;autovacuum_analyze_scale_factor&lt;/code&gt; 为 0.1。&lt;/p&gt;
&lt;h2 id="三先监控再调参数"&gt;&lt;a href="#%e4%b8%89%e5%85%88%e7%9b%91%e6%8e%a7%e5%86%8d%e8%b0%83%e5%8f%82%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;三、先监控，再调参数
&lt;/h2&gt;&lt;h3 id="1-找出死元组较多的表"&gt;&lt;a href="#1-%e6%89%be%e5%87%ba%e6%ad%bb%e5%85%83%e7%bb%84%e8%be%83%e5%a4%9a%e7%9a%84%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;1. 找出死元组较多的表
&lt;/h3&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;schemaname&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;relname&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n_live_tup&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n_dead_tup&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&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="n"&gt;n_dead_tup&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="k"&gt;NULLIF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_live_tup&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="n"&gt;n_dead_tup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dead_pct&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last_autovacuum&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last_autoanalyze&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_count&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autoanalyze_count&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_user_tables&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n_dead_tup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;不要只盯着 &lt;code&gt;dead_pct&lt;/code&gt;：百万行大表的 5% 可能已经很多，而几十行小表的 50% 通常影响有限。应同时观察绝对数量、增长速度、表尺寸和业务延迟。&lt;/p&gt;
&lt;h3 id="2-查看表与索引大小"&gt;&lt;a href="#2-%e6%9f%a5%e7%9c%8b%e8%a1%a8%e4%b8%8e%e7%b4%a2%e5%bc%95%e5%a4%a7%e5%b0%8f" class="header-anchor"&gt;&lt;/a&gt;2. 查看表与索引大小
&lt;/h3&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nspname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;schema_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_size_pretty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_table_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;table_size&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_size_pretty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_indexes_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indexes_size&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_size_pretty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_total_relation_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total_size&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&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;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&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="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relnamespace&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="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relkind&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;r&amp;#39;&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="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;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nspname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pg_catalog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;information_schema&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_total_relation_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;&lt;code&gt;pg_stat_user_tables&lt;/code&gt; 中的元组数是统计估算，不是严格实时计数。累计统计可能有短暂延迟，而且默认在同一事务中读取时会缓存到事务结束，因此排障时应避免在长事务里反复查询后误判数据没有变化。&lt;/p&gt;
&lt;h3 id="3-检查-autovacuum-是否正在工作"&gt;&lt;a href="#3-%e6%a3%80%e6%9f%a5-autovacuum-%e6%98%af%e5%90%a6%e6%ad%a3%e5%9c%a8%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;3. 检查 Autovacuum 是否正在工作
&lt;/h3&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;datname&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;relid&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;regclass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phase&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;heap_blks_total&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;heap_blks_scanned&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;heap_blks_vacuumed&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_vacuum_count&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_progress_vacuum&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;同时检查全局配置：&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;track_counts&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_max_workers&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_naptime&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_vacuum_cost_delay&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_vacuum_cost_limit&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;h2 id="四针对热点大表做局部调优"&gt;&lt;a href="#%e5%9b%9b%e9%92%88%e5%af%b9%e7%83%ad%e7%82%b9%e5%a4%a7%e8%a1%a8%e5%81%9a%e5%b1%80%e9%83%a8%e8%b0%83%e4%bc%98" class="header-anchor"&gt;&lt;/a&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;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_vacuum_scale_factor&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;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;02&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_vacuum_threshold&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;1000&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_analyze_scale_factor&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;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;02&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;autovacuum_analyze_threshold&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;1000&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="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;若 &lt;code&gt;orders&lt;/code&gt; 有 1000 万行，新的 vacuum 触发值约为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1000 + 0.02 × 10,000,000 = 201,000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这比默认约 200 万行更及时，同时不会让所有表都采用同样激进的策略。调整后至少持续观察一个完整业务周期：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n_dead_tup&lt;/code&gt; 是否形成可控波动而非持续上升；&lt;/li&gt;
&lt;li&gt;autovacuum 的执行次数与单次持续时间；&lt;/li&gt;
&lt;li&gt;数据盘 IOPS、吞吐和延迟；&lt;/li&gt;
&lt;li&gt;SQL 的 P95/P99 延迟；&lt;/li&gt;
&lt;li&gt;表和索引尺寸是否趋于稳定。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="五为什么调低阈值仍可能无效"&gt;&lt;a href="#%e4%ba%94%e4%b8%ba%e4%bb%80%e4%b9%88%e8%b0%83%e4%bd%8e%e9%98%88%e5%80%bc%e4%bb%8d%e5%8f%af%e8%83%bd%e6%97%a0%e6%95%88" class="header-anchor"&gt;&lt;/a&gt;五、为什么“调低阈值”仍可能无效
&lt;/h2&gt;&lt;h3 id="1-长事务阻止清理"&gt;&lt;a href="#1-%e9%95%bf%e4%ba%8b%e5%8a%a1%e9%98%bb%e6%ad%a2%e6%b8%85%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;1. 长事务阻止清理
&lt;/h3&gt;&lt;p&gt;只要某个老快照仍可能看见旧版本，VACUUM 就不能安全移除它。可先排查长时间未结束的事务：&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;usename&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;state&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xact_start&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&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="n"&gt;xact_start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xact_age&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_event_type&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_event&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;query&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_activity&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;xact_start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xact_start&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;应用连接池中的 &lt;code&gt;idle in transaction&lt;/code&gt;、未提交的批处理、长期保持的报表事务，都是常见根因。此时继续降低 scale factor，只会让 vacuum 更频繁地尝试，却未必能回收空间。&lt;/p&gt;
&lt;h3 id="2-清理能力跟不上写入速度"&gt;&lt;a href="#2-%e6%b8%85%e7%90%86%e8%83%bd%e5%8a%9b%e8%b7%9f%e4%b8%8d%e4%b8%8a%e5%86%99%e5%85%a5%e9%80%9f%e5%ba%a6" class="header-anchor"&gt;&lt;/a&gt;2. 清理能力跟不上写入速度
&lt;/h3&gt;&lt;p&gt;Autovacuum 使用基于成本的延迟机制来降低后台维护对前台业务的 I/O 冲击。如果多张大表同时高频更新，worker 数量、成本限额或磁盘能力可能成为瓶颈。&lt;/p&gt;
&lt;p&gt;调优顺序建议是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先解决长事务和异常写入；&lt;/li&gt;
&lt;li&gt;针对热点表降低触发阈值；&lt;/li&gt;
&lt;li&gt;确认磁盘有余量后，再评估 worker 数量和成本参数；&lt;/li&gt;
&lt;li&gt;每次只改一组参数，并保留前后监控数据。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不要只为“让 vacuum 尽快结束”就无限提高成本限额，否则维护 I/O 可能直接影响在线查询。&lt;/p&gt;
&lt;h3 id="3-误把内部可复用空间当成故障"&gt;&lt;a href="#3-%e8%af%af%e6%8a%8a%e5%86%85%e9%83%a8%e5%8f%af%e5%a4%8d%e7%94%a8%e7%a9%ba%e9%97%b4%e5%bd%93%e6%88%90%e6%95%85%e9%9a%9c" class="header-anchor"&gt;&lt;/a&gt;3. 误把内部可复用空间当成故障
&lt;/h3&gt;&lt;p&gt;普通 VACUUM 后文件不缩小，并不表示它没有工作。若表仍会持续写入，保留并复用这些空闲空间往往比频繁执行 &lt;code&gt;VACUUM FULL&lt;/code&gt; 更合理。&lt;/p&gt;
&lt;p&gt;只有在一次性大规模删除、确认未来不会很快重新增长，并且能够安排锁表维护窗口时，才考虑 &lt;code&gt;VACUUM FULL&lt;/code&gt;、&lt;code&gt;CLUSTER&lt;/code&gt; 或其他表重写方案。执行前必须预留接近表及索引重建所需的额外空间。&lt;/p&gt;
&lt;h2 id="六生产调优清单"&gt;&lt;a href="#%e5%85%ad%e7%94%9f%e4%ba%a7%e8%b0%83%e4%bc%98%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;六、生产调优清单
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;保持 autovacuum 开启，不要把关闭它当成性能优化。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;pg_stat_user_tables&lt;/code&gt; 建立死元组数量、比例和清理时间的趋势图。&lt;/li&gt;
&lt;li&gt;优先为热点大表设置表级参数，避免粗暴修改全局阈值。&lt;/li&gt;
&lt;li&gt;同时监控磁盘 I/O 和业务延迟，防止维护任务挤压前台负载。&lt;/li&gt;
&lt;li&gt;排查长事务、复制槽和其他可能维持旧快照的因素。&lt;/li&gt;
&lt;li&gt;将普通 VACUUM 作为日常机制，把表重写当作有维护窗口的例外操作。&lt;/li&gt;
&lt;li&gt;定期检查事务 ID 年龄，不能只关注磁盘膨胀。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;Autovacuum 的本质不是“定时清垃圾”，而是根据表的变更规模动态触发的一组维护任务。真正有效的优化，不是简单把参数调得更激进，而是让触发频率、清理吞吐和业务写入速度达到平衡。&lt;/p&gt;
&lt;p&gt;面对表膨胀时，应先回答三个问题：死元组为什么持续产生、为什么未被及时清理、普通 VACUUM 回收的空间是否已经被业务复用。把这些问题与长事务、I/O 能力和表级阈值结合起来分析，通常比直接执行 &lt;code&gt;VACUUM FULL&lt;/code&gt; 更安全，也更接近根因。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/routine-vacuuming.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 官方文档：Routine Vacuuming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/runtime-config-vacuum.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 官方文档：Vacuuming 配置参数&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/monitoring-stats.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 官方文档：累计统计系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/sql-vacuum.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 官方文档：VACUUM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>PostgreSQL WAL、检查点与崩溃恢复：原理、参数与工程实践</title><link>https://blog.waihost.com/posts/postgresql-wal-checkpoint-crash-recovery/</link><pubDate>Fri, 31 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/postgresql-wal-checkpoint-crash-recovery/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/postgresql-wal-checkpoint-crash-recovery.svg" alt="Featured image of post PostgreSQL WAL、检查点与崩溃恢复：原理、参数与工程实践" /&gt;&lt;p&gt;生产环境里，数据库“提交成功”并不等于数据页已经刷到表文件。PostgreSQL 用 &lt;strong&gt;Write-Ahead Logging（WAL，预写日志）&lt;/strong&gt; 把变更先顺序写到日志，再异步回写堆/索引页；一旦进程或主机崩溃，就从最近检查点（checkpoint）开始 &lt;strong&gt;REDO 前滚&lt;/strong&gt;，把还没落盘的变更重放回来。理解 WAL 与检查点，才能在“提交延迟、恢复时间、磁盘占用”之间做正确取舍，而不是盲目把 &lt;code&gt;fsync&lt;/code&gt; 关掉。&lt;/p&gt;
&lt;h2 id="问题背景为什么不能每次提交都刷数据页"&gt;&lt;a href="#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e8%83%bd%e6%af%8f%e6%ac%a1%e6%8f%90%e4%ba%a4%e9%83%bd%e5%88%b7%e6%95%b0%e6%8d%ae%e9%a1%b5" class="header-anchor"&gt;&lt;/a&gt;问题背景：为什么不能每次提交都刷数据页？
&lt;/h2&gt;&lt;p&gt;一次事务可能修改很多表页。如果每次 &lt;code&gt;COMMIT&lt;/code&gt; 都把相关数据页 &lt;code&gt;fsync&lt;/code&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;：并发提交会互相争抢刷脏页。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;恢复语义更复杂&lt;/strong&gt;：缺少统一的“已持久化边界”。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;WAL 的核心规则（官方表述）：&lt;strong&gt;对数据文件的修改，必须在描述该修改的 WAL 记录刷到永久存储之后才能写入数据页&lt;/strong&gt;。遵循这条规则后，提交时只需保证相关 WAL 已落盘，崩溃时再用日志重做（roll-forward / REDO）尚未写入数据页的变更。&lt;/p&gt;
&lt;p&gt;这带来两个工程收益：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;提交路径偏顺序写&lt;/strong&gt;：同步成本主要在 WAL 文件，而不是整页随机写。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持在线备份与 PITR&lt;/strong&gt;：归档 WAL + 基准备份，可回放到任意覆盖时间点。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="核心原理lsn段文件检查点与-redo"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e5%8e%9f%e7%90%86lsn%e6%ae%b5%e6%96%87%e4%bb%b6%e6%a3%80%e6%9f%a5%e7%82%b9%e4%b8%8e-redo" class="header-anchor"&gt;&lt;/a&gt;核心原理：LSN、段文件、检查点与 REDO
&lt;/h2&gt;&lt;h3 id="1-lsn日志里的字节尺"&gt;&lt;a href="#1-lsn%e6%97%a5%e5%bf%97%e9%87%8c%e7%9a%84%e5%ad%97%e8%8a%82%e5%b0%ba" class="header-anchor"&gt;&lt;/a&gt;1. LSN：日志里的“字节尺”
&lt;/h3&gt;&lt;p&gt;每条 WAL 记录写入后，插入位置用 &lt;strong&gt;Log Sequence Number（LSN）&lt;/strong&gt; 描述，本质上是 WAL 中单调递增的字节偏移。PostgreSQL 用 &lt;code&gt;pg_lsn&lt;/code&gt; 类型表示它，可用于比较两点之间产生了多少 WAL、衡量复制与恢复进度。&lt;/p&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="c1"&gt;-- 当前 WAL 写位置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 计算两个 LSN 之间的字节差（备份/复制场景常用）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_wal_lsn_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0/0&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;h3 id="2-段文件布局pg_wal-里的-16mb-段"&gt;&lt;a href="#2-%e6%ae%b5%e6%96%87%e4%bb%b6%e5%b8%83%e5%b1%80pg_wal-%e9%87%8c%e7%9a%84-16mb-%e6%ae%b5" class="header-anchor"&gt;&lt;/a&gt;2. 段文件布局：&lt;code&gt;pg_wal&lt;/code&gt; 里的 16MB 段
&lt;/h3&gt;&lt;p&gt;WAL 默认存放在数据目录下的 &lt;code&gt;pg_wal/&lt;/code&gt;（历史版本曾叫 &lt;code&gt;pg_xlog&lt;/code&gt;）。段文件通常 &lt;strong&gt;每段 16MB&lt;/strong&gt;（&lt;code&gt;initdb --wal-segsize&lt;/code&gt; 可改），段内再按页划分（常见 8kB）。文件名是递增编号，例如从 &lt;code&gt;000000010000000000000001&lt;/code&gt; 起。&lt;/p&gt;
&lt;p&gt;运维提示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WAL 磁盘与主数据盘分离，有助于把顺序写与随机写解耦（可在停库后迁移 &lt;code&gt;pg_wal&lt;/code&gt; 并用符号链接指回原路径）。&lt;/li&gt;
&lt;li&gt;段文件在检查点之后、确认不再需要时会被 &lt;strong&gt;回收重命名&lt;/strong&gt; 或删除；归档模式下必须先归档再回收。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-检查点恢复的安全锚点"&gt;&lt;a href="#3-%e6%a3%80%e6%9f%a5%e7%82%b9%e6%81%a2%e5%a4%8d%e7%9a%84%e5%ae%89%e5%85%a8%e9%94%9a%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;3. 检查点：恢复的“安全锚点”
&lt;/h3&gt;&lt;p&gt;检查点是 WAL 序列中的一个保证点：&lt;strong&gt;该点之前的堆/索引变更，都已反映到数据文件并刷盘&lt;/strong&gt;。检查点过程会：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把脏数据页写回磁盘；&lt;/li&gt;
&lt;li&gt;在 WAL 中写入特殊的 checkpoint 记录；&lt;/li&gt;
&lt;li&gt;把检查点位置写入 &lt;code&gt;pg_control&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;崩溃恢复时，服务器：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读 &lt;code&gt;pg_control&lt;/code&gt; 找到最新检查点；&lt;/li&gt;
&lt;li&gt;定位 checkpoint 记录中的 &lt;strong&gt;redo 起点&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;从该 LSN &lt;strong&gt;向前扫描 WAL 做 REDO&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此：检查点越频繁，崩溃后需要重放的 WAL 通常越少，&lt;strong&gt;恢复更快&lt;/strong&gt;；但刷脏页更勤，&lt;strong&gt;运行期 I/O 更重&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;默认自动触发条件（二者先到为准）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;参数&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
					&lt;th&gt;默认（官方文档）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;checkpoint_timeout&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;两次自动检查点的最长时间间隔&lt;/td&gt;
					&lt;td&gt;5 分钟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;max_wal_size&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;自动检查点期间 WAL 增长的软上限&lt;/td&gt;
					&lt;td&gt;1 GB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;checkpoint_completion_target&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;检查点 I/O 在间隔内的目标完成比例&lt;/td&gt;
					&lt;td&gt;0.9&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;min_wal_size&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;低于该占用时优先回收复用段，而不是删除&lt;/td&gt;
					&lt;td&gt;80 MB&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;CHECKPOINT&lt;/code&gt; SQL 可强制立即检查点，但文档明确：&lt;strong&gt;不适合作为常规业务操作&lt;/strong&gt;，一般留给维护窗口或排障。&lt;/p&gt;
&lt;h3 id="4-全页写full-page-writes与页撕裂"&gt;&lt;a href="#4-%e5%85%a8%e9%a1%b5%e5%86%99full-page-writes%e4%b8%8e%e9%a1%b5%e6%92%95%e8%a3%82" class="header-anchor"&gt;&lt;/a&gt;4. 全页写（Full Page Writes）与页撕裂
&lt;/h3&gt;&lt;p&gt;默认 &lt;code&gt;full_page_writes = on&lt;/code&gt;：检查点之后，某个数据页 &lt;strong&gt;第一次被修改&lt;/strong&gt; 时，会把 &lt;strong&gt;整页内容&lt;/strong&gt; 记入 WAL（FPI，full page image）。目的是防止崩溃时页只写了一半（torn page），仅靠“增量修改记录”无法正确还原。&lt;/p&gt;
&lt;p&gt;代价是：检查点刚结束后的一段时间内 WAL 量会冲高。高负载系统常通过合理调大 &lt;code&gt;max_wal_size&lt;/code&gt; / &lt;code&gt;checkpoint_timeout&lt;/code&gt;，避免检查点过于密集导致 FPI 风暴。&lt;/p&gt;
&lt;h2 id="提交耐久性synchronous_commit-与-fsync"&gt;&lt;a href="#%e6%8f%90%e4%ba%a4%e8%80%90%e4%b9%85%e6%80%a7synchronous_commit-%e4%b8%8e-fsync" class="header-anchor"&gt;&lt;/a&gt;提交耐久性：&lt;code&gt;synchronous_commit&lt;/code&gt; 与 &lt;code&gt;fsync&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;这是最容易踩坑的一组旋钮，必须分清 &lt;strong&gt;丢最近事务&lt;/strong&gt; 与 &lt;strong&gt;数据库损坏&lt;/strong&gt; 的差别。&lt;/p&gt;
&lt;h3 id="synchronous_commit可会话级调整"&gt;&lt;a href="#synchronous_commit%e5%8f%af%e4%bc%9a%e8%af%9d%e7%ba%a7%e8%b0%83%e6%95%b4" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;synchronous_commit&lt;/code&gt;（可会话级调整）
&lt;/h3&gt;&lt;p&gt;控制：在向客户端返回“成功”前，WAL 需要处理到什么程度。合法值包括：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;remote_apply&lt;/code&gt;、&lt;code&gt;on&lt;/code&gt;（默认）、&lt;code&gt;remote_write&lt;/code&gt;、&lt;code&gt;local&lt;/code&gt;、&lt;code&gt;off&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;关键语义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;非 &lt;code&gt;off&lt;/code&gt; 的本地行为：等待 &lt;strong&gt;本地 WAL 刷盘&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;off&lt;/code&gt;（异步提交）：逻辑提交完成后即可返回，不等待 WAL 落盘；崩溃可能丢失最近若干已“成功”的事务。&lt;/li&gt;
&lt;li&gt;官方强调：异步提交的风险是 &lt;strong&gt;数据丢失，不是数据损坏&lt;/strong&gt;。恢复仍会重放到最后已刷盘的 WAL，库状态自洽，只是像最近事务被干净回滚一样。&lt;/li&gt;
&lt;/ul&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="c1"&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;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;synchronous_commit&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="k"&gt;off&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;span class="line"&gt;&lt;span class="cl"&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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;...&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 默认仍是 on；按事务开始时的参数值决定该事务提交模式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;银行出钞、扣款等“客户端会据此做外部动作”的场景，不要关同步提交。&lt;/p&gt;
&lt;h3 id="fsync集群级危险"&gt;&lt;a href="#fsync%e9%9b%86%e7%be%a4%e7%ba%a7%e5%8d%b1%e9%99%a9" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;fsync&lt;/code&gt;（集群级，危险）
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;fsync = on&lt;/code&gt; 时，PostgreSQL 通过 &lt;code&gt;fsync()&lt;/code&gt; 或等价方法（见 &lt;code&gt;wal_sync_method&lt;/code&gt;）尽量把更新真正写到磁盘，保证 OS/硬件崩溃后仍可恢复到一致状态。&lt;/p&gt;
&lt;p&gt;关掉 &lt;code&gt;fsync&lt;/code&gt; 可能换来吞吐，但在掉电/系统崩溃时可能导致 &lt;strong&gt;不可恢复损坏&lt;/strong&gt;。文档只建议在可整体重建的场景（初始装载、用完即丢的批处理库、只读克隆等）临时关闭。&lt;/p&gt;
&lt;p&gt;工程对照：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;设置&lt;/th&gt;
					&lt;th&gt;主要风险&lt;/th&gt;
					&lt;th&gt;适用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;synchronous_commit=off&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;丢最近事务，库仍一致&lt;/td&gt;
					&lt;td&gt;可丢失的短事务&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;fsync=off&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可能损坏，需重建&lt;/td&gt;
					&lt;td&gt;几乎仅限可重建环境&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;默认两者开启&lt;/td&gt;
					&lt;td&gt;提交稍慢，耐久性强&lt;/td&gt;
					&lt;td&gt;绝大多数生产&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="可复现观测实验实验室"&gt;&lt;a href="#%e5%8f%af%e5%a4%8d%e7%8e%b0%e8%a7%82%e6%b5%8b%e5%ae%9e%e9%aa%8c%e5%ae%9e%e9%aa%8c%e5%ae%a4" class="header-anchor"&gt;&lt;/a&gt;可复现观测实验（实验室）
&lt;/h2&gt;&lt;p&gt;下面命令假设你有一个可写的测试实例。目标是把“看不见的 WAL 机制”变成可观察指标。&lt;/p&gt;
&lt;h3 id="1看当前-wal-与检查点统计"&gt;&lt;a href="#1%e7%9c%8b%e5%bd%93%e5%89%8d-wal-%e4%b8%8e%e6%a3%80%e6%9f%a5%e7%82%b9%e7%bb%9f%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;1）看当前 WAL 与检查点统计
&lt;/h3&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_level&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fsync&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;synchronous_commit&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkpoint_timeout&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;max_wal_size&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;min_wal_size&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;full_page_writes&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkpoint_completion_target&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;span class="line"&gt;&lt;span class="cl"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current_lsn&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 新版本检查点统计在 pg_stat_checkpointer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_timed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_requested&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_done&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;write_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sync_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buffers_written&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_checkpointer&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- WAL 生成量与 FPI
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_fpi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_buffers_full&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_wal&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;说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;num_timed&lt;/code&gt; / &lt;code&gt;num_requested&lt;/code&gt; 会计入完成与跳过；&lt;code&gt;num_done&lt;/code&gt; 只计真正完成的检查点。&lt;/li&gt;
&lt;li&gt;空闲实例可能因“自上次检查点以来没有 WAL”而跳过定时检查点。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2制造-wal-并观察-lsn-前进"&gt;&lt;a href="#2%e5%88%b6%e9%80%a0-wal-%e5%b9%b6%e8%a7%82%e5%af%9f-lsn-%e5%89%8d%e8%bf%9b" class="header-anchor"&gt;&lt;/a&gt;2）制造 WAL 并观察 LSN 前进
&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;psql&lt;/code&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_lab&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bigserial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;text&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="p"&gt;);&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 记录写入前 LSN（psql 变量）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;before_lsn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;gset&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="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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_lab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate_series&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&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;span class="line"&gt;&lt;span class="cl"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;after_lsn&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_wal_lsn_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_current_wal_lsn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;before_lsn&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_bytes&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;&lt;code&gt;pg_wal_lsn_diff&lt;/code&gt; 返回两个 LSN 之间的字节差，便于量化一次批量写入产生了多少 WAL。若不用 &lt;code&gt;\gset&lt;/code&gt;，可先手工抄下 &lt;code&gt;before_lsn&lt;/code&gt; 再代入比较。&lt;/p&gt;
&lt;h3 id="3对比同步异步提交延迟概念实验"&gt;&lt;a href="#3%e5%af%b9%e6%af%94%e5%90%8c%e6%ad%a5%e5%bc%82%e6%ad%a5%e6%8f%90%e4%ba%a4%e5%bb%b6%e8%bf%9f%e6%a6%82%e5%bf%b5%e5%ae%9e%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;3）对比同步/异步提交延迟（概念实验）
&lt;/h3&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="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;timing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&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="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;BEGIN&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LOCAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;synchronous_commit&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="k"&gt;on&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_lab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sync&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COMMIT&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;span class="line"&gt;&lt;span class="cl"&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;BEGIN&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LOCAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;synchronous_commit&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="k"&gt;off&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wal_lab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;async&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COMMIT&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;在高并发小事务压测下，异步提交通常降低提交等待；但要清楚这是 &lt;strong&gt;用丢失窗口换延迟&lt;/strong&gt;，不是免费午餐。&lt;/p&gt;
&lt;h3 id="4强制检查点仅实验"&gt;&lt;a href="#4%e5%bc%ba%e5%88%b6%e6%a3%80%e6%9f%a5%e7%82%b9%e4%bb%85%e5%ae%9e%e9%aa%8c" class="header-anchor"&gt;&lt;/a&gt;4）强制检查点（仅实验）
&lt;/h3&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;CHECKPOINT&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num_done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;write_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sync_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buffers_written&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_checkpointer&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;观察 &lt;code&gt;write_time&lt;/code&gt; / &lt;code&gt;sync_time&lt;/code&gt; 与 &lt;code&gt;buffers_written&lt;/code&gt; 的变化，理解检查点 I/O 的代价。&lt;/p&gt;
&lt;h2 id="工程调参与排错清单"&gt;&lt;a href="#%e5%b7%a5%e7%a8%8b%e8%b0%83%e5%8f%82%e4%b8%8e%e6%8e%92%e9%94%99%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;工程调参与排错清单
&lt;/h2&gt;&lt;h3 id="恢复时间-vs-运行期-io"&gt;&lt;a href="#%e6%81%a2%e5%a4%8d%e6%97%b6%e9%97%b4-vs-%e8%bf%90%e8%a1%8c%e6%9c%9f-io" class="header-anchor"&gt;&lt;/a&gt;恢复时间 vs 运行期 I/O
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;缩短崩溃恢复&lt;/strong&gt;：减小 &lt;code&gt;checkpoint_timeout&lt;/code&gt; / &lt;code&gt;max_wal_size&lt;/code&gt; → 检查点更勤 → REDO 更少。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;减轻检查点尖峰&lt;/strong&gt;：增大二者，并把 &lt;code&gt;checkpoint_completion_target&lt;/code&gt; 维持在接近 &lt;code&gt;0.9&lt;/code&gt;，让刷脏页摊到整个间隔。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要用检查点频率去“保证归档频率”&lt;/strong&gt;：若关心归档 RPO，应调 &lt;code&gt;archive_timeout&lt;/code&gt;，而不是把检查点拧得很紧。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="wal-目录膨胀"&gt;&lt;a href="#wal-%e7%9b%ae%e5%bd%95%e8%86%a8%e8%83%80" class="header-anchor"&gt;&lt;/a&gt;WAL 目录膨胀
&lt;/h3&gt;&lt;p&gt;常见原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;归档命令失败，段无法回收；&lt;/li&gt;
&lt;li&gt;复制槽（replication slot）落后，强制保留旧段；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wal_keep_size&lt;/code&gt; / 相关保留设置过大；&lt;/li&gt;
&lt;li&gt;批量导入、索引重建产生大量 WAL。&lt;/li&gt;
&lt;/ol&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="c1"&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;archive_mode&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;archive_command&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;archive_timeout&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_is_in_recovery&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;同时检查 &lt;code&gt;pg_wal&lt;/code&gt; 磁盘占用、复制槽延迟与归档日志报错。&lt;/p&gt;
&lt;h3 id="wal_level-选型"&gt;&lt;a href="#wal_level-%e9%80%89%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;&lt;code&gt;wal_level&lt;/code&gt; 选型
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;级别&lt;/th&gt;
					&lt;th&gt;大致用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;minimal&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;仅崩溃恢复所需信息，体积最小；&lt;strong&gt;不足以&lt;/strong&gt; PITR/流复制&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;replica&lt;/code&gt;（默认）&lt;/td&gt;
					&lt;td&gt;支持归档与物理复制、备库只读查询&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;logical&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;在 replica 基础上增加逻辑解码所需信息&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;生产若要做流复制或连续归档，不要用 &lt;code&gt;minimal&lt;/code&gt;；文档还指出：&lt;code&gt;max_wal_senders&lt;/code&gt; 非 0 时甚至不能以 &lt;code&gt;minimal&lt;/code&gt; 启动。&lt;/p&gt;
&lt;h3 id="硬件与虚假写成功"&gt;&lt;a href="#%e7%a1%ac%e4%bb%b6%e4%b8%8e%e8%99%9a%e5%81%87%e5%86%99%e6%88%90%e5%8a%9f" class="header-anchor"&gt;&lt;/a&gt;硬件与虚假“写成功”
&lt;/h3&gt;&lt;p&gt;WAL 要求日志先于数据页持久化。若磁盘/控制器 &lt;strong&gt;谎报写完成&lt;/strong&gt;（只进缓存未真正落盘），掉电仍可能造成不可恢复损坏。务必确认 WAL 所在存储关闭了危险写缓存，或有电池备份写缓存（BBU）。&lt;/p&gt;
&lt;h2 id="常见坑对照表"&gt;&lt;a href="#%e5%b8%b8%e8%a7%81%e5%9d%91%e5%af%b9%e7%85%a7%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;常见坑对照表
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;现象&lt;/th&gt;
					&lt;th&gt;可能原因&lt;/th&gt;
					&lt;th&gt;处理方向&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;提交延迟高、小事务 TPS 低&lt;/td&gt;
					&lt;td&gt;每次提交都在等 WAL fsync&lt;/td&gt;
					&lt;td&gt;评估 &lt;code&gt;synchronous_commit=off&lt;/code&gt;（可丢）或提升 WAL 盘延迟；关注 group commit&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;检查点期间延迟尖刺&lt;/td&gt;
					&lt;td&gt;脏页集中刷写&lt;/td&gt;
					&lt;td&gt;调大 &lt;code&gt;max_wal_size&lt;/code&gt;/&lt;code&gt;checkpoint_timeout&lt;/code&gt;，保持 &lt;code&gt;checkpoint_completion_target≈0.9&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;崩溃恢复很久&lt;/td&gt;
					&lt;td&gt;检查点过稀，REDO 区间过长&lt;/td&gt;
					&lt;td&gt;适度降低 &lt;code&gt;max_wal_size&lt;/code&gt; 或 &lt;code&gt;checkpoint_timeout&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;pg_wal&lt;/code&gt; 撑满磁盘&lt;/td&gt;
					&lt;td&gt;归档失败 / 复制槽落后&lt;/td&gt;
					&lt;td&gt;修归档、清理无用槽、扩容并监控&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;关 &lt;code&gt;fsync&lt;/code&gt; “更快”&lt;/td&gt;
					&lt;td&gt;用损坏风险换吞吐&lt;/td&gt;
					&lt;td&gt;生产禁止；可重建场景才临时关闭&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;异步提交后“丢单”&lt;/td&gt;
					&lt;td&gt;崩溃窗口内事务未刷盘&lt;/td&gt;
					&lt;td&gt;业务上接受丢失，或关键路径保持 &lt;code&gt;on&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;检查点后 WAL 暴涨&lt;/td&gt;
					&lt;td&gt;FPI（&lt;code&gt;full_page_writes&lt;/code&gt;）&lt;/td&gt;
					&lt;td&gt;避免检查点过密；观察 &lt;code&gt;pg_stat_wal.wal_fpi&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;WAL 先于数据页&lt;/strong&gt;：提交持久化的关键路径是刷 WAL，而不是立刻刷所有脏表页。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;检查点定义 REDO 起点&lt;/strong&gt;：&lt;code&gt;checkpoint_timeout&lt;/code&gt; 与 &lt;code&gt;max_wal_size&lt;/code&gt; 共同决定自动检查点节奏，直接影响崩溃恢复时间与运行期 I/O。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;synchronous_commit=off&lt;/code&gt; ≠ &lt;code&gt;fsync=off&lt;/code&gt;&lt;/strong&gt;：前者可能丢最近事务但保持一致；后者可能损坏。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用 LSN 与统计视图观测&lt;/strong&gt;：&lt;code&gt;pg_current_wal_lsn&lt;/code&gt;、&lt;code&gt;pg_stat_checkpointer&lt;/code&gt;、&lt;code&gt;pg_stat_wal&lt;/code&gt; 把机制落到指标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调参要绑定目标&lt;/strong&gt;：RTO（恢复时间）、提交延迟、磁盘占用、复制/归档 RPO，不要只抄一组“神秘最优参数”。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把这些机制吃透后，再去谈高可用、PITR、逻辑复制，才会知道每条配置背后买的是什么、卖的是什么。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/wal-intro.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：Write-Ahead Logging (WAL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/wal-configuration.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：WAL Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/wal-async-commit.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：Asynchronous Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/wal-internals.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：WAL Internals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/runtime-config-wal.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：Write Ahead Log 运行参数（19.5）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/sql-checkpoint.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：CHECKPOINT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/monitoring-stats.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：Monitoring Statistics（含 &lt;code&gt;pg_stat_checkpointer&lt;/code&gt; / &lt;code&gt;pg_stat_wal&lt;/code&gt;）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/functions-admin.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 文档：系统管理函数（&lt;code&gt;pg_current_wal_lsn&lt;/code&gt; 等）&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>PostgreSQL B-tree 索引：结构、扫描方式与工程实践</title><link>https://blog.waihost.com/posts/postgresql-btree-index-scan-practice/</link><pubDate>Fri, 24 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/postgresql-btree-index-scan-practice/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/postgresql-btree-index-scan-practice.svg" alt="Featured image of post PostgreSQL B-tree 索引：结构、扫描方式与工程实践" /&gt;&lt;p&gt;线上 SQL 变慢时，第一反应往往是“加个索引”。但在 PostgreSQL 里，索引不是“有就快”的开关：默认的 &lt;strong&gt;B-tree&lt;/strong&gt; 适合哪些谓词？多列索引为什么“左边优先”？为什么 &lt;code&gt;EXPLAIN&lt;/code&gt; 里会出现 &lt;code&gt;Index Scan&lt;/code&gt;、&lt;code&gt;Bitmap Heap Scan&lt;/code&gt; 或 &lt;code&gt;Index Only Scan&lt;/code&gt;？部分索引、&lt;code&gt;INCLUDE&lt;/code&gt; 覆盖列、&lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt; 又分别解决什么工程问题？&lt;/p&gt;
&lt;p&gt;本文基于 PostgreSQL 官方文档（当前文档站对应 &lt;strong&gt;PostgreSQL 18&lt;/strong&gt; 手册章节），从机制讲到可复现实验与排错清单，帮助你把索引用在真正该用的地方。&lt;/p&gt;
&lt;h2 id="问题背景没有索引时数据库在做什么"&gt;&lt;a href="#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af%e6%b2%a1%e6%9c%89%e7%b4%a2%e5%bc%95%e6%97%b6%e6%95%b0%e6%8d%ae%e5%ba%93%e5%9c%a8%e5%81%9a%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;问题背景：没有索引时，数据库在做什么
&lt;/h2&gt;&lt;p&gt;官方索引导论用了一个很直观的例子：表 &lt;code&gt;test1(id, content)&lt;/code&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;content&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="n"&gt;test1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;constant&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;如果没有预先准备，系统只能 &lt;strong&gt;逐行扫描整表&lt;/strong&gt; 找匹配行；行数很大而命中很少时，这显然低效。若在 &lt;code&gt;id&lt;/code&gt; 上维护索引，定位匹配行可以走更高效的路径（例如在搜索树中只走几层），而不必通读整本书式的堆表。&lt;/p&gt;
&lt;p&gt;关键工程含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;索引要提前“预见”查询会怎样查找数据——这是 DBA/开发者的职责，而不是数据库自动替你猜对所有场景。&lt;/li&gt;
&lt;li&gt;索引创建后会随表的增删改自动维护，但也会带来 &lt;strong&gt;写放大与存储开销&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;规划器是否选用索引，依赖统计信息；因此要定期 &lt;code&gt;ANALYZE&lt;/code&gt;，并学会用 &lt;code&gt;EXPLAIN&lt;/code&gt; 验证真实计划。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="核心原理为什么日常几乎都是-b-tree"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e5%8e%9f%e7%90%86%e4%b8%ba%e4%bb%80%e4%b9%88%e6%97%a5%e5%b8%b8%e5%87%a0%e4%b9%8e%e9%83%bd%e6%98%af-b-tree" class="header-anchor"&gt;&lt;/a&gt;核心原理：为什么日常几乎都是 B-tree
&lt;/h2&gt;&lt;p&gt;PostgreSQL 提供多种索引访问方法：&lt;code&gt;B-tree&lt;/code&gt;、&lt;code&gt;Hash&lt;/code&gt;、&lt;code&gt;GiST&lt;/code&gt;、&lt;code&gt;SP-GiST&lt;/code&gt;、&lt;code&gt;GIN&lt;/code&gt;、&lt;code&gt;BRIN&lt;/code&gt;，以及扩展如 &lt;code&gt;bloom&lt;/code&gt;。&lt;br&gt;
&lt;strong&gt;&lt;code&gt;CREATE INDEX&lt;/code&gt; 默认创建 B-tree&lt;/strong&gt;，因为它覆盖了最常见的相等与范围查询场景。其它类型需要显式 &lt;code&gt;USING method&lt;/code&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&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;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;USING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HASH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;column&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;h3 id="b-tree-能加速哪些谓词"&gt;&lt;a href="#b-tree-%e8%83%bd%e5%8a%a0%e9%80%9f%e5%93%aa%e4%ba%9b%e8%b0%93%e8%af%8d" class="header-anchor"&gt;&lt;/a&gt;B-tree 能加速哪些谓词
&lt;/h3&gt;&lt;p&gt;官方说明：B-tree 可处理 &lt;strong&gt;可排序数据&lt;/strong&gt; 上的相等与范围查询。规划器会在索引列参与下列比较时考虑使用 B-tree：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;运算符 / 形态&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; &lt;code&gt;&amp;lt;=&lt;/code&gt; &lt;code&gt;=&lt;/code&gt; &lt;code&gt;&amp;gt;=&lt;/code&gt; &lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;基本比较&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;BETWEEN&lt;/code&gt; / &lt;code&gt;IN&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;可视为上述比较的组合&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;IS NULL&lt;/code&gt; / &lt;code&gt;IS NOT NULL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;也可用于 B-tree&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LIKE&lt;/code&gt; / &lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;仅当模式为常量且 &lt;strong&gt;锚定在字符串开头&lt;/strong&gt;，如 &lt;code&gt;col LIKE 'foo%'&lt;/code&gt;、&lt;code&gt;col ~ '^foo'&lt;/code&gt;；&lt;code&gt;'%bar'&lt;/code&gt; 这类前后缀/中间匹配不行&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;补充：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;非 &lt;code&gt;C&lt;/code&gt; locale 时，模式匹配类查询可能需要特殊 &lt;strong&gt;operator class&lt;/strong&gt; 才能用索引（见手册“Operator Classes and Operator Families”相关章节）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ILIKE&lt;/code&gt; / &lt;code&gt;~*&lt;/code&gt; 更受限：模式通常需要以“不受大小写转换影响的字符”开头。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hash 索引&lt;/strong&gt; 只存 32-bit 哈希码，因此 &lt;strong&gt;只能处理简单相等比较&lt;/strong&gt;，不能替代 B-tree 的范围与排序能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="只有-b-tree-能带着顺序吐行"&gt;&lt;a href="#%e5%8f%aa%e6%9c%89-b-tree-%e8%83%bd%e5%b8%a6%e7%9d%80%e9%a1%ba%e5%ba%8f%e5%90%90%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;只有 B-tree 能“带着顺序”吐行
&lt;/h3&gt;&lt;p&gt;索引除了找行，还可能直接按指定顺序交付结果，从而避免额外排序。官方明确：在当前支持的索引类型中，&lt;strong&gt;只有 B-tree 能产生有序输出&lt;/strong&gt;；其它类型返回匹配行的顺序是未指定、实现相关的。&lt;/p&gt;
&lt;p&gt;默认 B-tree 条目按 &lt;strong&gt;升序、NULLS LAST&lt;/strong&gt; 存储（相等时用表 TID 作决胜列）。因此：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;正向扫描满足 &lt;code&gt;ORDER BY x&lt;/code&gt;（即 &lt;code&gt;ASC NULLS LAST&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;反向扫描可满足 &lt;code&gt;ORDER BY x DESC&lt;/code&gt;（对应 &lt;code&gt;DESC NULLS FIRST&lt;/code&gt; 等组合规则）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工程上特别有价值的形态是 &lt;strong&gt;&lt;code&gt;ORDER BY ... LIMIT n&lt;/code&gt;&lt;/strong&gt;：显式排序往往要处理全部候选才能取前 n 行；若有匹配的 B-tree，可直接取前 n 行，无需扫完剩余数据。&lt;/p&gt;
&lt;h3 id="唯一性约束如何落地"&gt;&lt;a href="#%e5%94%af%e4%b8%80%e6%80%a7%e7%ba%a6%e6%9d%9f%e5%a6%82%e4%bd%95%e8%90%bd%e5%9c%b0" class="header-anchor"&gt;&lt;/a&gt;唯一性约束如何落地
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目前只有 B-tree 可声明为 unique&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;默认情况下，唯一列中的 &lt;strong&gt;多个 NULL 不视为相等&lt;/strong&gt;（允许多个 NULL）；&lt;code&gt;NULLS NOT DISTINCT&lt;/code&gt; 会把 NULL 当相等处理。&lt;/li&gt;
&lt;li&gt;定义 &lt;code&gt;PRIMARY KEY&lt;/code&gt; / &lt;code&gt;UNIQUE&lt;/code&gt; 约束时，PostgreSQL &lt;strong&gt;会自动创建&lt;/strong&gt; 对应唯一索引，无需再手写一份重复索引。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="扫描方式同一条-sql三种常见走路方式"&gt;&lt;a href="#%e6%89%ab%e6%8f%8f%e6%96%b9%e5%bc%8f%e5%90%8c%e4%b8%80%e6%9d%a1-sql%e4%b8%89%e7%a7%8d%e5%b8%b8%e8%a7%81%e8%b5%b0%e8%b7%af%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;扫描方式：同一条 SQL，三种常见“走路方式”
&lt;/h2&gt;&lt;p&gt;PostgreSQL 的索引是 &lt;strong&gt;二级索引（secondary index）&lt;/strong&gt;：索引与堆表（heap）分开存储。普通索引扫描通常既读索引，又回表读堆；匹配的索引项可能相邻，但对应堆行可能散落各处，带来随机 I/O。&lt;/p&gt;
&lt;h3 id="1index-scan点查--高选择性范围"&gt;&lt;a href="#1index-scan%e7%82%b9%e6%9f%a5--%e9%ab%98%e9%80%89%e6%8b%a9%e6%80%a7%e8%8c%83%e5%9b%b4" class="header-anchor"&gt;&lt;/a&gt;1）Index Scan：点查 / 高选择性范围
&lt;/h3&gt;&lt;p&gt;适合“索引快速锁定少量行，再回表取完整行”的路径。&lt;code&gt;EXPLAIN&lt;/code&gt; 中常见 &lt;code&gt;Index Scan using ...&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="2bitmap-index-scan--bitmap-heap-scan中等选择性或组合条件"&gt;&lt;a href="#2bitmap-index-scan--bitmap-heap-scan%e4%b8%ad%e7%ad%89%e9%80%89%e6%8b%a9%e6%80%a7%e6%88%96%e7%bb%84%e5%90%88%e6%9d%a1%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;2）Bitmap Index Scan + Bitmap Heap Scan：中等选择性或组合条件
&lt;/h3&gt;&lt;p&gt;当需要组合多个索引、或单次索引扫描无法直接表达某些 &lt;code&gt;OR&lt;/code&gt;/&lt;code&gt;AND&lt;/code&gt; 形态时，系统可：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;扫描一个或多个索引，在内存中生成 &lt;strong&gt;bitmap&lt;/strong&gt;（标记可能命中的堆位置）&lt;/li&gt;
&lt;li&gt;对 bitmap 做 &lt;code&gt;AND&lt;/code&gt; / &lt;code&gt;OR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;再按 &lt;strong&gt;物理顺序&lt;/strong&gt; 访问堆表（&lt;code&gt;Bitmap Heap Scan&lt;/code&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;官方指出：按物理序访问会 &lt;strong&gt;丢失原索引顺序&lt;/strong&gt;，因此后续若需要排序，可能再加 &lt;code&gt;Sort&lt;/code&gt;。这也解释了：bitmap 路径擅长降低随机 I/O，但不一定能顺便满足 &lt;code&gt;ORDER BY&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="3index-only-scan尽量不回表"&gt;&lt;a href="#3index-only-scan%e5%b0%bd%e9%87%8f%e4%b8%8d%e5%9b%9e%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;3）Index Only Scan：尽量不回表
&lt;/h3&gt;&lt;p&gt;Index-only scan 的目标是 &lt;strong&gt;只靠索引回答查询&lt;/strong&gt;。官方给出两个基本前提：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;索引类型支持&lt;/strong&gt; index-only scan：B-tree &lt;strong&gt;始终支持&lt;/strong&gt;；GiST/SP-GiST 仅部分 operator class；GIN 等通常不支持（索引项往往只存原值的一部分）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查询只引用索引中存有的列&lt;/strong&gt;。例如索引在 &lt;code&gt;(x, y)&lt;/code&gt; 上：
&lt;ul&gt;
&lt;li&gt;可用：&lt;code&gt;SELECT x, y FROM tab WHERE x = 'key';&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不可用（还要读 &lt;code&gt;z&lt;/code&gt;）：&lt;code&gt;SELECT x, z FROM tab WHERE x = 'key';&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;即便列都在索引里，PostgreSQL 仍要做 &lt;strong&gt;MVCC 可见性&lt;/strong&gt; 判断。可见性信息不在索引项里，而在堆中；因此引入 &lt;strong&gt;visibility map（可见性映射）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;若堆页对应 all-visible 位已设置，可认为行对当前/未来事务可见，&lt;strong&gt;无需再访问堆元组&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;若未设置，仍需回表检查可见性——此时相对普通 Index Scan 的收益会明显下降&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此：Index Only Scan “物理上可能”，但 &lt;strong&gt;只有当表中相当比例堆页的 all-visible 位有效时&lt;/strong&gt; 才更划算。对“大量行很少变化”的表，这类扫描非常实用；写很频繁、可见性图难以保持的表，收益会打折。&lt;/p&gt;
&lt;h3 id="覆盖索引与-include"&gt;&lt;a href="#%e8%a6%86%e7%9b%96%e7%b4%a2%e5%bc%95%e4%b8%8e-include" class="header-anchor"&gt;&lt;/a&gt;覆盖索引与 &lt;code&gt;INCLUDE&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;为了让高频查询更容易走 index-only，可以做 &lt;strong&gt;covering index（覆盖索引）&lt;/strong&gt;：让索引包含查询需要返回/过滤的列。PostgreSQL 允许用 &lt;code&gt;INCLUDE&lt;/code&gt; 添加 &lt;strong&gt;非键（non-key）列&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;非键列 &lt;strong&gt;不能&lt;/strong&gt; 用于索引扫描的查找条件，也不参与唯一/排他约束判定&lt;/li&gt;
&lt;li&gt;但 index-only scan 可直接从索引叶子返回这些列，无需回表&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INCLUDE&lt;/code&gt; 列会增大索引、复制数据；宽列要谨慎&lt;/li&gt;
&lt;li&gt;带 non-key 列的 B-tree &lt;strong&gt;不会使用 deduplication&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;表达式不能作为 &lt;code&gt;INCLUDE&lt;/code&gt; 列（因为无法用于 index-only scan）&lt;/li&gt;
&lt;li&gt;当前 B-tree / GiST / SP-GiST 支持该特性；叶子存 INCLUDE 值，上层导航项不包含它们&lt;/li&gt;
&lt;/ul&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="c1"&gt;-- 键列用于查找，INCLUDE 列服务于覆盖返回
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders_user_created_cover&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_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;created_at&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INCLUDE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&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;h2 id="多列索引部分索引选型比多建几个更重要"&gt;&lt;a href="#%e5%a4%9a%e5%88%97%e7%b4%a2%e5%bc%95%e9%83%a8%e5%88%86%e7%b4%a2%e5%bc%95%e9%80%89%e5%9e%8b%e6%af%94%e5%a4%9a%e5%bb%ba%e5%87%a0%e4%b8%aa%e6%9b%b4%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;多列索引、部分索引：选型比“多建几个”更重要
&lt;/h2&gt;&lt;h3 id="多列-b-tree最左前缀与效率"&gt;&lt;a href="#%e5%a4%9a%e5%88%97-b-tree%e6%9c%80%e5%b7%a6%e5%89%8d%e7%bc%80%e4%b8%8e%e6%95%88%e7%8e%87" class="header-anchor"&gt;&lt;/a&gt;多列 B-tree：最左前缀与效率
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;索引最多 &lt;strong&gt;32 列&lt;/strong&gt;（含 &lt;code&gt;INCLUDE&lt;/code&gt;；编译期可改 &lt;code&gt;pg_config_manual.h&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;多键列目前由 B-tree、GiST、GIN、BRIN 等支持（与能否 &lt;code&gt;INCLUDE&lt;/code&gt; 是两件独立的事）。&lt;/li&gt;
&lt;li&gt;多列 B-tree 可用于涉及任意列子集的条件，但 &lt;strong&gt;在前导（最左）列上有约束时最高效&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;精确规则（官方表述）：对前导列的 &lt;strong&gt;相等约束&lt;/strong&gt;，加上第一个没有相等约束的列上的 &lt;strong&gt;不等式约束&lt;/strong&gt;，总是用于限制扫描的索引区间；更右侧列上的条件仍会在索引内检查（可减少回表），但不一定缩小扫描区间。&lt;/li&gt;
&lt;li&gt;新版本还有 &lt;strong&gt;skip scan&lt;/strong&gt; 优化：在合适基数下，可对缺少常规相等约束的中间列做内部动态相等约束，减少读取区间——但这是优化，不是让你随意打乱“左前缀”设计习惯。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;经验对照：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;查询形态&lt;/th&gt;
					&lt;th&gt;更合适的索引直觉&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;总是 &lt;code&gt;WHERE a = ? AND b = ?&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;(a, b)&lt;/code&gt; 复合索引&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有时只有 &lt;code&gt;a&lt;/code&gt;，有时只有 &lt;code&gt;b&lt;/code&gt;，有时两者&lt;/td&gt;
					&lt;td&gt;可能两个单列 + 让规划器组合；或评估 skip scan / 复合&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ORDER BY a, b LIMIT n&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;与排序方向一致的 &lt;code&gt;(a, b)&lt;/code&gt; B-tree&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;只查“活跃订单”等小子集&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;部分索引&lt;/strong&gt; 往往比全表索引更划算&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="部分索引只索引值得索引的子集"&gt;&lt;a href="#%e9%83%a8%e5%88%86%e7%b4%a2%e5%bc%95%e5%8f%aa%e7%b4%a2%e5%bc%95%e5%80%bc%e5%be%97%e7%b4%a2%e5%bc%95%e7%9a%84%e5%ad%90%e9%9b%86" class="header-anchor"&gt;&lt;/a&gt;部分索引：只索引“值得索引”的子集
&lt;/h3&gt;&lt;p&gt;部分索引建立在表的一个子集上，子集由谓词（&lt;code&gt;WHERE&lt;/code&gt;）定义，索引 &lt;strong&gt;只包含满足谓词的行&lt;/strong&gt;。&lt;/p&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;/li&gt;
&lt;/ol&gt;
&lt;p&gt;典型场景：访问日志中组织内网 IP 占比极高，但排查更关心外部 IP：&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;access_log_client_ip_ix&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;access_log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_ip&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;192.168.100.0&amp;#39;&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="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;client_ip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;192.168.100.255&amp;#39;&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="w"&gt; &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;只有查询条件也落在“被索引子集”内时，规划器才能使用该部分索引；条件与谓词冲突时不会用。&lt;/p&gt;
&lt;h2 id="可复现实验从建表到读懂-explain"&gt;&lt;a href="#%e5%8f%af%e5%a4%8d%e7%8e%b0%e5%ae%9e%e9%aa%8c%e4%bb%8e%e5%bb%ba%e8%a1%a8%e5%88%b0%e8%af%bb%e6%87%82-explain" class="header-anchor"&gt;&lt;/a&gt;可复现实验：从建表到读懂 EXPLAIN
&lt;/h2&gt;&lt;p&gt;下面用一套小实验把机制落到命令（在任意 PostgreSQL ≥ 14 环境可跑；语句本身与官方语义一致）。&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="c1"&gt;-- 1) 准备数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;DROP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bigserial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timestamptz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&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="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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_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;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;created_at&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;int&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;paid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;pending&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cancelled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;paid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;paid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="mi"&gt;1&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;int&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&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="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;int&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; days&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;interval&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;generate_series&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200000&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;span class="line"&gt;&lt;span class="cl"&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;ANALYZE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 2) 无业务二级索引时看计划（主键本身是 B-tree 唯一索引）
&lt;/span&gt;&lt;/span&gt;&lt;/span&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="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ANALYZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BUFFERS&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_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;42&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 3) 建立常用复合索引 + 部分索引 + 覆盖索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders_user_created_idx&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_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;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;span class="line"&gt;&lt;span class="cl"&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders_pending_idx&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;created_at&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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;pending&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;span class="line"&gt;&lt;span class="cl"&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders_user_cover_idx&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INCLUDE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&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;span class="line"&gt;&lt;span class="cl"&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;ANALYZE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 4) 对比计划节点名称
&lt;/span&gt;&lt;/span&gt;&lt;/span&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="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ANALYZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BUFFERS&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;span class="line"&gt;&lt;span class="cl"&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;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;user_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;42&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;span class="line"&gt;&lt;span class="cl"&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;EXPLAIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ANALYZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BUFFERS&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;span class="line"&gt;&lt;span class="cl"&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;created_at&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;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;pending&amp;#39;&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="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;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&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="nb"&gt;interval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;7 days&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;span class="line"&gt;&lt;span class="cl"&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;EXPLAIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ANALYZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BUFFERS&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_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;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo_orders&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;user_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;42&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 若统计与可见性合适，可能出现 Index Only Scan（依赖 INCLUDE 覆盖 + visibility map）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;读计划时优先看：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;节点类型&lt;/strong&gt;：&lt;code&gt;Seq Scan&lt;/code&gt; / &lt;code&gt;Index Scan&lt;/code&gt; / &lt;code&gt;Bitmap Index Scan&lt;/code&gt; + &lt;code&gt;Bitmap Heap Scan&lt;/code&gt; / &lt;code&gt;Index Only Scan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实际行数 vs 估算行数&lt;/strong&gt;（&lt;code&gt;rows&lt;/code&gt;）：偏差大 → 统计过期或谓词难估，先 &lt;code&gt;ANALYZE&lt;/code&gt;，再考虑扩展统计&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buffers&lt;/strong&gt;：命中共享缓冲还是读盘；Index Only Scan 是否仍有大量 heap fetches（可见性图不给力）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;是否多了不必要的 Sort&lt;/strong&gt;：排序方向与索引 &lt;code&gt;(ASC/DESC, NULLS ...)&lt;/code&gt; 是否一致&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="生产变更create-index-concurrently"&gt;&lt;a href="#%e7%94%9f%e4%ba%a7%e5%8f%98%e6%9b%b4create-index-concurrently" class="header-anchor"&gt;&lt;/a&gt;生产变更：&lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;普通 &lt;code&gt;CREATE INDEX&lt;/code&gt; 会对表加写锁：其它事务仍可读，但 &lt;strong&gt;INSERT/UPDATE/DELETE 会阻塞到索引建完&lt;/strong&gt;。大表上这可能长达数小时，生产不可接受。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt; 的官方要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;构建过程 &lt;strong&gt;不获取会阻止并发写&lt;/strong&gt; 的锁（允许正常 DML 继续）&lt;/li&gt;
&lt;li&gt;代价：通常要 &lt;strong&gt;两次表扫描&lt;/strong&gt;，并等待可能修改/使用该索引的相关事务结束，&lt;strong&gt;总工作量更大、耗时更长&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;过程中索引会先以 &lt;strong&gt;INVALID&lt;/strong&gt; 状态进入系统目录；成功结束后才标为可用&lt;/li&gt;
&lt;li&gt;若扫描阶段失败（死锁、唯一冲突等），命令失败但可能留下 &lt;strong&gt;INVALID 索引&lt;/strong&gt;：查询会忽略它，却仍要为写维护它 → 推荐 &lt;code&gt;DROP&lt;/code&gt; 后重试 &lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt;（或 &lt;code&gt;REINDEX INDEX CONCURRENTLY&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt; &lt;strong&gt;不能&lt;/strong&gt; 放在事务块里；分区表并发构建有额外限制（可先对分区并发建，再非并发建分区父索引以缩短写锁定窗口）&lt;/li&gt;
&lt;li&gt;同一表上 &lt;strong&gt;同时只能有一个&lt;/strong&gt; concurrent index build&lt;/li&gt;
&lt;/ul&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sales_quantity_index&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sales_table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quantity&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;h2 id="常见坑与排查清单"&gt;&lt;a href="#%e5%b8%b8%e8%a7%81%e5%9d%91%e4%b8%8e%e6%8e%92%e6%9f%a5%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;常见坑与排查清单
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;现象&lt;/th&gt;
					&lt;th&gt;常见原因&lt;/th&gt;
					&lt;th&gt;怎么查 / 怎么办&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;建了索引仍 &lt;code&gt;Seq Scan&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;选择性差、统计过期、函数包住列导致无法匹配、成本模型认为全表更便宜&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;EXPLAIN&lt;/code&gt;；&lt;code&gt;ANALYZE&lt;/code&gt;；避免 &lt;code&gt;WHERE func(col)=...&lt;/code&gt;（改表达式索引）；用真实参数看计划&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LIKE '%x%'&lt;/code&gt; 不走 B-tree&lt;/td&gt;
					&lt;td&gt;B-tree 需要前缀锚定模式&lt;/td&gt;
					&lt;td&gt;换 &lt;code&gt;pg_trgm&lt;/code&gt; + GIN/GiST 等（另一条路线，不是默认 B-tree）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多列索引“像没用”&lt;/td&gt;
					&lt;td&gt;谓词没落在最左列，或类型/排序规则不匹配&lt;/td&gt;
					&lt;td&gt;检查前导列是否有相等/范围条件；核对 &lt;code&gt;ASC/DESC NULLS&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;期望 Index Only Scan 却回表很多&lt;/td&gt;
					&lt;td&gt;查询列未覆盖；visibility map 中 all-visible 比例低&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;INCLUDE&lt;/code&gt; 覆盖；减少无意义更新；关注 vacuum 是否跟上&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;写变慢、膨胀&lt;/td&gt;
					&lt;td&gt;索引过多、宽 INCLUDE、低选择性索引&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;pg_stat_user_indexes&lt;/code&gt; 看扫描次数；删冗余；部分索引收窄&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CONCURRENTLY&lt;/code&gt; 后有 &lt;code&gt;INVALID&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;构建失败留下残留&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;\d table&lt;/code&gt; 确认；&lt;code&gt;DROP INDEX&lt;/code&gt; 后重建&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;唯一约束“允许多个 NULL”&lt;/td&gt;
					&lt;td&gt;默认 NULL 不相等&lt;/td&gt;
					&lt;td&gt;需要业务唯一含 NULL 时用 &lt;code&gt;NULLS NOT DISTINCT&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&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="c1"&gt;-- 索引是否被使用（需打开 stats）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;schemaname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;relname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indexrelname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_scan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_tup_read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_tup_fetch&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_stat_user_indexes&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_scan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ASC&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;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 无效索引排查（概念：concurrent 失败残留）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indisvalid&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&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;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indexrelid&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="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indisvalid&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;h2 id="工程实践建议可直接落地"&gt;&lt;a href="#%e5%b7%a5%e7%a8%8b%e5%ae%9e%e8%b7%b5%e5%bb%ba%e8%ae%ae%e5%8f%af%e7%9b%b4%e6%8e%a5%e8%90%bd%e5%9c%b0" class="header-anchor"&gt;&lt;/a&gt;工程实践建议（可直接落地）
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先写清访问路径&lt;/strong&gt;：等值 / 范围 / 排序 / 覆盖返回列 / 是否只查子集。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;默认从 B-tree 开始&lt;/strong&gt;：范围、排序、唯一约束几乎都靠它；Hash 仅在“只要相等且理解其限制”时考虑。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复合索引按过滤+排序设计列序&lt;/strong&gt;：高频等值列靠左，范围/排序列靠右；方向与 &lt;code&gt;ORDER BY&lt;/code&gt; 对齐。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;热点子集优先部分索引&lt;/strong&gt;：状态机里的 &lt;code&gt;pending&lt;/code&gt;、软删除后的“有效行”、租户内活跃数据等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高频只读投影再谈 &lt;code&gt;INCLUDE&lt;/code&gt;&lt;/strong&gt;：覆盖收益要压过索引变大与 dedup 失效的代价。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生产建索引用 &lt;code&gt;CONCURRENTLY&lt;/code&gt;，并处理 INVALID 残留&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用 &lt;code&gt;EXPLAIN (ANALYZE, BUFFERS)&lt;/code&gt; 闭环&lt;/strong&gt;，而不是用“感觉”判断索引是否生效。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;PostgreSQL 索引体系的核心不是“类型清单”，而是三层决策：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;访问方法&lt;/strong&gt;：日常以 B-tree 承载相等、范围、排序与唯一性；Hash/GIN/GiST/BRIN 解决更专门的谓词与数据形态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;扫描算子&lt;/strong&gt;：Index Scan 精确定位，Bitmap 组合与减少随机 I/O，Index Only Scan 在覆盖列 + 可见性图友好时避免回表。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工程形态&lt;/strong&gt;：多列最左前缀、部分索引缩子集、&lt;code&gt;INCLUDE&lt;/code&gt; 做覆盖、&lt;code&gt;CONCURRENTLY&lt;/code&gt; 保障在线变更。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把这三层和 &lt;code&gt;EXPLAIN&lt;/code&gt; 对上，索引才会从“玄学加速”变成可验证的性能工具。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-intro.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Indexes — Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-types.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Index Types（B-Tree / Hash / GiST / GIN / BRIN）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-multicolumn.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Multicolumn Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-ordering.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Indexes and ORDER BY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-bitmap-scans.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Combining Multiple Indexes（bitmap 组合）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-unique.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Unique Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-partial.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Partial Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/indexes-index-only-scans.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Index-Only Scans and Covering Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/sql-createindex.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：CREATE INDEX（含 CONCURRENTLY / INCLUDE）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.postgresql.org/docs/current/using-explain.html" target="_blank" rel="noopener"
 &gt;PostgreSQL 18 文档：Using EXPLAIN&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>OceanBase 从零开始：核心概念、上手路径，以及和 MySQL 的关键差异</title><link>https://blog.waihost.com/posts/oceanbase-beginner-mysql-comparison/</link><pubDate>Fri, 17 Jul 2026 01:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/oceanbase-beginner-mysql-comparison/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/oceanbase-beginner-mysql-comparison.svg" alt="Featured image of post OceanBase 从零开始：核心概念、上手路径，以及和 MySQL 的关键差异" /&gt;&lt;p&gt;如果你已经会 MySQL，第一次接触 OceanBase 时，最容易卡住的不是“SQL 怎么写”，而是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;它看起来很像 MySQL，为什么连接方式、资源模型、高可用和运维概念完全不是一回事？&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;本文面向零基础到 MySQL 初中级同学，用一条从概念到上手的路径讲清楚：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;OceanBase 是什么&lt;/li&gt;
&lt;li&gt;和 MySQL 在架构、租户、连接、兼容性上的核心差异&lt;/li&gt;
&lt;li&gt;从连接、建库建表到基础 SQL 的最小实践&lt;/li&gt;
&lt;li&gt;什么场景该把 OceanBase 当“更强的 MySQL”，什么场景不能这么想&lt;/li&gt;
&lt;/ol&gt;

 &lt;blockquote&gt;
 &lt;p&gt;说明：本文以 &lt;strong&gt;OceanBase 社区版（MySQL 模式）&lt;/strong&gt; 为主。官方文档明确：&lt;strong&gt;社区版仅提供 MySQL 模式&lt;/strong&gt;；企业版还支持 Oracle 模式。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="一先建立正确心智模型"&gt;&lt;a href="#%e4%b8%80%e5%85%88%e5%bb%ba%e7%ab%8b%e6%ad%a3%e7%a1%ae%e5%bf%83%e6%99%ba%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;一、先建立正确心智模型
&lt;/h2&gt;&lt;h3 id="1-mysql-的常见心智模型"&gt;&lt;a href="#1-mysql-%e7%9a%84%e5%b8%b8%e8%a7%81%e5%bf%83%e6%99%ba%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;1. MySQL 的常见心智模型
&lt;/h3&gt;&lt;p&gt;很多人对 MySQL 的默认理解是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;一台机器 / 一个 mysqld 实例
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个 database
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个 table
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;连接通常很直接：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P3306 -uroot -p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;你连上的，基本就是“这个实例本身”。&lt;/p&gt;
&lt;h3 id="2-oceanbase-的心智模型"&gt;&lt;a href="#2-oceanbase-%e7%9a%84%e5%bf%83%e6%99%ba%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;2. OceanBase 的心智模型
&lt;/h3&gt;&lt;p&gt;OceanBase 更接近：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;一个集群（Cluster）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个节点（OBServer）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个可用区（Zone）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个租户（Tenant） ← 应用视角下更像“数据库实例”
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个 database
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个 table / 分区
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键变化只有一句话：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;在 OceanBase 里，应用通常不是“连一台 MySQL 机器”，而是“连某个租户”。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;官方文档把租户定义为：集群内互相隔离的数据库“实例”。对应用来说，一个租户近似一个独立数据库实例；租户之间数据、权限、资源隔离。&lt;/p&gt;
&lt;h2 id="二oceanbase-是什么"&gt;&lt;a href="#%e4%ba%8coceanbase-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;二、OceanBase 是什么
&lt;/h2&gt;&lt;p&gt;OceanBase 是蚂蚁集团开源的&lt;strong&gt;分布式关系型数据库&lt;/strong&gt;，基于 Paxos 类共识协议与分布式架构，提供高可用和水平扩展能力，可运行在普通服务器集群上。&lt;/p&gt;
&lt;p&gt;官方强调的关键能力包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;水平扩展&lt;/li&gt;
&lt;li&gt;高可用（RPO=0、RTO 秒级恢复目标）&lt;/li&gt;
&lt;li&gt;MySQL 兼容，便于迁移&lt;/li&gt;
&lt;li&gt;HTAP（同一套系统同时服务事务与分析负载）&lt;/li&gt;
&lt;li&gt;多租户资源隔离&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你可以把“上手阶段”理解成两层：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;层&lt;/th&gt;
					&lt;th&gt;你感受到的&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL 层&lt;/td&gt;
					&lt;td&gt;很像 MySQL：&lt;code&gt;CREATE DATABASE&lt;/code&gt; / &lt;code&gt;CREATE TABLE&lt;/code&gt; / &lt;code&gt;SELECT&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;系统层&lt;/td&gt;
					&lt;td&gt;更像分布式数据库：集群、Zone、租户、Unit、副本、OBProxy&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="三和-mysql-的核心差异总览"&gt;&lt;a href="#%e4%b8%89%e5%92%8c-mysql-%e7%9a%84%e6%a0%b8%e5%bf%83%e5%b7%ae%e5%bc%82%e6%80%bb%e8%a7%88" class="header-anchor"&gt;&lt;/a&gt;三、和 MySQL 的核心差异总览
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;维度&lt;/th&gt;
					&lt;th&gt;MySQL（常见单机/主从）&lt;/th&gt;
					&lt;th&gt;OceanBase&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;基本部署单元&lt;/td&gt;
					&lt;td&gt;实例（mysqld）&lt;/td&gt;
					&lt;td&gt;集群 + 租户&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;应用连接对象&lt;/td&gt;
					&lt;td&gt;实例&lt;/td&gt;
					&lt;td&gt;租户（经直连或 OBProxy）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;默认端口（常见）&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;直连 &lt;code&gt;2881&lt;/code&gt;，经 ODP/OBProxy 常见 &lt;code&gt;2883&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;用户写法&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;root&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;root@tenant&lt;/code&gt; 或 &lt;code&gt;user@tenant#cluster&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;扩展方式&lt;/td&gt;
					&lt;td&gt;垂直扩容 / 读写分离 / 分库分表&lt;/td&gt;
					&lt;td&gt;原生分区、多节点、副本扩展&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;高可用机制&lt;/td&gt;
					&lt;td&gt;主从复制、MGR 等&lt;/td&gt;
					&lt;td&gt;基于 Multi-Paxos 的多副本日志流&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;多业务隔离&lt;/td&gt;
					&lt;td&gt;多实例 / 多库 + 权限&lt;/td&gt;
					&lt;td&gt;原生多租户 + 资源池&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;存储引擎模型&lt;/td&gt;
					&lt;td&gt;InnoDB 等可插拔引擎&lt;/td&gt;
					&lt;td&gt;自研分布式存储与事务体系&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL 兼容&lt;/td&gt;
					&lt;td&gt;原生 MySQL&lt;/td&gt;
					&lt;td&gt;MySQL 模式兼容 5.7/8.0 大部分能力，但非 100%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;社区版模式&lt;/td&gt;
					&lt;td&gt;MySQL&lt;/td&gt;
					&lt;td&gt;仅 MySQL 模式&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一句话：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;MySQL 更像“一台关系库”；OceanBase 更像“一个可多租户的分布式数据库平台”。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="四架构差异为什么它不像单机-mysql"&gt;&lt;a href="#%e5%9b%9b%e6%9e%b6%e6%9e%84%e5%b7%ae%e5%bc%82%e4%b8%ba%e4%bb%80%e4%b9%88%e5%ae%83%e4%b8%8d%e5%83%8f%e5%8d%95%e6%9c%ba-mysql" class="header-anchor"&gt;&lt;/a&gt;四、架构差异：为什么它不像单机 MySQL
&lt;/h2&gt;&lt;h3 id="1-shared-nothing-集群"&gt;&lt;a href="#1-shared-nothing-%e9%9b%86%e7%be%a4" class="header-anchor"&gt;&lt;/a&gt;1. Shared-Nothing 集群
&lt;/h3&gt;&lt;p&gt;官方系统架构文档指出，OceanBase 常用无共享（Shared-Nothing）模式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点对等&lt;/li&gt;
&lt;li&gt;每个节点都有自己的 SQL / 存储 / 事务能力&lt;/li&gt;
&lt;li&gt;表可水平拆分为多个分区（Partition）&lt;/li&gt;
&lt;li&gt;分区数据落在 Tablet，修改通过日志流（Log Stream）持久化&lt;/li&gt;
&lt;li&gt;主从副本通过 Multi-Paxos 保持一致性&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这意味着：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据天然可分布到多节点&lt;/li&gt;
&lt;li&gt;故障切换依赖副本选举，而不是简单“切到另一台 mysqld”&lt;/li&gt;
&lt;li&gt;建表时的分区设计，会直接影响数据分布与扩展性&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="2-多租户最容易被-mysql-同学忽略的概念"&gt;&lt;a href="#2-%e5%a4%9a%e7%a7%9f%e6%88%b7%e6%9c%80%e5%ae%b9%e6%98%93%e8%a2%ab-mysql-%e5%90%8c%e5%ad%a6%e5%bf%bd%e7%95%a5%e7%9a%84%e6%a6%82%e5%bf%b5" class="header-anchor"&gt;&lt;/a&gt;2. 多租户：最容易被 MySQL 同学忽略的概念
&lt;/h3&gt;&lt;p&gt;在 OceanBase 中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;集群初始化后会有系统租户 &lt;strong&gt;&lt;code&gt;sys&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sys&lt;/code&gt; 保存集群元数据，本身也是 MySQL 兼容模式租户&lt;/li&gt;
&lt;li&gt;业务一般应在&lt;strong&gt;普通租户&lt;/strong&gt;里建库建表，而不是把所有业务都堆在 &lt;code&gt;sys&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;创建业务租户的典型顺序是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Unit Config（资源规格）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Resource Pool（资源池）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → Tenant（租户）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这和 MySQL 里“直接 &lt;code&gt;CREATE DATABASE&lt;/code&gt;”完全不同。&lt;br&gt;
MySQL 的 database 更像命名空间；OceanBase 的 tenant 更像独立实例边界。&lt;/p&gt;
&lt;h3 id="3-obproxy--odp应用如何像访问单机库一样访问分布式库"&gt;&lt;a href="#3-obproxy--odp%e5%ba%94%e7%94%a8%e5%a6%82%e4%bd%95%e5%83%8f%e8%ae%bf%e9%97%ae%e5%8d%95%e6%9c%ba%e5%ba%93%e4%b8%80%e6%a0%b7%e8%ae%bf%e9%97%ae%e5%88%86%e5%b8%83%e5%bc%8f%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;3. OBProxy / ODP：应用如何“像访问单机库一样”访问分布式库
&lt;/h3&gt;&lt;p&gt;为了让应用尽量少感知分区和副本分布，OceanBase 提供 &lt;strong&gt;ODP（OceanBase Database Proxy，又称 OBProxy）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用通常连代理&lt;/li&gt;
&lt;li&gt;代理把 SQL 路由到合适节点&lt;/li&gt;
&lt;li&gt;对应用更接近“连一个入口地址”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这对应 MySQL 生态里的 proxy / 中间件角色，但在 OceanBase 里它更常作为标准访问路径出现。&lt;/p&gt;
&lt;h2 id="五连接差异最容易踩坑的地方"&gt;&lt;a href="#%e4%ba%94%e8%bf%9e%e6%8e%a5%e5%b7%ae%e5%bc%82%e6%9c%80%e5%ae%b9%e6%98%93%e8%b8%a9%e5%9d%91%e7%9a%84%e5%9c%b0%e6%96%b9" class="header-anchor"&gt;&lt;/a&gt;五、连接差异：最容易踩坑的地方
&lt;/h2&gt;&lt;h3 id="1-docker-体验环境最简单"&gt;&lt;a href="#1-docker-%e4%bd%93%e9%aa%8c%e7%8e%af%e5%a2%83%e6%9c%80%e7%ae%80%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;1. Docker 体验环境（最简单）
&lt;/h3&gt;&lt;p&gt;快速体验可用官方镜像：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker logs oceanbase-ce &lt;span class="p"&gt;|&lt;/span&gt; tail -1 &lt;span class="c1"&gt;# 期望 boot success!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;连接示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 系统租户 root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或宿主机 mysql 客户端&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot@test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-正式连接写法用户名里有租户"&gt;&lt;a href="#2-%e6%ad%a3%e5%bc%8f%e8%bf%9e%e6%8e%a5%e5%86%99%e6%b3%95%e7%94%a8%e6%88%b7%e5%90%8d%e9%87%8c%e6%9c%89%e7%a7%9f%e6%88%b7" class="header-anchor"&gt;&lt;/a&gt;2. 正式连接写法：用户名里有租户
&lt;/h3&gt;&lt;p&gt;官方文档给出两类常见连接：&lt;/p&gt;
&lt;h4 id="直连-observer默认端口常为-2881"&gt;&lt;a href="#%e7%9b%b4%e8%bf%9e-observer%e9%bb%98%e8%ae%a4%e7%ab%af%e5%8f%a3%e5%b8%b8%e4%b8%ba-2881" class="header-anchor"&gt;&lt;/a&gt;直连 OBServer（默认端口常为 2881）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h&amp;lt;observer_ip&amp;gt; -P2881 -u用户名@租户名 -p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直连时 &lt;code&gt;-u&lt;/code&gt; 应是 &lt;code&gt;用户名@租户名&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要在直连用户名里带集群名&lt;/strong&gt;，否则可能报错&lt;/li&gt;
&lt;li&gt;普通租户直连时，目标节点上需要有该租户资源&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="通过-odpobproxy默认端口常为-2883"&gt;&lt;a href="#%e9%80%9a%e8%bf%87-odpobproxy%e9%bb%98%e8%ae%a4%e7%ab%af%e5%8f%a3%e5%b8%b8%e4%b8%ba-2883" class="header-anchor"&gt;&lt;/a&gt;通过 ODP/OBProxy（默认端口常为 2883）
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h&amp;lt;odp_ip&amp;gt; -P2883 -u用户名@租户名#集群名 -p
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;用户名还可能写成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;集群名:租户名:用户名&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;集群名-租户名-用户名&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;集群名.租户名.用户名&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这和 MySQL 的 &lt;code&gt;root@'%'&lt;/code&gt; 完全不是同一套语义。&lt;/p&gt;
&lt;h3 id="3-客户端选择"&gt;&lt;a href="#3-%e5%ae%a2%e6%88%b7%e7%ab%af%e9%80%89%e6%8b%a9" class="header-anchor"&gt;&lt;/a&gt;3. 客户端选择
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;可用 &lt;code&gt;obclient&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;也可用 MySQL 客户端连接 MySQL 模式租户&lt;br&gt;
官方文档提到当前支持的 MySQL 客户端版本包括 5.5 / 5.6 / 5.7（以你使用版本的文档为准）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="六从零上手mysql-同学-10-分钟路径"&gt;&lt;a href="#%e5%85%ad%e4%bb%8e%e9%9b%b6%e4%b8%8a%e6%89%8bmysql-%e5%90%8c%e5%ad%a6-10-%e5%88%86%e9%92%9f%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;六、从零上手：MySQL 同学 10 分钟路径
&lt;/h2&gt;&lt;p&gt;下面假设你已经能连上一个 MySQL 模式租户。&lt;/p&gt;
&lt;h3 id="1-看有哪些库"&gt;&lt;a href="#1-%e7%9c%8b%e6%9c%89%e5%93%aa%e4%ba%9b%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;1. 看有哪些库
&lt;/h3&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATABASES&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;体验环境里常见会看到 &lt;code&gt;oceanbase&lt;/code&gt;、&lt;code&gt;test&lt;/code&gt;、&lt;code&gt;information_schema&lt;/code&gt;、&lt;code&gt;mysql&lt;/code&gt; 等。&lt;/p&gt;
&lt;h3 id="2-创建业务库"&gt;&lt;a href="#2-%e5%88%9b%e5%bb%ba%e4%b8%9a%e5%8a%a1%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;2. 创建业务库
&lt;/h3&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATABASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;CHARACTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utf8mb4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WRITE&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;USE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo&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;这和 MySQL 非常像。&lt;/p&gt;
&lt;h3 id="3-建表写入查询"&gt;&lt;a href="#3-%e5%bb%ba%e8%a1%a8%e5%86%99%e5%85%a5%e6%9f%a5%e8%af%a2" class="header-anchor"&gt;&lt;/a&gt;3. 建表、写入、查询
&lt;/h3&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATETIME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CURRENT_TIMESTAMP&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="p"&gt;);&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="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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&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="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&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="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bob&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;span class="line"&gt;&lt;span class="cl"&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;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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&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="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;alice2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;DELETE&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;2&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;官方 MySQL 模式基础文档也覆盖了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CREATE DATABASE&lt;/code&gt; / &lt;code&gt;SHOW DATABASES&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt; / &lt;code&gt;SHOW TABLES&lt;/code&gt; / &lt;code&gt;SHOW CREATE TABLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ALTER TABLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INSERT&lt;/code&gt; / &lt;code&gt;UPDATE&lt;/code&gt; / &lt;code&gt;DELETE&lt;/code&gt; / &lt;code&gt;TRUNCATE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;多表查询、聚合、&lt;code&gt;EXPLAIN&lt;/code&gt; 等&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-看建表细节时的oceanbase-味道"&gt;&lt;a href="#4-%e7%9c%8b%e5%bb%ba%e8%a1%a8%e7%bb%86%e8%8a%82%e6%97%b6%e7%9a%84oceanbase-%e5%91%b3%e9%81%93" class="header-anchor"&gt;&lt;/a&gt;4. 看建表细节时的“OceanBase 味道”
&lt;/h3&gt;&lt;p&gt;在 OceanBase 里执行：&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;G&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;你可能会看到比 MySQL 更“重”的表属性，例如副本数、压缩、Tablet 相关参数等。&lt;br&gt;
这说明：&lt;strong&gt;SQL 表面兼容，元数据与存储参数并不等同于 InnoDB。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="七兼容性像-mysql但不是-100-mysql"&gt;&lt;a href="#%e4%b8%83%e5%85%bc%e5%ae%b9%e6%80%a7%e5%83%8f-mysql%e4%bd%86%e4%b8%8d%e6%98%af-100-mysql" class="header-anchor"&gt;&lt;/a&gt;七、兼容性：像 MySQL，但不是 100% MySQL
&lt;/h2&gt;&lt;p&gt;官方《与 MySQL 兼容性对比》说明：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;OceanBase 的 MySQL 模式兼容 MySQL 5.7/8.0 的&lt;strong&gt;绝大部分&lt;/strong&gt;功能和语法；因架构差异或需求优先级，部分功能未支持。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="1-相似度高的部分"&gt;&lt;a href="#1-%e7%9b%b8%e4%bc%bc%e5%ba%a6%e9%ab%98%e7%9a%84%e9%83%a8%e5%88%86" class="header-anchor"&gt;&lt;/a&gt;1. 相似度高的部分
&lt;/h3&gt;&lt;p&gt;通常对应用最友好的部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常见数值 / 时间 / 字符 / JSON 等数据类型&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT&lt;/code&gt; / &lt;code&gt;INSERT&lt;/code&gt; / &lt;code&gt;UPDATE&lt;/code&gt; / &lt;code&gt;DELETE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;多表连接、子查询、聚合分组&lt;/li&gt;
&lt;li&gt;存储过程、函数、触发器等大部分 PL 能力&lt;/li&gt;
&lt;li&gt;&lt;code&gt;information_schema&lt;/code&gt;、&lt;code&gt;mysql&lt;/code&gt; 中的大量视图（但不是逐列完全等价）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;很多基于 MySQL 协议的驱动可直接连&lt;/li&gt;
&lt;li&gt;简单 CRUD 业务迁移门槛较低&lt;/li&gt;
&lt;li&gt;你会有“这不就是 MySQL 吗”的错觉&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-必须注意的差异"&gt;&lt;a href="#2-%e5%bf%85%e9%a1%bb%e6%b3%a8%e6%84%8f%e7%9a%84%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;2. 必须注意的差异
&lt;/h3&gt;&lt;p&gt;官方明确提到的差异方向包括：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;类别&lt;/th&gt;
					&lt;th&gt;差异点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL 语法&lt;/td&gt;
					&lt;td&gt;例如不支持 &lt;code&gt;SELECT ... FOR SHARE ...&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TRUNCATE&lt;/td&gt;
					&lt;td&gt;不支持在事务处理与表锁定过程中操作&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;系统视图&lt;/td&gt;
					&lt;td&gt;不保证所有视图/列含义都与 MySQL 相同&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;存储引擎&lt;/td&gt;
					&lt;td&gt;不是 InnoDB 插件体系，而是自研分布式存储事务体系&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;优化器&lt;/td&gt;
					&lt;td&gt;执行计划与优化策略不同&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;分区 / 备份恢复&lt;/td&gt;
					&lt;td&gt;能力模型与操作路径不同&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;架构相关功能&lt;/td&gt;
					&lt;td&gt;因分布式架构，部分单机 MySQL 习惯不能照搬&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="3-实战迁移建议"&gt;&lt;a href="#3-%e5%ae%9e%e6%88%98%e8%bf%81%e7%a7%bb%e5%bb%ba%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;3. 实战迁移建议
&lt;/h3&gt;&lt;p&gt;从 MySQL 迁到 OceanBase 时，不要只做“能不能连上”：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先验证协议层&lt;/strong&gt;：驱动、连接池、ORM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再验证 SQL 层&lt;/strong&gt;：慢 SQL、锁、事务边界、分页、HINT&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再验证运维层&lt;/strong&gt;：备份恢复、监控指标、扩缩容、租户资源&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后验证边界语法&lt;/strong&gt;：冷门函数、系统表、复制相关特性、特定锁语法&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;一句话：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;兼容的是“MySQL 使用体验”，不是“MySQL 内核实现”。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="八对象模型对比database-相同边界不同"&gt;&lt;a href="#%e5%85%ab%e5%af%b9%e8%b1%a1%e6%a8%a1%e5%9e%8b%e5%af%b9%e6%af%94database-%e7%9b%b8%e5%90%8c%e8%be%b9%e7%95%8c%e4%b8%8d%e5%90%8c" class="header-anchor"&gt;&lt;/a&gt;八、对象模型对比：database 相同，边界不同
&lt;/h2&gt;&lt;h3 id="mysql"&gt;&lt;a href="#mysql" class="header-anchor"&gt;&lt;/a&gt;MySQL
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Instance
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Database
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Table / View / Procedure
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;权限、连接、资源，常常都围绕“实例 + 账号”展开。&lt;/p&gt;
&lt;h3 id="oceanbase"&gt;&lt;a href="#oceanbase" class="header-anchor"&gt;&lt;/a&gt;OceanBase
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Tenant（资源与权限边界更强）
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Database
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── Table / Index / Procedure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── sys 租户（集群元数据）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对 MySQL 同学最实用的迁移记忆：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;你在 MySQL 想做的事&lt;/th&gt;
					&lt;th&gt;在 OceanBase 更常见的对应&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;新建一个业务实例&lt;/td&gt;
					&lt;td&gt;新建一个业务租户&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;在实例里建库&lt;/td&gt;
					&lt;td&gt;在租户里 &lt;code&gt;CREATE DATABASE&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;给业务分配 CPU/内存&lt;/td&gt;
					&lt;td&gt;调整 Unit Config / Resource Pool&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;连业务库&lt;/td&gt;
					&lt;td&gt;连 &lt;code&gt;user@tenant&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;做高可用&lt;/td&gt;
					&lt;td&gt;规划 Zone / 副本 / 主备切换，而不是只配主从&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="九一个最小对比实验帮助真正理解差异"&gt;&lt;a href="#%e4%b9%9d%e4%b8%80%e4%b8%aa%e6%9c%80%e5%b0%8f%e5%af%b9%e6%af%94%e5%ae%9e%e9%aa%8c%e5%b8%ae%e5%8a%a9%e7%9c%9f%e6%ad%a3%e7%90%86%e8%a7%a3%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;九、一个最小对比实验（帮助真正理解差异）
&lt;/h2&gt;&lt;h3 id="实验-a同一套-crud"&gt;&lt;a href="#%e5%ae%9e%e9%aa%8c-a%e5%90%8c%e4%b8%80%e5%a5%97-crud" class="header-anchor"&gt;&lt;/a&gt;实验 A：同一套 CRUD
&lt;/h3&gt;&lt;p&gt;在 OceanBase MySQL 模式租户执行：&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATABASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;CHARACTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utf8mb4&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;USE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shop&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;span class="line"&gt;&lt;span class="cl"&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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="p"&gt;);&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="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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&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="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;PAID&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;CREATED&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;span class="line"&gt;&lt;span class="cl"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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;PAID&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;你会发现：&lt;br&gt;
&lt;strong&gt;如果只看 SQL，这和 MySQL 几乎没区别。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="实验-b连接串差异"&gt;&lt;a href="#%e5%ae%9e%e9%aa%8c-b%e8%bf%9e%e6%8e%a5%e4%b8%b2%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;实验 B：连接串差异
&lt;/h3&gt;&lt;p&gt;MySQL：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P3306 -uroot -p shop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OceanBase 直连某租户：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot@test -p shop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OceanBase 经 ODP：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2883 -uroot@test#cluster_name -p shop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;你会发现：&lt;br&gt;
&lt;strong&gt;真正拉开差距的，是“你连到了哪里”和“资源边界在哪里”。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="实验-c多租户隔离"&gt;&lt;a href="#%e5%ae%9e%e9%aa%8c-c%e5%a4%9a%e7%a7%9f%e6%88%b7%e9%9a%94%e7%a6%bb" class="header-anchor"&gt;&lt;/a&gt;实验 C：多租户隔离
&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;sys&lt;/code&gt; 中创建两个业务租户后：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;root@tenant1&lt;/code&gt; 里建表&lt;/li&gt;
&lt;li&gt;&lt;code&gt;root@tenant2&lt;/code&gt; 里看不到那张表&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;官方多租户示例正是用这种方式证明：&lt;br&gt;
&lt;strong&gt;租户之间资源、数据、权限隔离。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这比 MySQL 里“两个 database 互相授权”要更接近“两个实例”。&lt;/p&gt;
&lt;h2 id="十什么时候适合用-oceanbase什么时候继续-mysql"&gt;&lt;a href="#%e5%8d%81%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e9%80%82%e5%90%88%e7%94%a8-oceanbase%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e7%bb%a7%e7%bb%ad-mysql" class="header-anchor"&gt;&lt;/a&gt;十、什么时候适合用 OceanBase，什么时候继续 MySQL
&lt;/h2&gt;&lt;h3 id="更适合考虑-oceanbase-的场景"&gt;&lt;a href="#%e6%9b%b4%e9%80%82%e5%90%88%e8%80%83%e8%99%91-oceanbase-%e7%9a%84%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;更适合考虑 OceanBase 的场景
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;需要水平扩展，单机 MySQL + 分库分表成本高&lt;/li&gt;
&lt;li&gt;需要更强的金融级高可用与多副本一致性&lt;/li&gt;
&lt;li&gt;希望一套系统兼顾 TP 与部分 AP&lt;/li&gt;
&lt;li&gt;多业务要强隔离，但又想统一运维平台（多租户）&lt;/li&gt;
&lt;li&gt;已有大量 MySQL 协议应用，希望降低改造成本&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="更适合继续-mysql-的场景"&gt;&lt;a href="#%e6%9b%b4%e9%80%82%e5%90%88%e7%bb%a7%e7%bb%ad-mysql-%e7%9a%84%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;更适合继续 MySQL 的场景
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;单机或轻量业务，数据量和可用性要求不高&lt;/li&gt;
&lt;li&gt;团队只熟悉传统 mysqld 运维，短期不想引入分布式复杂度&lt;/li&gt;
&lt;li&gt;深度依赖某些 MySQL 专有行为 / 插件 / 生态工具且未验证兼容&lt;/li&gt;
&lt;li&gt;本地开发只需要极轻量依赖（虽然也可用 OceanBase Docker，但 MySQL 更轻）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="十一学习路线建议"&gt;&lt;a href="#%e5%8d%81%e4%b8%80%e5%ad%a6%e4%b9%a0%e8%b7%af%e7%ba%bf%e5%bb%ba%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;十一、学习路线建议
&lt;/h2&gt;&lt;p&gt;如果你是 MySQL 背景，建议按这个顺序学：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先跑起来&lt;/strong&gt;：Docker / &lt;code&gt;obd demo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先会连&lt;/strong&gt;：&lt;code&gt;user@tenant&lt;/code&gt;、&lt;code&gt;2881&lt;/code&gt; / &lt;code&gt;2883&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先当 MySQL 用&lt;/strong&gt;：建库建表 CRUD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再学租户与资源&lt;/strong&gt;：Unit / Resource Pool / sys 与普通租户&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;再学分布式&lt;/strong&gt;：分区、副本、Zone、OBProxy 路由&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最后做迁移评估&lt;/strong&gt;：兼容性清单 + 压测 + 备份恢复演练&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;配套阅读：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;本站另一篇：&lt;a class="link" href="https://blog.waihost.com/posts/oceanbase-multi-platform-setup-guide/" &gt;OceanBase 多平台搭建教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;官方 MySQL 兼容性文档&lt;/li&gt;
&lt;li&gt;官方系统架构与多租户文档&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="十二速查对照表"&gt;&lt;a href="#%e5%8d%81%e4%ba%8c%e9%80%9f%e6%9f%a5%e5%af%b9%e7%85%a7%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;十二、速查对照表
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;主题&lt;/th&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;OceanBase&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;默认连接&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;root@host:3306&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;root@tenant@host:2881&lt;/code&gt; 或经 ODP &lt;code&gt;2883&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;业务隔离&lt;/td&gt;
					&lt;td&gt;database / 多实例&lt;/td&gt;
					&lt;td&gt;tenant&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;管理入口&lt;/td&gt;
					&lt;td&gt;实例管理员&lt;/td&gt;
					&lt;td&gt;常先登 &lt;code&gt;sys&lt;/code&gt; 做集群与租户管理&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;扩展&lt;/td&gt;
					&lt;td&gt;加配 / 分库分表&lt;/td&gt;
					&lt;td&gt;分区 + 多节点 + 资源单元&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;高可用&lt;/td&gt;
					&lt;td&gt;复制拓扑&lt;/td&gt;
					&lt;td&gt;Multi-Paxos 多副本&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL 习惯&lt;/td&gt;
					&lt;td&gt;原生 MySQL&lt;/td&gt;
					&lt;td&gt;高度兼容，但要做差异验证&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;社区版模式&lt;/td&gt;
					&lt;td&gt;MySQL&lt;/td&gt;
					&lt;td&gt;仅 MySQL 模式&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;OceanBase 对 MySQL 同学并不“难在 SQL”，而难在&lt;strong&gt;换模型&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把“实例”理解升级成“集群 + 租户”&lt;/li&gt;
&lt;li&gt;把“连上 mysqld”升级成“连上正确的租户入口”&lt;/li&gt;
&lt;li&gt;把“兼容 MySQL”理解成“协议与常用 SQL 友好，不等于内核相同”&lt;/li&gt;
&lt;li&gt;先用 CRUD 建立信心，再用租户、分区、副本理解它的分布式能力&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;掌握这四步后，你就不会再把 OceanBase 误当成“换了皮的 MySQL”，也能更准确判断它该用在什么地方。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;OceanBase 官方仓库 README（中英文，MySQL 兼容与快速开始）：https://github.com/oceanbase/oceanbase&lt;/li&gt;
&lt;li&gt;OceanBase 官方文档：系统架构（&lt;code&gt;oceanbase-doc&lt;/code&gt; / V4.3.5）&lt;/li&gt;
&lt;li&gt;OceanBase 官方文档：与 MySQL 兼容性对比&lt;/li&gt;
&lt;li&gt;OceanBase 官方文档：SQL 基础操作（MySQL 模式）&lt;/li&gt;
&lt;li&gt;OceanBase 官方文档：体验多租户特性&lt;/li&gt;
&lt;li&gt;OceanBase 官方文档：通过 MySQL 客户端连接 OceanBase 租户&lt;/li&gt;
&lt;li&gt;OceanBase Docker 镜像：https://hub.docker.com/r/oceanbase/oceanbase-ce&lt;/li&gt;
&lt;li&gt;OceanBase 中文文档中心：https://www.oceanbase.com/docs/oceanbase-database-cn&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>OceanBase 多平台搭建教程：Linux / Windows / macOS / Docker 从零到可连接</title><link>https://blog.waihost.com/posts/oceanbase-multi-platform-setup-guide/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/oceanbase-multi-platform-setup-guide/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/oceanbase-multi-platform-setup-guide.svg" alt="Featured image of post OceanBase 多平台搭建教程：Linux / Windows / macOS / Docker 从零到可连接" /&gt;&lt;p&gt;OceanBase 是蚂蚁集团开源的分布式关系型数据库，兼容 MySQL 协议，适合本地体验、开发联调与集群试验。很多人第一次上手时最困惑的不是“它强在哪”，而是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;我在 Linux / Windows / macOS 上，到底该用哪一种方式装？&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;本文按官方社区推荐路径，整理一套可复用的多平台搭建方法：优先讲&lt;strong&gt;最快跑起来&lt;/strong&gt;，再讲&lt;strong&gt;更接近生产部署&lt;/strong&gt;的方式，并给出连接验证与常见排错。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;说明：本文以 &lt;strong&gt;OceanBase 社区版（CE）&lt;/strong&gt; 的官方开源安装路径为主，面向学习与开发环境。官方 Docker 镜像明确标注&lt;strong&gt;仅供测试，不建议直接用于生产&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="一先选对安装路径"&gt;&lt;a href="#%e4%b8%80%e5%85%88%e9%80%89%e5%af%b9%e5%ae%89%e8%a3%85%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;一、先选对安装路径
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;平台&lt;/th&gt;
					&lt;th&gt;最推荐方式&lt;/th&gt;
					&lt;th&gt;备选方式&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Linux&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;all-in-one&lt;/code&gt; + &lt;code&gt;obd demo&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Docker / OBD 自定义集群&lt;/td&gt;
					&lt;td&gt;官方 all-in-one &lt;strong&gt;仅支持 Linux&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;macOS&lt;/td&gt;
					&lt;td&gt;Docker Desktop + &lt;code&gt;oceanbase-ce&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;远程 Linux 开发机&lt;/td&gt;
					&lt;td&gt;本机不建议硬编译 observer 当第一选择&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Windows&lt;/td&gt;
					&lt;td&gt;Docker Desktop&lt;/td&gt;
					&lt;td&gt;WSL2 + Linux 方案&lt;/td&gt;
					&lt;td&gt;原生 Windows 不适合当主路径&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;任意平台（快速体验）&lt;/td&gt;
					&lt;td&gt;Docker &lt;code&gt;oceanbase/oceanbase-ce&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;quay.io / ghcr.io 镜像源&lt;/td&gt;
					&lt;td&gt;单实例、端口 &lt;code&gt;2881&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Kubernetes&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ob-operator&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;—&lt;/td&gt;
					&lt;td&gt;容器化生产/类生产集群请走 operator&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="资源底线很重要"&gt;&lt;a href="#%e8%b5%84%e6%ba%90%e5%ba%95%e7%ba%bf%e5%be%88%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;资源底线（很重要）
&lt;/h3&gt;&lt;p&gt;不同路径对资源要求不同，至少记住两档：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Docker 官方镜像（测试）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;主机建议至少 &lt;strong&gt;2 物理核 + 8GB 内存&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;obd demo&lt;/code&gt; 本地单节点&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;至少 &lt;strong&gt;2 CPU、6GB 可用内存、54GB 可用磁盘&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;端口 &lt;strong&gt;2881 / 2882&lt;/strong&gt; 未被占用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;机器太小会导致 bootstrap 卡住、容器反复重启，看起来像“命令写错了”，其实是资源不足。&lt;/p&gt;
&lt;h2 id="二通用概念端口租户客户端"&gt;&lt;a href="#%e4%ba%8c%e9%80%9a%e7%94%a8%e6%a6%82%e5%bf%b5%e7%ab%af%e5%8f%a3%e7%a7%9f%e6%88%b7%e5%ae%a2%e6%88%b7%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;二、通用概念：端口、租户、客户端
&lt;/h2&gt;&lt;p&gt;搭好后，通常这样连接：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;项目&lt;/th&gt;
					&lt;th&gt;常见值&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;协议&lt;/td&gt;
					&lt;td&gt;MySQL 兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL 端口&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;2881&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;系统租户&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sys&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;示例业务租户&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;test&lt;/code&gt;（Docker 镜像常见）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;客户端&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;obclient&lt;/code&gt; 或标准 &lt;code&gt;mysql&lt;/code&gt; 客户端&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;常用连接示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 系统租户 root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 普通租户 root（Docker 文档示例）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot@test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果你本机没有 &lt;code&gt;mysql&lt;/code&gt; 客户端，可用容器内置客户端：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="三最快路径dockerlinux--windows--macos-通用"&gt;&lt;a href="#%e4%b8%89%e6%9c%80%e5%bf%ab%e8%b7%af%e5%be%84dockerlinux--windows--macos-%e9%80%9a%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;三、最快路径：Docker（Linux / Windows / macOS 通用）
&lt;/h2&gt;&lt;p&gt;这是跨平台体验 OceanBase &lt;strong&gt;最省事&lt;/strong&gt;的方式。&lt;br&gt;
官方提供镜像：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker Hub：&lt;code&gt;oceanbase/oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;备选：&lt;code&gt;quay.io/oceanbase/oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;备选：&lt;code&gt;ghcr.io/oceanbase/oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;官方说明：该镜像用于&lt;strong&gt;快速搭建测试环境&lt;/strong&gt;，只支持&lt;strong&gt;单实例&lt;/strong&gt;；若在 Kubernetes 中运行，请改用 &lt;code&gt;ob-operator&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="1-前置条件"&gt;&lt;a href="#1-%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;1. 前置条件
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;已安装并可运行 Docker（Linux Docker Engine / Docker Desktop）&lt;/li&gt;
&lt;li&gt;主机资源满足：约 2 核 + 8GB 内存&lt;/li&gt;
&lt;li&gt;本机 &lt;code&gt;2881&lt;/code&gt; 端口空闲&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-启动实例"&gt;&lt;a href="#2-%e5%90%af%e5%8a%a8%e5%ae%9e%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;2. 启动实例
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mini 模式：适合快速体验（官方 README 推荐写法）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker Hub 文档还给出了其他模式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用容器更多资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;normal -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# slim / fastboot 模式&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;slim -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;若 Docker Hub 拉取慢，可切换镜像源：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d quay.io/oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d ghcr.io/oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-等待-bootstrap-完成"&gt;&lt;a href="#3-%e7%ad%89%e5%be%85-bootstrap-%e5%ae%8c%e6%88%90" class="header-anchor"&gt;&lt;/a&gt;3. 等待 bootstrap 完成
&lt;/h3&gt;&lt;p&gt;首次启动可能需要几分钟。查看日志末尾：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker logs oceanbase-ce &lt;span class="p"&gt;|&lt;/span&gt; tail -1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;期望看到：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;boot success!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-连接验证"&gt;&lt;a href="#4-%e8%bf%9e%e6%8e%a5%e9%aa%8c%e8%af%81" class="header-anchor"&gt;&lt;/a&gt;4. 连接验证
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 方式 A：容器内客户端&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 方式 B：宿主机 mysql 客户端&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P2881 -uroot@test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DATABASES&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;version&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;h3 id="5-常用运维命令"&gt;&lt;a href="#5-%e5%b8%b8%e7%94%a8%e8%bf%90%e7%bb%b4%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;&lt;/a&gt;5. 常用运维命令
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker ps -a &lt;span class="p"&gt;|&lt;/span&gt; grep oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker logs -f oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker restart oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker stop oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker rm -f oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="6-初始化-sql可选"&gt;&lt;a href="#6-%e5%88%9d%e5%a7%8b%e5%8c%96-sql%e5%8f%af%e9%80%89" class="header-anchor"&gt;&lt;/a&gt;6. 初始化 SQL（可选）
&lt;/h3&gt;&lt;p&gt;官方镜像支持挂载初始化脚本目录：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /path/to/init-sql:/root/boot/init.d &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：官方文档提醒，初始化脚本中&lt;strong&gt;不要直接改 root 密码&lt;/strong&gt;；若要改密码，应使用镜像提供的环境变量（如 &lt;code&gt;OB_TENANT_PASSWORD&lt;/code&gt;，以当前镜像说明为准）。&lt;/p&gt;
&lt;h2 id="四linux-原生all-in-one--obd官方推荐体验路径"&gt;&lt;a href="#%e5%9b%9blinux-%e5%8e%9f%e7%94%9fall-in-one--obd%e5%ae%98%e6%96%b9%e6%8e%a8%e8%8d%90%e4%bd%93%e9%aa%8c%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;四、Linux 原生：all-in-one + OBD（官方推荐体验路径）
&lt;/h2&gt;&lt;p&gt;如果你有一台 Linux 服务器或虚拟机，想更接近“真集群工具链”，优先用官方 &lt;strong&gt;all-in-one&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="1-一键安装-all-in-one"&gt;&lt;a href="#1-%e4%b8%80%e9%94%ae%e5%ae%89%e8%a3%85-all-in-one" class="header-anchor"&gt;&lt;/a&gt;1. 一键安装 all-in-one
&lt;/h3&gt;&lt;p&gt;官方 README 明确：&lt;strong&gt;仅 Linux&lt;/strong&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 需要能访问外网&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash -c &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -s https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/download-center/opensource/oceanbase-all-in-one/installer.sh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.oceanbase-all-in-one/bin/env.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-一键拉起演示实例"&gt;&lt;a href="#2-%e4%b8%80%e9%94%ae%e6%8b%89%e8%b5%b7%e6%bc%94%e7%a4%ba%e5%ae%9e%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;2. 一键拉起演示实例
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obd demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;obd demo&lt;/code&gt; 会在本机部署并启动一个 OceanBase 实例。部署完成后：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obclient -h127.0.0.1 -uroot -P2881
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-单独安装-obdcentosrhel-系"&gt;&lt;a href="#3-%e5%8d%95%e7%8b%ac%e5%ae%89%e8%a3%85-obdcentosrhel-%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;3. 单独安装 OBD（CentOS/RHEL 系）
&lt;/h3&gt;&lt;p&gt;如果你不走 all-in-one，也可以单独装 OceanBase Deployer：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y yum-utils
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y ob-deploy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /etc/profile.d/obd.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后同样可用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obd demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-obd-demo-前自检清单"&gt;&lt;a href="#4-obd-demo-%e5%89%8d%e8%87%aa%e6%a3%80%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;4. &lt;code&gt;obd demo&lt;/code&gt; 前自检清单
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;端口 &lt;code&gt;2881&lt;/code&gt;、&lt;code&gt;2882&lt;/code&gt; 空闲&lt;/li&gt;
&lt;li&gt;可用内存 ≥ 6GB&lt;/li&gt;
&lt;li&gt;CPU ≥ 2&lt;/li&gt;
&lt;li&gt;可用磁盘 ≥ 54GB&lt;/li&gt;
&lt;li&gt;系统时间正常、主机名可解析&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;资源不够时，OBD 往往会在预检阶段失败；先把机器规格补齐再重试，比反复改 YAML 更有效。&lt;/p&gt;
&lt;h2 id="五windows-搭建"&gt;&lt;a href="#%e4%ba%94windows-%e6%90%ad%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;五、Windows 搭建
&lt;/h2&gt;&lt;p&gt;Windows 原生不适合作为 OceanBase observer 主部署平台。实操建议两条路：&lt;/p&gt;
&lt;h3 id="方案-adocker-desktop最简单"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-adocker-desktop%e6%9c%80%e7%ae%80%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;方案 A：Docker Desktop（最简单）
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;安装 &lt;a class="link" href="https://docs.docker.com/desktop/" target="_blank" rel="noopener"
 &gt;Docker Desktop for Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;确保 WSL2 后端已启用（Docker Desktop 默认推荐）&lt;/li&gt;
&lt;li&gt;在 PowerShell / Windows Terminal 执行：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;-p&lt;/span&gt; &lt;span class="mf"&gt;2881&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2881&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;-name&lt;/span&gt; &lt;span class="nb"&gt;oceanbase-ce&lt;/span&gt; &lt;span class="n"&gt;-e&lt;/span&gt; &lt;span class="n"&gt;MODE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mini&lt;/span&gt; &lt;span class="n"&gt;-d&lt;/span&gt; &lt;span class="n"&gt;oceanbase&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;oceanbase-ce&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="nb"&gt;oceanbase-ce&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="4"&gt;
&lt;li&gt;看到 &lt;code&gt;boot success!&lt;/code&gt; 后连接：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;-it&lt;/span&gt; &lt;span class="nb"&gt;oceanbase-ce&lt;/span&gt; &lt;span class="n"&gt;obclient&lt;/span&gt; &lt;span class="n"&gt;-h127&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;1&lt;/span&gt; &lt;span class="n"&gt;-P2881&lt;/span&gt; &lt;span class="n"&gt;-uroot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Windows 上若本机没有 mysql 客户端，优先用容器内 &lt;code&gt;obclient&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="方案-bwsl2--linux-路径"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-bwsl2--linux-%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;方案 B：WSL2 + Linux 路径
&lt;/h3&gt;&lt;p&gt;适合希望练习 &lt;code&gt;obd&lt;/code&gt; / all-in-one 的同学：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安装 WSL2 与 Ubuntu（或其他受支持发行版）&lt;/li&gt;
&lt;li&gt;给 WSL 分配足够内存（建议在 &lt;code&gt;.wslconfig&lt;/code&gt; 中提高 memory）&lt;/li&gt;
&lt;li&gt;在 WSL 内按上文 &lt;strong&gt;Linux all-in-one / Docker&lt;/strong&gt; 步骤执行&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注意：WSL 的磁盘 I/O 与内存限制会影响 bootstrap 时间，尽量把数据放在 Linux 文件系统内，不要跨挂载到很慢的 Windows 目录。&lt;/p&gt;
&lt;h2 id="六macos-搭建"&gt;&lt;a href="#%e5%85%admacos-%e6%90%ad%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;六、macOS 搭建
&lt;/h2&gt;&lt;p&gt;macOS 上同样优先 Docker：&lt;/p&gt;
&lt;h3 id="1-安装-docker-desktop-for-mac"&gt;&lt;a href="#1-%e5%ae%89%e8%a3%85-docker-desktop-for-mac" class="header-anchor"&gt;&lt;/a&gt;1. 安装 Docker Desktop for Mac
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Intel / Apple Silicon 都可使用 Docker Desktop&lt;/li&gt;
&lt;li&gt;在 Docker Desktop → Settings → Resources 中给足 CPU/内存（建议 ≥ 2 CPU、8GB）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-启动-oceanbase"&gt;&lt;a href="#2-%e5%90%af%e5%8a%a8-oceanbase" class="header-anchor"&gt;&lt;/a&gt;2. 启动 OceanBase
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;拉取慢时可换：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d ghcr.io/oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-连接"&gt;&lt;a href="#3-%e8%bf%9e%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;3. 连接
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-macos-特别提醒"&gt;&lt;a href="#4-macos-%e7%89%b9%e5%88%ab%e6%8f%90%e9%86%92" class="header-anchor"&gt;&lt;/a&gt;4. macOS 特别提醒
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;官方 &lt;strong&gt;all-in-one 标注 Linux Only&lt;/strong&gt;，不要在 macOS 上硬套那条 installer 当主路径&lt;/li&gt;
&lt;li&gt;Apple Silicon 上若镜像/依赖偶发兼容问题，优先换官方备用镜像源，或使用远程 Linux 机器做部署练习&lt;/li&gt;
&lt;li&gt;开发联调可把应用跑在 macOS，数据库跑在 Docker 容器；应用连接 &lt;code&gt;127.0.0.1:2881&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="七进阶kubernetes-与多节点"&gt;&lt;a href="#%e4%b8%83%e8%bf%9b%e9%98%b6kubernetes-%e4%b8%8e%e5%a4%9a%e8%8a%82%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;七、进阶：Kubernetes 与多节点
&lt;/h2&gt;&lt;p&gt;当你已经不满足“本机单实例体验”，可以往这两类走：&lt;/p&gt;
&lt;h3 id="1-kubernetesob-operator"&gt;&lt;a href="#1-kubernetesob-operator" class="header-anchor"&gt;&lt;/a&gt;1. Kubernetes：&lt;code&gt;ob-operator&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;官方 README 推荐使用 &lt;a class="link" href="https://github.com/oceanbase/ob-operator" target="_blank" rel="noopener"
 &gt;ob-operator&lt;/a&gt; 在 K8s 中部署管理 OceanBase。&lt;br&gt;
适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想练容器化运维&lt;/li&gt;
&lt;li&gt;需要更接近云原生的生命周期管理&lt;/li&gt;
&lt;li&gt;本地 kind/k3s/自建集群实验&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;快速入口见：https://oceanbase.github.io/ob-operator&lt;/p&gt;
&lt;h3 id="2-obd-自定义集群"&gt;&lt;a href="#2-obd-%e8%87%aa%e5%ae%9a%e4%b9%89%e9%9b%86%e7%be%a4" class="header-anchor"&gt;&lt;/a&gt;2. OBD 自定义集群
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;obd demo&lt;/code&gt; 只是快速单机演示。真正做多副本/多节点时，应使用 OBD 的集群配置与命令组（镜像仓库、集群启停、升级等）。&lt;br&gt;
这已经超出“第一次搭起来”的范围，但方向应是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先用 Docker / &lt;code&gt;obd demo&lt;/code&gt; 跑通连接&lt;/li&gt;
&lt;li&gt;再学 OBD 配置文件与集群拓扑&lt;/li&gt;
&lt;li&gt;最后再上 K8s operator&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="八连接后的最小验收清单"&gt;&lt;a href="#%e5%85%ab%e8%bf%9e%e6%8e%a5%e5%90%8e%e7%9a%84%e6%9c%80%e5%b0%8f%e9%aa%8c%e6%94%b6%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&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="c1"&gt;-- 1. 能登录
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 2. 看版本信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;version&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 3. 建库建表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATABASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;USE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;demo&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;oceanbase&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&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;宿主机侧再确认：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 端口监听&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ss -lntp &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="m"&gt;2881&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lsof -iTCP:2881 -sTCP:LISTEN
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="九常见问题排查"&gt;&lt;a href="#%e4%b9%9d%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e6%8e%92%e6%9f%a5" class="header-anchor"&gt;&lt;/a&gt;九、常见问题排查
&lt;/h2&gt;&lt;h3 id="1-容器一直起不来--没有-boot-success"&gt;&lt;a href="#1-%e5%ae%b9%e5%99%a8%e4%b8%80%e7%9b%b4%e8%b5%b7%e4%b8%8d%e6%9d%a5--%e6%b2%a1%e6%9c%89-boot-success" class="header-anchor"&gt;&lt;/a&gt;1. 容器一直起不来 / 没有 &lt;code&gt;boot success!&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;优先检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内存是否低于 8GB（Docker 场景）&lt;/li&gt;
&lt;li&gt;磁盘是否紧张&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker logs oceanbase-ce&lt;/code&gt; 是否有 OOM / 权限 / 存储错误&lt;/li&gt;
&lt;li&gt;是否重复占用容器名 &lt;code&gt;oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;处理：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker rm -f oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-2881-端口冲突"&gt;&lt;a href="#2-2881-%e7%ab%af%e5%8f%a3%e5%86%b2%e7%aa%81" class="header-anchor"&gt;&lt;/a&gt;2. &lt;code&gt;2881&lt;/code&gt; 端口冲突
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 换宿主机端口映射，例如 12881 -&amp;gt; 2881&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 12881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysql -h127.0.0.1 -P12881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-docker-hub-拉取失败"&gt;&lt;a href="#3-docker-hub-%e6%8b%89%e5%8f%96%e5%a4%b1%e8%b4%a5" class="header-anchor"&gt;&lt;/a&gt;3. Docker Hub 拉取失败
&lt;/h3&gt;&lt;p&gt;依次尝试：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;quay.io/oceanbase/oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ghcr.io/oceanbase/oceanbase-ce&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;配置可用的镜像加速 / 代理&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="4-能进容器但不能从宿主机连接"&gt;&lt;a href="#4-%e8%83%bd%e8%bf%9b%e5%ae%b9%e5%99%a8%e4%bd%86%e4%b8%8d%e8%83%bd%e4%bb%8e%e5%ae%bf%e4%b8%bb%e6%9c%ba%e8%bf%9e%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;4. 能进容器但不能从宿主机连接
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;确认 &lt;code&gt;-p 2881:2881&lt;/code&gt; 已映射&lt;/li&gt;
&lt;li&gt;Windows/macOS 确认 Docker Desktop 正在运行&lt;/li&gt;
&lt;li&gt;云服务器还要放行安全组/防火墙入站规则&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-obd-demo-预检失败"&gt;&lt;a href="#5-obd-demo-%e9%a2%84%e6%a3%80%e5%a4%b1%e8%b4%a5" class="header-anchor"&gt;&lt;/a&gt;5. &lt;code&gt;obd demo&lt;/code&gt; 预检失败
&lt;/h3&gt;&lt;p&gt;对照官方条件逐项查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内存、CPU、磁盘是否达标&lt;/li&gt;
&lt;li&gt;2881/2882 是否被占用&lt;/li&gt;
&lt;li&gt;是否在非 Linux 环境误跑 all-in-one&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="十平台选型建议实战版"&gt;&lt;a href="#%e5%8d%81%e5%b9%b3%e5%8f%b0%e9%80%89%e5%9e%8b%e5%bb%ba%e8%ae%ae%e5%ae%9e%e6%88%98%e7%89%88" class="header-anchor"&gt;&lt;/a&gt;十、平台选型建议（实战版）
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;你的目标&lt;/th&gt;
					&lt;th&gt;建议&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;30 分钟内先连上跑 SQL&lt;/td&gt;
					&lt;td&gt;Docker &lt;code&gt;MODE=mini&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;在 Linux 服务器练官方部署工具&lt;/td&gt;
					&lt;td&gt;all-in-one + &lt;code&gt;obd demo&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Windows 笔记本本地体验&lt;/td&gt;
					&lt;td&gt;Docker Desktop&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;macOS 开发机联调&lt;/td&gt;
					&lt;td&gt;Docker Desktop&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;学习 K8s 运维&lt;/td&gt;
					&lt;td&gt;ob-operator&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;准备生产环境&lt;/td&gt;
					&lt;td&gt;不要直接用体验镜像；按正式部署/高可用架构与官方生产文档规划&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一句话总结：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;跨平台先 Docker；Linux 深造用 OBD；生产上集群/K8s，不要拿体验镜像硬上。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="十一精简命令速查"&gt;&lt;a href="#%e5%8d%81%e4%b8%80%e7%b2%be%e7%ae%80%e5%91%bd%e4%bb%a4%e9%80%9f%e6%9f%a5" class="header-anchor"&gt;&lt;/a&gt;十一、精简命令速查
&lt;/h2&gt;&lt;h3 id="docker全平台"&gt;&lt;a href="#docker%e5%85%a8%e5%b9%b3%e5%8f%b0" class="header-anchor"&gt;&lt;/a&gt;Docker（全平台）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -p 2881:2881 --name oceanbase-ce -e &lt;span class="nv"&gt;MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mini -d oceanbase/oceanbase-ce
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker logs oceanbase-ce &lt;span class="p"&gt;|&lt;/span&gt; tail -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it oceanbase-ce obclient -h127.0.0.1 -P2881 -uroot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="linux-all-in-one"&gt;&lt;a href="#linux-all-in-one" class="header-anchor"&gt;&lt;/a&gt;Linux all-in-one
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash -c &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -s https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/download-center/opensource/oceanbase-all-in-one/installer.sh&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.oceanbase-all-in-one/bin/env.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obd demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obclient -h127.0.0.1 -uroot -P2881
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="obd-rpmcentosrhel"&gt;&lt;a href="#obd-rpmcentosrhel" class="header-anchor"&gt;&lt;/a&gt;OBD RPM（CentOS/RHEL）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y yum-utils
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum install -y ob-deploy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /etc/profile.d/obd.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;obd demo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;OceanBase 的“多平台搭建”并不要求你在每个 OS 上都原生编译一套数据库：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Docker&lt;/strong&gt; 是 Linux / Windows / macOS 的最大公约数，适合快速体验与开发联调。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux all-in-one + OBD&lt;/strong&gt; 更接近官方部署工具体验，适合服务器环境。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows / macOS&lt;/strong&gt; 应把精力放在 Docker Desktop（或 WSL2）而不是强行原生部署。&lt;/li&gt;
&lt;li&gt;需要容器编排时，转向 &lt;strong&gt;ob-operator&lt;/strong&gt;，而不是把 &lt;code&gt;oceanbase-ce&lt;/code&gt; 体验镜像直接当生产方案。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;先保证“能启动、能连接、能建表”，再进入租户管理、资源规格、多副本和高可用，路径会清晰很多。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;OceanBase 官方仓库 README（中英文 Quick Start / Docker / all-in-one）：https://github.com/oceanbase/oceanbase&lt;/li&gt;
&lt;li&gt;OceanBase Docker 镜像说明（Docker Hub &lt;code&gt;oceanbase/oceanbase-ce&lt;/code&gt;）：https://hub.docker.com/r/oceanbase/oceanbase-ce&lt;/li&gt;
&lt;li&gt;OceanBase Docker 镜像仓库文档：https://github.com/oceanbase/docker-images&lt;/li&gt;
&lt;li&gt;OceanBase Deployer（OBD）中文 README：https://github.com/oceanbase/obdeploy&lt;/li&gt;
&lt;li&gt;ob-operator 文档：https://oceanbase.github.io/ob-operator&lt;/li&gt;
&lt;li&gt;OceanBase 中文文档中心：https://www.oceanbase.com/docs/oceanbase-database-cn&lt;/li&gt;
&lt;li&gt;快速体验入口：https://open.oceanbase.com/quickStart&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MySQL InnoDB 事务隔离级别与 MVCC：原理、可见性与工程实践</title><link>https://blog.waihost.com/posts/mysql-innodb-mvcc-isolation-levels/</link><pubDate>Tue, 14 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/mysql-innodb-mvcc-isolation-levels/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/mysql-innodb-mvcc-isolation-levels.svg" alt="Featured image of post MySQL InnoDB 事务隔离级别与 MVCC：原理、可见性与工程实践" /&gt;&lt;p&gt;在业务代码里，很多人把「开事务」当成理所当然：&lt;code&gt;BEGIN&lt;/code&gt; → 几条 SQL → &lt;code&gt;COMMIT&lt;/code&gt;。线上一旦出现脏数据、重复扣减、偶发死锁，第一反应却是「加锁」或「把隔离级别调高」。其实 InnoDB 的默认行为已经是一套完整的 &lt;strong&gt;多版本并发控制（MVCC）+ 行级锁&lt;/strong&gt; 组合；真正关键的是：读走快照还是走加锁读、当前隔离级别如何决定可见性与间隙锁。&lt;/p&gt;
&lt;p&gt;本文基于 MySQL 官方手册中的隔离级别、多版本、一致性非锁定读、间隙锁/next-key 与死锁说明，梳理可复用的原理与工程实践，而不是版本变更清单。&lt;/p&gt;
&lt;h2 id="问题背景并发事务到底在打架什么"&gt;&lt;a href="#%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af%e5%b9%b6%e5%8f%91%e4%ba%8b%e5%8a%a1%e5%88%b0%e5%ba%95%e5%9c%a8%e6%89%93%e6%9e%b6%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;问题背景：并发事务到底在“打架”什么
&lt;/h2&gt;&lt;p&gt;SQL 标准用隔离级别描述并发下的异常现象（脏读、不可重复读、幻读）。InnoDB 实现了标准里的四级隔离：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;隔离级别&lt;/th&gt;
					&lt;th&gt;典型问题&lt;/th&gt;
					&lt;th&gt;InnoDB 要点（官方行为）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;READ UNCOMMITTED&lt;/td&gt;
					&lt;td&gt;脏读&lt;/td&gt;
					&lt;td&gt;普通 &lt;code&gt;SELECT&lt;/code&gt; 可能读到「更早版本」的行，读本身不一致&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;READ COMMITTED&lt;/td&gt;
					&lt;td&gt;不可重复读、幻读&lt;/td&gt;
					&lt;td&gt;每次一致性读使用&lt;strong&gt;新快照&lt;/strong&gt;；锁定读通常只锁记录、不锁间隙&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;REPEATABLE READ（默认）&lt;/td&gt;
					&lt;td&gt;幻读在加锁读路径上被抑制&lt;/td&gt;
					&lt;td&gt;事务内普通一致性读复用&lt;strong&gt;首次读建立的快照&lt;/strong&gt;；范围锁定读使用 gap/next-key&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SERIALIZABLE&lt;/td&gt;
					&lt;td&gt;最强串行语义&lt;/td&gt;
					&lt;td&gt;在 &lt;code&gt;autocommit&lt;/code&gt; 关闭时，普通 &lt;code&gt;SELECT&lt;/code&gt; 隐式变为 &lt;code&gt;SELECT ... FOR SHARE&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;默认是 &lt;strong&gt;REPEATABLE READ&lt;/strong&gt;。很多团队在迁移自 Oracle 等库时会改成 READ COMMITTED，这会显著改变锁与幻读行为——必须按业务场景评估，而不是「听说更像 Oracle 就改」。&lt;/p&gt;
&lt;h2 id="核心原理mvcc-如何让读不挡写"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e5%8e%9f%e7%90%86mvcc-%e5%a6%82%e4%bd%95%e8%ae%a9%e8%af%bb%e4%b8%8d%e6%8c%a1%e5%86%99" class="header-anchor"&gt;&lt;/a&gt;核心原理：MVCC 如何让读不挡写
&lt;/h2&gt;&lt;h3 id="行上的隐藏字段与-undo"&gt;&lt;a href="#%e8%a1%8c%e4%b8%8a%e7%9a%84%e9%9a%90%e8%97%8f%e5%ad%97%e6%ae%b5%e4%b8%8e-undo" class="header-anchor"&gt;&lt;/a&gt;行上的隐藏字段与 undo
&lt;/h3&gt;&lt;p&gt;InnoDB 是多版本存储引擎：被修改行的旧版本信息保存在 &lt;strong&gt;undo 表空间 / 回滚段&lt;/strong&gt; 中，用于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;事务回滚时做 undo&lt;/li&gt;
&lt;li&gt;一致性读时构造「更早版本的行」&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;官方文档指出，InnoDB 会在每行内部维护（概念上）这些字段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DB_TRX_ID&lt;/strong&gt;（6 字节）：最近一次插入或更新该行的事务 ID；删除在内部也视作更新，并打上删除标记&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DB_ROLL_PTR&lt;/strong&gt;（7 字节）：回滚指针，指向 undo log，从而能重建更新前的行内容&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DB_ROW_ID&lt;/strong&gt;（6 字节）：单调递增的行 ID；仅在没有合适主键、需要自动生成聚簇索引时进入索引结构&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;undo 又分为 insert undo 与 update undo：insert undo 在事务提交后即可丢弃；update undo 还要服务一致性读，只有当不再存在「可能需要该历史版本」的读视图事务时，才能清理。这也是「长事务拖垮 undo / 历史版本膨胀」的根因。&lt;/p&gt;
&lt;h3 id="一致性非锁定读consistent-nonlocking-read"&gt;&lt;a href="#%e4%b8%80%e8%87%b4%e6%80%a7%e9%9d%9e%e9%94%81%e5%ae%9a%e8%af%bbconsistent-nonlocking-read" class="header-anchor"&gt;&lt;/a&gt;一致性非锁定读（Consistent Nonlocking Read）
&lt;/h3&gt;&lt;p&gt;在 READ COMMITTED 与 REPEATABLE READ 下，普通 &lt;code&gt;SELECT&lt;/code&gt; 默认走 &lt;strong&gt;一致性读&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询看到某个时间点之前已提交事务所做的修改&lt;/li&gt;
&lt;li&gt;看不到之后提交或未提交事务的修改&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;例外&lt;/strong&gt;：同一事务内更早语句自己写过的变更，当前事务能看见&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一致性读 &lt;strong&gt;不在表上加读锁&lt;/strong&gt;，因此其他会话可以同时改这些表——这就是 MVCC 带来的读写并发。&lt;/p&gt;
&lt;p&gt;快照时机是理解 RR / RC 差异的关键：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;REPEATABLE READ&lt;/strong&gt;：事务内第一次一致性读建立快照，后续普通 &lt;code&gt;SELECT&lt;/code&gt; 复用同一快照，彼此一致&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;READ COMMITTED&lt;/strong&gt;：事务内每一次一致性读都建立并读取&lt;strong&gt;新的&lt;/strong&gt;快照&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此在 RR 下，「同一事务里两次 &lt;code&gt;SELECT&lt;/code&gt; 结果一样」是默认语义；在 RC 下，「读到别人已提交的新数据」是默认语义。&lt;/p&gt;
&lt;p&gt;官方还特别提醒：快照主要作用于事务内的 &lt;code&gt;SELECT&lt;/code&gt;，&lt;strong&gt;不一定&lt;/strong&gt;约束 &lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; 的目标行集合。在 RR 中可能出现：&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="c1"&gt;-- 会话 A：REPEATABLE READ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&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;xyz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;DELETE&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="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&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;xyz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&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;xyz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 仍可能是 0（普通 SELECT 仍看旧快照）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;也就是说：&lt;strong&gt;写路径看到的是“当前最新可提交状态 + 锁”&lt;/strong&gt;，读路径在 RR 下仍可能停在旧快照。混用「普通 SELECT 决策 + DML」时，要意识到二者语义不同；需要当前读时用 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; / &lt;code&gt;FOR SHARE&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="加锁读与间隙幻读如何被挡住"&gt;&lt;a href="#%e5%8a%a0%e9%94%81%e8%af%bb%e4%b8%8e%e9%97%b4%e9%9a%99%e5%b9%bb%e8%af%bb%e5%a6%82%e4%bd%95%e8%a2%ab%e6%8c%a1%e4%bd%8f" class="header-anchor"&gt;&lt;/a&gt;加锁读与间隙：幻读如何被挡住
&lt;/h3&gt;&lt;p&gt;普通 &lt;code&gt;SELECT&lt;/code&gt; 是快照读；下列语句是 &lt;strong&gt;locking read / 当前读&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; / &lt;code&gt;SELECT ... FOR SHARE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE&lt;/code&gt; / &lt;code&gt;DELETE&lt;/code&gt;（以及会读取并锁定目标行的 DML）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 &lt;strong&gt;REPEATABLE READ&lt;/strong&gt; 下（官方）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;唯一索引 + &lt;strong&gt;唯一等值&lt;/strong&gt;条件：通常只锁住找到的索引记录，&lt;strong&gt;不锁前面的 gap&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;其他搜索条件（范围、非唯一等）：扫描范围内使用 &lt;strong&gt;gap lock&lt;/strong&gt; 或 &lt;strong&gt;next-key lock&lt;/strong&gt;，阻止其他会话向间隙中插入&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Next-key lock&lt;/strong&gt; = 索引记录锁 + 该记录之前间隙上的 gap lock。官方用幻读例子说明：若只锁已有记录、不锁间隙，其他事务可在范围中间插入新行，导致同一事务再次查询出现「幻影行」。InnoDB 通过 next-key 算法抑制这类插入。&lt;/p&gt;
&lt;p&gt;在 &lt;strong&gt;READ COMMITTED&lt;/strong&gt; 下（官方）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;锁定读一般只锁 &lt;strong&gt;index record&lt;/strong&gt;，不锁 gap，因此允许在已锁记录旁插入新行&lt;/li&gt;
&lt;li&gt;gap 锁主要用于外键检查与重复键检查&lt;/li&gt;
&lt;li&gt;因为 gap 锁关闭，&lt;strong&gt;可能出现幻读&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;另有工程意义：&lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; 对 &lt;strong&gt;不匹配 WHERE 的行&lt;/strong&gt; 会在评估后释放锁，死锁概率通常更低；但死锁仍可能发生&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="serializable-不是神秘黑盒"&gt;&lt;a href="#serializable-%e4%b8%8d%e6%98%af%e7%a5%9e%e7%a7%98%e9%bb%91%e7%9b%92" class="header-anchor"&gt;&lt;/a&gt;SERIALIZABLE 不是「神秘黑盒」
&lt;/h3&gt;&lt;p&gt;官方定义很明确：SERIALIZABLE 类似 REPEATABLE READ，但当 &lt;strong&gt;autocommit 关闭&lt;/strong&gt; 时，InnoDB 会把普通 &lt;code&gt;SELECT&lt;/code&gt; &lt;strong&gt;隐式转换成&lt;/strong&gt; &lt;code&gt;SELECT ... FOR SHARE&lt;/code&gt;。若 autocommit 开启，单条 &lt;code&gt;SELECT&lt;/code&gt; 本身就是只读事务，可走一致性非锁定读而不必阻塞。&lt;/p&gt;
&lt;p&gt;因此：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;想用 SERIALIZABLE 做「读也要挡住别人改」：确保在显式事务中（关闭 autocommit）&lt;/li&gt;
&lt;li&gt;它会显著增加锁竞争，只适合 XA、强一致性专项场景，不适合默认全库开启&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="实践如何查看设置与正确选用"&gt;&lt;a href="#%e5%ae%9e%e8%b7%b5%e5%a6%82%e4%bd%95%e6%9f%a5%e7%9c%8b%e8%ae%be%e7%bd%ae%e4%b8%8e%e6%ad%a3%e7%a1%ae%e9%80%89%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;实践：如何查看、设置与正确选用
&lt;/h2&gt;&lt;h3 id="查看与设置隔离级别"&gt;&lt;a href="#%e6%9f%a5%e7%9c%8b%e4%b8%8e%e8%ae%be%e7%bd%ae%e9%9a%94%e7%a6%bb%e7%ba%a7%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;查看与设置隔离级别
&lt;/h3&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="c1"&gt;-- 查看（MySQL 8 推荐系统变量）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@@&lt;/span&gt;&lt;span class="k"&gt;GLOBAL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction_isolation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@@&lt;/span&gt;&lt;span class="k"&gt;SESSION&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction_isolation&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ISOLATION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COMMITTED&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SESSION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ISOLATION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;REPEATABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GLOBAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ISOLATION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COMMITTED&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;也可在配置文件中设置服务端默认：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;transaction-isolation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;READ-COMMITTED&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;（选项值使用连字符形式，如 &lt;code&gt;REPEATABLE-READ&lt;/code&gt;。）&lt;/p&gt;
&lt;p&gt;访问模式还可设为 &lt;code&gt;READ ONLY&lt;/code&gt; / &lt;code&gt;READ WRITE&lt;/code&gt;，只读事务有助于引擎做优化，适合报表会话。&lt;/p&gt;
&lt;h3 id="业务选型建议工程向"&gt;&lt;a href="#%e4%b8%9a%e5%8a%a1%e9%80%89%e5%9e%8b%e5%bb%ba%e8%ae%ae%e5%b7%a5%e7%a8%8b%e5%90%91" class="header-anchor"&gt;&lt;/a&gt;业务选型建议（工程向）
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;默认保持 REPEATABLE READ&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;账户余额校验 + 扣减、库存预占、需要「事务内多次普通读一致」的流程更自然&lt;/li&gt;
&lt;li&gt;范围更新/删除配合索引时，要注意 gap/next-key 带来的插入阻塞&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;高并发、写多读多、能接受「读到最新已提交」时考虑 READ COMMITTED&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常见于互联网业务减少间隙锁、降低死锁&lt;/li&gt;
&lt;li&gt;必须接受：同一事务内两次普通读可能不同；幻读可能发生&lt;/li&gt;
&lt;li&gt;官方要求 RC 下二进制日志实质走 &lt;strong&gt;row-based&lt;/strong&gt;（&lt;code&gt;MIXED&lt;/code&gt; 时会自动切 row）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;需要「读到的行在事务期间不被别人改」&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要只靠普通 &lt;code&gt;SELECT&lt;/code&gt; 的 RR 快照（别人仍可改，你只是看不见）&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;（要改）或 &lt;code&gt;FOR SHARE&lt;/code&gt;（共享读）明确当前读&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;避免长事务&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;官方建议即使是只做一致性读的事务也要及时提交，否则 update undo 无法回收，回滚段膨胀&lt;/li&gt;
&lt;li&gt;长事务还会拉长锁持有时间，放大死锁与锁等待&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="可复现的小实验建议在测试库"&gt;&lt;a href="#%e5%8f%af%e5%a4%8d%e7%8e%b0%e7%9a%84%e5%b0%8f%e5%ae%9e%e9%aa%8c%e5%bb%ba%e8%ae%ae%e5%9c%a8%e6%b5%8b%e8%af%95%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;可复现的小实验（建议在测试库）
&lt;/h3&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;InnoDB&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&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;&lt;strong&gt;实验 A：RR 下快照读&lt;/strong&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="c1"&gt;-- 会话 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SESSION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ISOLATION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LEVEL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;REPEATABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;START&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 100
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 会话 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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;90&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COMMIT&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 会话 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 仍为 100（复用首次快照）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COMMIT&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 提交后新事务可见 90
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;实验 B：需要当前读时加锁&lt;/strong&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;START&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FOR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 当前读 + X 锁
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 业务校验 balance &amp;gt;= 10 后再扣减
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;balance&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="n"&gt;balance&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;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;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;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COMMIT&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;&lt;strong&gt;实验 C：范围条件与插入阻塞（RR）&lt;/strong&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="c1"&gt;-- 会话 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;START&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRANSACTION&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FOR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 范围 + next-key/gap
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 会话 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 往往会等待会话 1 提交
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;把 &lt;code&gt;FOR UPDATE&lt;/code&gt; 换成普通 &lt;code&gt;SELECT&lt;/code&gt; 时，会话 2 通常可以插入（快照读不加锁），这能直观区分「看不见」和「锁住」。&lt;/p&gt;
&lt;h2 id="常见坑与排查"&gt;&lt;a href="#%e5%b8%b8%e8%a7%81%e5%9d%91%e4%b8%8e%e6%8e%92%e6%9f%a5" class="header-anchor"&gt;&lt;/a&gt;常见坑与排查
&lt;/h2&gt;&lt;h3 id="1-用普通-select-做决策却期望互斥"&gt;&lt;a href="#1-%e7%94%a8%e6%99%ae%e9%80%9a-select-%e5%81%9a%e5%86%b3%e7%ad%96%e5%8d%b4%e6%9c%9f%e6%9c%9b%e4%ba%92%e6%96%a5" class="header-anchor"&gt;&lt;/a&gt;1. 用普通 SELECT 做决策，却期望互斥
&lt;/h3&gt;&lt;p&gt;快照读不互斥。库存/余额扣减必须：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事务内 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; 再更新，或&lt;/li&gt;
&lt;li&gt;直接条件更新并检查影响行数：&lt;code&gt;UPDATE ... WHERE id=? AND balance&amp;gt;=?&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;仅靠 RR 的「两次 SELECT 一样」&lt;strong&gt;不能&lt;/strong&gt;防止超卖。&lt;/p&gt;
&lt;h3 id="2-唯一等值-vs-范围锁范围差很多"&gt;&lt;a href="#2-%e5%94%af%e4%b8%80%e7%ad%89%e5%80%bc-vs-%e8%8c%83%e5%9b%b4%e9%94%81%e8%8c%83%e5%9b%b4%e5%b7%ae%e5%be%88%e5%a4%9a" class="header-anchor"&gt;&lt;/a&gt;2. 唯一等值 vs 范围：锁范围差很多
&lt;/h3&gt;&lt;p&gt;官方写明：RR 下唯一索引等值命中通常只锁记录；范围或非唯一条件会锁间隙。排查「插入被堵住」时，先看 SQL 是否走了范围扫描、索引是否合适。&lt;/p&gt;
&lt;h3 id="3-rr-下select-看不到delete-却删到了"&gt;&lt;a href="#3-rr-%e4%b8%8bselect-%e7%9c%8b%e4%b8%8d%e5%88%b0delete-%e5%8d%b4%e5%88%a0%e5%88%b0%e4%ba%86" class="header-anchor"&gt;&lt;/a&gt;3. RR 下「SELECT 看不到，DELETE 却删到了」
&lt;/h3&gt;&lt;p&gt;这是官方明确描述过的快照读与 DML 当前读差异，不是玄学 bug。审计日志或对账逻辑要按「语句类型」理解可见性。&lt;/p&gt;
&lt;h3 id="4-死锁隔离级别救不了写写冲突"&gt;&lt;a href="#4-%e6%ad%bb%e9%94%81%e9%9a%94%e7%a6%bb%e7%ba%a7%e5%88%ab%e6%95%91%e4%b8%8d%e4%ba%86%e5%86%99%e5%86%99%e5%86%b2%e7%aa%81" class="header-anchor"&gt;&lt;/a&gt;4. 死锁：隔离级别救不了写写冲突
&lt;/h3&gt;&lt;p&gt;官方指出：死锁可能性与隔离级别无直接关系——隔离级别主要改读行为，而死锁来自写锁互相等待。处理要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;保持默认死锁检测开启（&lt;code&gt;innodb_deadlock_detect&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;死锁发生时 InnoDB 会回滚其中一个事务（victim），&lt;strong&gt;应用必须可重试&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;关闭检测时依赖 &lt;code&gt;innodb_lock_wait_timeout&lt;/code&gt;，代价是更长的等待&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;SHOW ENGINE INNODB STATUS&lt;/code&gt; 查看最近一次死锁&lt;/li&gt;
&lt;li&gt;工程上：固定多表/多行加锁顺序、缩短事务、给 &lt;code&gt;WHERE&lt;/code&gt; 列建合适索引&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-历史版本与undo-涨爆"&gt;&lt;a href="#5-%e5%8e%86%e5%8f%b2%e7%89%88%e6%9c%ac%e4%b8%8eundo-%e6%b6%a8%e7%88%86" class="header-anchor"&gt;&lt;/a&gt;5. 历史版本与「undo 涨爆」
&lt;/h3&gt;&lt;p&gt;长查询、忘记提交的会话、超大事务都会让 update undo 滞留。监控 undo 表空间、历史列表长度，并在应用层强制事务超时/连接回收。&lt;/p&gt;
&lt;h3 id="6-混用锁定读与非锁定读"&gt;&lt;a href="#6-%e6%b7%b7%e7%94%a8%e9%94%81%e5%ae%9a%e8%af%bb%e4%b8%8e%e9%9d%9e%e9%94%81%e5%ae%9a%e8%af%bb" class="header-anchor"&gt;&lt;/a&gt;6. 混用锁定读与非锁定读
&lt;/h3&gt;&lt;p&gt;官方不建议在同一 RR 事务里混用大量「普通 SELECT」与 &lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;，因为二者看到的状态基准不同，逻辑难推理；若目标接近串行，应显式使用加锁读或评估 SERIALIZABLE。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;InnoDB 默认 &lt;strong&gt;REPEATABLE READ&lt;/strong&gt;，普通读靠 &lt;strong&gt;MVCC 快照&lt;/strong&gt;，写与加锁读靠 &lt;strong&gt;行锁 +（RR 下）gap/next-key&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RC&lt;/strong&gt; 每次一致性读换新快照、锁定读基本不锁 gap，并发更好但幻读与不可重复读更易出现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SERIALIZABLE&lt;/strong&gt; 在关闭 autocommit 时把普通 &lt;code&gt;SELECT&lt;/code&gt; 变成 &lt;code&gt;FOR SHARE&lt;/code&gt;，代价是锁竞争。&lt;/li&gt;
&lt;li&gt;工程上优先：短事务、正确索引、该当前读就 &lt;code&gt;FOR UPDATE&lt;/code&gt;、死锁可重试；不要把「提高隔离级别」当成唯一药方。&lt;/li&gt;
&lt;li&gt;理解「快照读 vs 当前读」比背诵四个级别名称更能减少线上数据竞争事故。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;MySQL 8.4 Reference Manual — &lt;a class="link" href="https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html" target="_blank" rel="noopener"
 &gt;Transaction Isolation Levels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual（Oracle Docs）— &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-multi-versioning.html" target="_blank" rel="noopener"
 &gt;InnoDB Multi-Versioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual — &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-consistent-read.html" target="_blank" rel="noopener"
 &gt;Consistent Nonlocking Reads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual — &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-locking.html" target="_blank" rel="noopener"
 &gt;InnoDB Locking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual — &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-next-key-locking.html" target="_blank" rel="noopener"
 &gt;Phantom Rows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual — &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/innodb-deadlocks.html" target="_blank" rel="noopener"
 &gt;Deadlocks in InnoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MySQL 8.0 Reference Manual — &lt;a class="link" href="https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/set-transaction.html" target="_blank" rel="noopener"
 &gt;SET TRANSACTION Statement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MariaDB Knowledge Base — &lt;a class="link" href="https://mariadb.com/kb/en/set-transaction/" target="_blank" rel="noopener"
 &gt;SET TRANSACTION&lt;/a&gt;（辅助对照 InnoDB 兼容实现）&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Redis 缓存穿透、击穿与雪崩：原理、场景与工程解法</title><link>https://blog.waihost.com/posts/redis-cache-penetration-breakdown-avalanche/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0800</pubDate><guid>https://blog.waihost.com/posts/redis-cache-penetration-breakdown-avalanche/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/redis-cache-penetration-breakdown-avalanche.svg" alt="Featured image of post Redis 缓存穿透、击穿与雪崩：原理、场景与工程解法" /&gt;&lt;p&gt;在高并发系统里，Redis 常常被放在数据库前面做读加速。一旦缓存设计不当，问题往往不是“Redis 慢一点”，而是数据库被瞬间打穿。工程上最常见、也最容易被混为一谈的三类故障是：&lt;strong&gt;缓存穿透&lt;/strong&gt;、&lt;strong&gt;缓存击穿&lt;/strong&gt;和&lt;strong&gt;缓存雪崩&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这三类问题听起来相似，根因却不同：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;典型特征&lt;/th&gt;
					&lt;th&gt;直接伤害&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;缓存穿透&lt;/td&gt;
					&lt;td&gt;查的是不存在的数据，缓存和 DB 都没有&lt;/td&gt;
					&lt;td&gt;恶意或异常请求反复打到 DB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;缓存击穿&lt;/td&gt;
					&lt;td&gt;某个热点 key 刚好过期&lt;/td&gt;
					&lt;td&gt;同一时刻大量请求打到 DB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;缓存雪崩&lt;/td&gt;
					&lt;td&gt;大量 key 同时失效，或缓存层整体不可用&lt;/td&gt;
					&lt;td&gt;系统级读流量直接压垮 DB&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;本文从现象、根因、可落地方案三层拆开，并结合 Redis 官方能力（&lt;code&gt;SET&lt;/code&gt; 的 &lt;code&gt;NX/EX&lt;/code&gt;、&lt;code&gt;EXPIRE&lt;/code&gt;、淘汰策略、分布式锁模式）给出可复用实践。&lt;/p&gt;
&lt;h2 id="一先把请求路径画清楚"&gt;&lt;a href="#%e4%b8%80%e5%85%88%e6%8a%8a%e8%af%b7%e6%b1%82%e8%b7%af%e5%be%84%e7%94%bb%e6%b8%85%e6%a5%9a" class="header-anchor"&gt;&lt;/a&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-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client -&amp;gt; App -&amp;gt; Redis -&amp;gt; (miss) -&amp;gt; Database -&amp;gt; write back Redis -&amp;gt; response
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;缓存层的价值在于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把高频读从数据库剥离出来；&lt;/li&gt;
&lt;li&gt;用更低延迟响应热点数据；&lt;/li&gt;
&lt;li&gt;给数据库争取容量和稳定性。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此，任何“绕过缓存直接打 DB”的路径，都要被当成故障设计点来处理。&lt;/p&gt;
&lt;h2 id="二缓存穿透查不存在的数据"&gt;&lt;a href="#%e4%ba%8c%e7%bc%93%e5%ad%98%e7%a9%bf%e9%80%8f%e6%9f%a5%e4%b8%8d%e5%ad%98%e5%9c%a8%e7%9a%84%e6%95%b0%e6%8d%ae" class="header-anchor"&gt;&lt;/a&gt;二、缓存穿透：查不存在的数据
&lt;/h2&gt;&lt;h3 id="1-现象"&gt;&lt;a href="#1-%e7%8e%b0%e8%b1%a1" class="header-anchor"&gt;&lt;/a&gt;1. 现象
&lt;/h3&gt;&lt;p&gt;请求的 key 在业务上不存在，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户 ID &lt;code&gt;-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;商品 ID &lt;code&gt;999999999&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;被爬虫扫出来的非法参数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此时 Redis 没有缓存，数据库也查不到记录。如果应用只在“查到结果时才写缓存”，那么每次请求都会落到数据库。&lt;/p&gt;
&lt;h3 id="2-根因"&gt;&lt;a href="#2-%e6%a0%b9%e5%9b%a0" class="header-anchor"&gt;&lt;/a&gt;2. 根因
&lt;/h3&gt;&lt;p&gt;穿透的本质不是“缓存过期”，而是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;空结果没有被负缓存（negative caching）保护。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="3-解法"&gt;&lt;a href="#3-%e8%a7%a3%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;3. 解法
&lt;/h3&gt;&lt;h4 id="方案-a缓存空对象最常用"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-a%e7%bc%93%e5%ad%98%e7%a9%ba%e5%af%b9%e8%b1%a1%e6%9c%80%e5%b8%b8%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;方案 A：缓存空对象（最常用）
&lt;/h4&gt;&lt;p&gt;查库为空时，也写入一个短 TTL 的空值标记：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 伪命令：空结果缓存 60 秒&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SET product:999999999 __NULL__ EX &lt;span class="m"&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;应用读到 &lt;code&gt;__NULL__&lt;/code&gt; 时直接返回“不存在”，不再访问数据库。&lt;/p&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TTL 不要太长，避免真实数据刚创建后长时间读不到；&lt;/li&gt;
&lt;li&gt;空值要有统一约定，避免和正常业务值冲突；&lt;/li&gt;
&lt;li&gt;对写路径做缓存失效/更新，保证最终一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="方案-b布隆过滤器bloom-filter前置拦截"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-b%e5%b8%83%e9%9a%86%e8%bf%87%e6%bb%a4%e5%99%a8bloom-filter%e5%89%8d%e7%bd%ae%e6%8b%a6%e6%88%aa" class="header-anchor"&gt;&lt;/a&gt;方案 B：布隆过滤器（Bloom Filter）前置拦截
&lt;/h4&gt;&lt;p&gt;对“可能存在”的 ID 集合做布隆过滤器：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据写入时同步/异步加入过滤器；&lt;/li&gt;
&lt;li&gt;查询前先判断“一定不存在还是可能存在”；&lt;/li&gt;
&lt;li&gt;一定不存在则直接拒绝，不打 Redis/DB。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;适合海量 ID、爬虫扫描、开放查询接口。代价是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有极低误判率（把不存在判断成可能存在）；&lt;/li&gt;
&lt;li&gt;需要维护过滤器更新与扩容。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="方案-c参数与权限校验前置"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-c%e5%8f%82%e6%95%b0%e4%b8%8e%e6%9d%83%e9%99%90%e6%a0%a1%e9%aa%8c%e5%89%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;方案 C：参数与权限校验前置
&lt;/h4&gt;&lt;p&gt;很多穿透其实是脏流量：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;非数字 ID&lt;/li&gt;
&lt;li&gt;超范围分页&lt;/li&gt;
&lt;li&gt;未登录却访问私有资源&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在网关/应用入口直接拦截，比把压力交给缓存更划算。&lt;/p&gt;
&lt;h2 id="三缓存击穿热点-key-刚好失效"&gt;&lt;a href="#%e4%b8%89%e7%bc%93%e5%ad%98%e5%87%bb%e7%a9%bf%e7%83%ad%e7%82%b9-key-%e5%88%9a%e5%a5%bd%e5%a4%b1%e6%95%88" class="header-anchor"&gt;&lt;/a&gt;三、缓存击穿：热点 key 刚好失效
&lt;/h2&gt;&lt;h3 id="1-现象-1"&gt;&lt;a href="#1-%e7%8e%b0%e8%b1%a1-1" class="header-anchor"&gt;&lt;/a&gt;1. 现象
&lt;/h3&gt;&lt;p&gt;某个非常热的 key（首页配置、秒杀库存视图、热门商品详情）在某一瞬间过期。&lt;br&gt;
下一毫秒，成千上万请求同时看到 miss，一起去查数据库，形成“单点热点打穿”。&lt;/p&gt;
&lt;h3 id="2-根因-1"&gt;&lt;a href="#2-%e6%a0%b9%e5%9b%a0-1" class="header-anchor"&gt;&lt;/a&gt;2. 根因
&lt;/h3&gt;&lt;p&gt;击穿关注的是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;单个热点 key 过期窗口内的并发回源。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;它和穿透不同：数据本来存在，只是缓存刚好空了。&lt;/p&gt;
&lt;h3 id="3-解法-1"&gt;&lt;a href="#3-%e8%a7%a3%e6%b3%95-1" class="header-anchor"&gt;&lt;/a&gt;3. 解法
&lt;/h3&gt;&lt;h4 id="方案-a互斥重建singleflight--分布式锁"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-a%e4%ba%92%e6%96%a5%e9%87%8d%e5%bb%basingleflight--%e5%88%86%e5%b8%83%e5%bc%8f%e9%94%81" class="header-anchor"&gt;&lt;/a&gt;方案 A：互斥重建（singleflight / 分布式锁）
&lt;/h4&gt;&lt;p&gt;只有一个请求负责回源重建，其他请求等待或短暂失败重试。&lt;/p&gt;
&lt;p&gt;Redis 官方 &lt;code&gt;SET&lt;/code&gt; 支持原子条件写入，可用 &lt;code&gt;NX + EX&lt;/code&gt; 做互斥：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 抢重建锁，5 秒自动过期，防止进程崩溃后死锁&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SET rebuild:lock:product:1001 &lt;span class="m"&gt;1&lt;/span&gt; NX EX &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读缓存 miss；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SET lock NX EX&lt;/code&gt; 抢锁；&lt;/li&gt;
&lt;li&gt;抢到锁的请求查 DB，写回缓存，释放锁；&lt;/li&gt;
&lt;li&gt;没抢到锁的请求短暂 sleep/重试读缓存，或返回旧兜底。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;官方文档明确：&lt;code&gt;SET key value NX EX seconds&lt;/code&gt; 是设置值并带过期时间的常用原子写法；&lt;code&gt;SETNX&lt;/code&gt; 在新代码中更推荐用 &lt;code&gt;SET ... NX&lt;/code&gt; 替代。&lt;/p&gt;
&lt;h4 id="方案-b逻辑过期logical-expire"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-b%e9%80%bb%e8%be%91%e8%bf%87%e6%9c%9flogical-expire" class="header-anchor"&gt;&lt;/a&gt;方案 B：逻辑过期（logical expire）
&lt;/h4&gt;&lt;p&gt;缓存 value 内嵌业务过期时间，物理 key 不过期或过期很久：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;price&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;expireAt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1720857600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;读取时：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;未逻辑过期：直接返回；&lt;/li&gt;
&lt;li&gt;已逻辑过期：返回旧数据，同时异步触发重建。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;优点是用户几乎无感 miss；代价是要接受短暂脏读，并做好异步重建失败补偿。&lt;/p&gt;
&lt;h4 id="方案-c热点-key-永不过期--主动更新"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-c%e7%83%ad%e7%82%b9-key-%e6%b0%b8%e4%b8%8d%e8%bf%87%e6%9c%9f--%e4%b8%bb%e5%8a%a8%e6%9b%b4%e6%96%b0" class="header-anchor"&gt;&lt;/a&gt;方案 C：热点 key 永不过期 + 主动更新
&lt;/h4&gt;&lt;p&gt;对真正的超级热点，不依赖 TTL 被动失效，而由写路径/定时任务主动更新。&lt;br&gt;
TTL 更适合普通数据；热点数据更适合“写时更新 + 监控”。&lt;/p&gt;
&lt;h2 id="四缓存雪崩大面积失效或缓存层故障"&gt;&lt;a href="#%e5%9b%9b%e7%bc%93%e5%ad%98%e9%9b%aa%e5%b4%a9%e5%a4%a7%e9%9d%a2%e7%a7%af%e5%a4%b1%e6%95%88%e6%88%96%e7%bc%93%e5%ad%98%e5%b1%82%e6%95%85%e9%9a%9c" class="header-anchor"&gt;&lt;/a&gt;四、缓存雪崩：大面积失效或缓存层故障
&lt;/h2&gt;&lt;h3 id="1-现象-2"&gt;&lt;a href="#1-%e7%8e%b0%e8%b1%a1-2" class="header-anchor"&gt;&lt;/a&gt;1. 现象
&lt;/h3&gt;&lt;p&gt;两类雪崩最常见：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;过期雪崩&lt;/strong&gt;：大量 key 在同一时间点过期；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可用性雪崩&lt;/strong&gt;：Redis 集群故障、网络分区、连接打满，导致缓存层整体不可用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;结果都是数据库在短时间内接到远超容量的读请求。&lt;/p&gt;
&lt;h3 id="2-根因-2"&gt;&lt;a href="#2-%e6%a0%b9%e5%9b%a0-2" class="header-anchor"&gt;&lt;/a&gt;2. 根因
&lt;/h3&gt;&lt;p&gt;雪崩的核心不是某一个 key，而是：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;缓存保护面在同一时间失效，流量失去缓冲层。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="3-解法-2"&gt;&lt;a href="#3-%e8%a7%a3%e6%b3%95-2" class="header-anchor"&gt;&lt;/a&gt;3. 解法
&lt;/h3&gt;&lt;h4 id="方案-attl-加随机抖动"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-attl-%e5%8a%a0%e9%9a%8f%e6%9c%ba%e6%8a%96%e5%8a%a8" class="header-anchor"&gt;&lt;/a&gt;方案 A：TTL 加随机抖动
&lt;/h4&gt;&lt;p&gt;不要让同类数据使用完全相同的过期时间：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ttl = base_ttl + random(0, jitter)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 例如 3600 + random(0, 300)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样可以把过期曲线打散，避免整点集体回源。&lt;/p&gt;
&lt;h4 id="方案-b多级缓存与本地缓存"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-b%e5%a4%9a%e7%ba%a7%e7%bc%93%e5%ad%98%e4%b8%8e%e6%9c%ac%e5%9c%b0%e7%bc%93%e5%ad%98" class="header-anchor"&gt;&lt;/a&gt;方案 B：多级缓存与本地缓存
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;本地 Caffeine/Guava Cache 挡住进程内重复读；&lt;/li&gt;
&lt;li&gt;Redis 作为分布式缓存；&lt;/li&gt;
&lt;li&gt;DB 作为最终数据源。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本地缓存 TTL 更短，可显著降低 Redis 抖动对 DB 的传导。&lt;/p&gt;
&lt;h4 id="方案-c限流熔断降级"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-c%e9%99%90%e6%b5%81%e7%86%94%e6%96%ad%e9%99%8d%e7%ba%a7" class="header-anchor"&gt;&lt;/a&gt;方案 C：限流、熔断、降级
&lt;/h4&gt;&lt;p&gt;缓存层异常时，应用不能无脑回源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对回源 QPS 做令牌桶/漏桶限流；&lt;/li&gt;
&lt;li&gt;数据库错误率升高时熔断；&lt;/li&gt;
&lt;li&gt;非核心接口返回兜底页/默认配置；&lt;/li&gt;
&lt;li&gt;核心读接口优先返回短暂旧数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="方案-d正确使用-redis-内存淘汰策略"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-d%e6%ad%a3%e7%a1%ae%e4%bd%bf%e7%94%a8-redis-%e5%86%85%e5%ad%98%e6%b7%98%e6%b1%b0%e7%ad%96%e7%95%a5" class="header-anchor"&gt;&lt;/a&gt;方案 D：正确使用 Redis 内存淘汰策略
&lt;/h4&gt;&lt;p&gt;当 Redis 用作缓存时，官方建议配置最大内存和淘汰策略，以便内存触顶时按策略驱逐 key，而不是写失败或无规划崩溃。常见策略包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;allkeys-lru&lt;/code&gt; / &lt;code&gt;allkeys-lfu&lt;/code&gt;：在全部 key 中淘汰；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;volatile-lru&lt;/code&gt; / &lt;code&gt;volatile-lfu&lt;/code&gt; / &lt;code&gt;volatile-ttl&lt;/code&gt;：只在设置了过期时间的 key 中淘汰。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关键点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;缓存场景应显式设置 &lt;code&gt;maxmemory&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;按业务选择 LRU/LFU；&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;evicted_keys&lt;/code&gt;、命中率、内存使用，避免“默默淘汰关键数据”却无人知晓。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;淘汰策略解决的是&lt;strong&gt;内存压力下的可持续性&lt;/strong&gt;，不能替代业务层的穿透/击穿防护，但能降低缓存层自身失控概率。&lt;/p&gt;
&lt;h2 id="五一套可落地的组合策略"&gt;&lt;a href="#%e4%ba%94%e4%b8%80%e5%a5%97%e5%8f%af%e8%90%bd%e5%9c%b0%e7%9a%84%e7%bb%84%e5%90%88%e7%ad%96%e7%95%a5" class="header-anchor"&gt;&lt;/a&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-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. 入口校验：挡住非法参数
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. 布隆过滤器/存在性索引：挡住明显不存在的 key
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Redis 读：命中则返回
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. miss 时：
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 热点 key：互斥重建或逻辑过期
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - 普通 key：允许有限并发回源
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. DB 空结果：写短 TTL 空缓存
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6. DB 有结果：写缓存，TTL 加抖动
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7. 全链路：限流 + 熔断 + 监控告警
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="伪代码示例"&gt;&lt;a href="#%e4%bc%aa%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b" class="header-anchor"&gt;&lt;/a&gt;伪代码示例
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;valid_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bloom&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;bloom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;might_contain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__NULL__&amp;#34;&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 热点互斥重建&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;locked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rebuild:lock:product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;locked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="n"&gt;get_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 简化：重试读缓存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&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;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__NULL__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rebuild:lock:product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SET ... NX EX&lt;/code&gt; 用于短锁，避免击穿时并发回源；&lt;/li&gt;
&lt;li&gt;空值缓存用于防穿透；&lt;/li&gt;
&lt;li&gt;TTL 抖动用于打散过期，降低雪崩概率。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="六排查清单线上怎么快速判断是哪一种"&gt;&lt;a href="#%e5%85%ad%e6%8e%92%e6%9f%a5%e6%b8%85%e5%8d%95%e7%ba%bf%e4%b8%8a%e6%80%8e%e4%b9%88%e5%bf%ab%e9%80%9f%e5%88%a4%e6%96%ad%e6%98%af%e5%93%aa%e4%b8%80%e7%a7%8d" class="header-anchor"&gt;&lt;/a&gt;六、排查清单：线上怎么快速判断是哪一种
&lt;/h2&gt;&lt;h3 id="1-先看指标"&gt;&lt;a href="#1-%e5%85%88%e7%9c%8b%e6%8c%87%e6%a0%87" class="header-anchor"&gt;&lt;/a&gt;1. 先看指标
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Redis 命中率是否骤降&lt;/li&gt;
&lt;li&gt;Redis 连接数/超时是否升高&lt;/li&gt;
&lt;li&gt;数据库 QPS、慢查询、连接池是否打满&lt;/li&gt;
&lt;li&gt;是否集中在某几个 key，还是大面积 key&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-判断路径"&gt;&lt;a href="#2-%e5%88%a4%e6%96%ad%e8%b7%af%e5%be%84" class="header-anchor"&gt;&lt;/a&gt;2. 判断路径
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;观察&lt;/th&gt;
					&lt;th&gt;更可能是&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;大量非法/不存在 ID，DB 查空很多&lt;/td&gt;
					&lt;td&gt;穿透&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;单个热 key 流量尖峰，过期瞬间 DB 飙升&lt;/td&gt;
					&lt;td&gt;击穿&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;整点或批次任务后大面积 miss&lt;/td&gt;
					&lt;td&gt;过期雪崩&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Redis 超时/主从切换/集群异常同时发生&lt;/td&gt;
					&lt;td&gt;可用性雪崩&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="3-临时止血"&gt;&lt;a href="#3-%e4%b8%b4%e6%97%b6%e6%ad%a2%e8%a1%80" class="header-anchor"&gt;&lt;/a&gt;3. 临时止血
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;对异常查询参数限流；&lt;/li&gt;
&lt;li&gt;对热点 key 预热并临时延长 TTL；&lt;/li&gt;
&lt;li&gt;打开空值缓存；&lt;/li&gt;
&lt;li&gt;给 DB 回源加总开关/配额；&lt;/li&gt;
&lt;li&gt;非核心读降级。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="七设计原则总结"&gt;&lt;a href="#%e4%b8%83%e8%ae%be%e8%ae%a1%e5%8e%9f%e5%88%99%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;七、设计原则总结
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;缓存不是数据库的影子，是保护层。&lt;/strong&gt; 任何 miss 路径都要有预算。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;空结果也是结果。&lt;/strong&gt; 不做负缓存，就容易被穿透。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;热点不能靠“碰巧没过期”。&lt;/strong&gt; 要有互斥重建、逻辑过期或主动更新。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;过期时间要工程化。&lt;/strong&gt; 相同 TTL 是雪崩温床，抖动是基本操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存故障要有降级。&lt;/strong&gt; 没有限流和熔断的缓存架构，只是把风险延后到数据库。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测性比“感觉很快”更重要。&lt;/strong&gt; 命中率、回源 QPS、淘汰数、锁竞争都要可监控。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="八什么时候不该过度设计"&gt;&lt;a href="#%e5%85%ab%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e4%b8%8d%e8%af%a5%e8%bf%87%e5%ba%a6%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;八、什么时候不该过度设计
&lt;/h2&gt;&lt;p&gt;不是所有系统都要上布隆过滤器 + 逻辑过期 + 多级缓存：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;读 QPS 不高、数据几乎都存在：做好空值缓存和基础 TTL 即可；&lt;/li&gt;
&lt;li&gt;写极少、读极多的配置类数据：适合主动更新 + 较长 TTL；&lt;/li&gt;
&lt;li&gt;强一致要求极高的余额/库存：缓存只能做辅助，核心以数据库/专用组件为准，并明确一致性模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;架构选择应匹配流量模型和一致性要求，而不是堆名词。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;缓存穿透、击穿、雪崩并不是三个神秘黑话，而是三条清晰的失败路径：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;穿透&lt;/strong&gt;：不存在的数据反复打穿 DB；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;击穿&lt;/strong&gt;：热点 key 失效瞬间被并发打穿；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;雪崩&lt;/strong&gt;：保护面大面积失效，流量失去缓冲。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;把问题定义清楚后，解法会自然收敛到：入口校验、空值缓存、互斥重建、TTL 抖动、淘汰策略、限流熔断与监控。&lt;br&gt;
Redis 提供了 &lt;code&gt;SET NX/EX&lt;/code&gt;、&lt;code&gt;EXPIRE&lt;/code&gt;、内存淘汰和分布式锁模式等基础能力，但真正决定系统稳不稳的，是你有没有把这些能力嵌进完整的读路径设计里。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Redis 官方文档：&lt;a class="link" href="https://redis.io/docs/latest/commands/set/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;SET&lt;/code&gt; 命令&lt;/a&gt;（含 &lt;code&gt;NX&lt;/code&gt; / &lt;code&gt;EX&lt;/code&gt; 等选项）&lt;/li&gt;
&lt;li&gt;Redis 官方文档：&lt;a class="link" href="https://redis.io/docs/latest/commands/expire/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;EXPIRE&lt;/code&gt; 命令&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Redis 官方文档：&lt;a class="link" href="https://redis.io/docs/latest/commands/setnx/" target="_blank" rel="noopener"
 &gt;&lt;code&gt;SETNX&lt;/code&gt; 命令&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Redis 官方文档：&lt;a class="link" href="https://redis.io/docs/latest/develop/reference/eviction/" target="_blank" rel="noopener"
 &gt;Key eviction 内存淘汰策略&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Redis 官方文档：&lt;a class="link" href="https://redis.io/docs/latest/develop/use/patterns/distributed-locks/" target="_blank" rel="noopener"
 &gt;Distributed locks 分布式锁模式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MySQL深度调优实战：从SQL到架构的全面优化</title><link>https://blog.waihost.com/posts/mysql-deep-optimization/</link><pubDate>Fri, 26 Jun 2026 17:00:00 +0000</pubDate><guid>https://blog.waihost.com/posts/mysql-deep-optimization/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/mysql-deep-optimization.svg" alt="Featured image of post MySQL深度调优实战：从SQL到架构的全面优化" /&gt;&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;MySQL 是最流行的关系型数据库之一，但在生产环境中，性能问题往往是开发和运维面临的最大挑战。本文将从 SQL 优化、索引设计、配置调优、架构优化四个维度，全面介绍 MySQL 性能调优的实战技巧。&lt;/p&gt;
&lt;h2 id="一sql-优化"&gt;&lt;a href="#%e4%b8%80sql-%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;一、SQL 优化
&lt;/h2&gt;&lt;h3 id="11-explain-执行计划分析"&gt;&lt;a href="#11-explain-%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92%e5%88%86%e6%9e%90" class="header-anchor"&gt;&lt;/a&gt;1.1 EXPLAIN 执行计划分析
&lt;/h3&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="o"&gt;*&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&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;city&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;Beijing&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;&lt;strong&gt;关键字段说明：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;字段&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;优化目标&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;type&lt;/td&gt;
					&lt;td&gt;访问类型&lt;/td&gt;
					&lt;td&gt;至少达到 range 级别&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;key&lt;/td&gt;
					&lt;td&gt;使用的索引&lt;/td&gt;
					&lt;td&gt;避免 NULL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;rows&lt;/td&gt;
					&lt;td&gt;扫描行数&lt;/td&gt;
					&lt;td&gt;越小越好&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Extra&lt;/td&gt;
					&lt;td&gt;额外信息&lt;/td&gt;
					&lt;td&gt;避免 Using filesort/temporary&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;type 访问类型（从好到差）：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;eq_ref&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ALL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-索引优化技巧"&gt;&lt;a href="#12-%e7%b4%a2%e5%bc%95%e4%bc%98%e5%8c%96%e6%8a%80%e5%b7%a7" class="header-anchor"&gt;&lt;/a&gt;1.2 索引优化技巧
&lt;/h3&gt;&lt;h4 id="最左前缀原则"&gt;&lt;a href="#%e6%9c%80%e5%b7%a6%e5%89%8d%e7%bc%80%e5%8e%9f%e5%88%99" class="header-anchor"&gt;&lt;/a&gt;最左前缀原则
&lt;/h4&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="c1"&gt;-- 联合索引 (a, b, c)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&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;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&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;1&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;b&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;2&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&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;1&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;b&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;2&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="k"&gt;c&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;3&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&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;2&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;c&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;3&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&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;2&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="k"&gt;c&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;3&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;h4 id="覆盖索引"&gt;&lt;a href="#%e8%a6%86%e7%9b%96%e7%b4%a2%e5%bc%95" class="header-anchor"&gt;&lt;/a&gt;覆盖索引
&lt;/h4&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="c1"&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;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_name_age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;John&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;h4 id="索引失效场景"&gt;&lt;a href="#%e7%b4%a2%e5%bc%95%e5%a4%b1%e6%95%88%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;索引失效场景
&lt;/h4&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;YEAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;create_time&lt;/span&gt;&lt;span class="p"&gt;)&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;2024&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;create_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-01-01&amp;#39;&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="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;create_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-01-01&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phone&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;13800138000&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phone&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;13800138000&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- ❌ LIKE 左模糊
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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;LIKE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%John&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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;LIKE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;John%&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- ❌ OR 条件
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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;25&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&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="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;John&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- ✅ 使用 UNION
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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;25&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;UNION&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;John&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;h3 id="13-查询优化"&gt;&lt;a href="#13-%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;1.3 查询优化
&lt;/h3&gt;&lt;h4 id="分页查询优化"&gt;&lt;a href="#%e5%88%86%e9%a1%b5%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;分页查询优化
&lt;/h4&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&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="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&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;INNER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&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="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="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&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="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;t&lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&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;h4 id="join-优化"&gt;&lt;a href="#join-%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;JOIN 优化
&lt;/h4&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="c1"&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;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&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="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&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;INNER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_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="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;u&lt;/span&gt;&lt;span class="p"&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="mi"&gt;1&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;h4 id="子查询优化"&gt;&lt;a href="#%e5%ad%90%e6%9f%a5%e8%af%a2%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;子查询优化
&lt;/h4&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="c1"&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;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&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="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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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="mi"&gt;1&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="p"&gt;);&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- ✅ JOIN 优化
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&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="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&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;INNER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_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="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;u&lt;/span&gt;&lt;span class="p"&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="mi"&gt;1&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;h2 id="二索引设计原则"&gt;&lt;a href="#%e4%ba%8c%e7%b4%a2%e5%bc%95%e8%ae%be%e8%ae%a1%e5%8e%9f%e5%88%99" class="header-anchor"&gt;&lt;/a&gt;二、索引设计原则
&lt;/h2&gt;&lt;h3 id="21-索引设计规范"&gt;&lt;a href="#21-%e7%b4%a2%e5%bc%95%e8%ae%be%e8%ae%a1%e8%a7%84%e8%8c%83" class="header-anchor"&gt;&lt;/a&gt;2.1 索引设计规范
&lt;/h3&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="c1"&gt;-- 1. 选择区分度高的列
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;selectivity&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 区分度 &amp;gt; 0.1 才考虑建索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 2. 联合索引字段顺序
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 区分度高的字段在前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 查询频率高的字段在前
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 排序字段在最后
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 3. 避免过多索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 每张表索引不超过 5 个
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 单个索引字段不超过 5 个
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="22-索引监控"&gt;&lt;a href="#22-%e7%b4%a2%e5%bc%95%e7%9b%91%e6%8e%a7" class="header-anchor"&gt;&lt;/a&gt;2.2 索引监控
&lt;/h3&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="c1"&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_schema&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_read&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_fetch&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table_io_waits_summary_by_index_usage&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;object_schema&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;your_database&amp;#39;&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_schema&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_name&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table_io_waits_summary_by_index_usage&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;object_schema&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;your_database&amp;#39;&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="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;index_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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="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;count_star&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;0&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;h2 id="三配置调优"&gt;&lt;a href="#%e4%b8%89%e9%85%8d%e7%bd%ae%e8%b0%83%e4%bc%98" class="header-anchor"&gt;&lt;/a&gt;三、配置调优
&lt;/h2&gt;&lt;h3 id="31-innodb-buffer-pool"&gt;&lt;a href="#31-innodb-buffer-pool" class="header-anchor"&gt;&lt;/a&gt;3.1 InnoDB Buffer Pool
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# my.cnf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Buffer Pool 大小，建议物理内存的 70-80%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_buffer_pool_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8G&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Buffer Pool 实例数，减少锁竞争&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_buffer_pool_instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Buffer Pool 预热&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_buffer_pool_dump_at_shutdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_buffer_pool_load_at_startup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="32-日志配置"&gt;&lt;a href="#32-%e6%97%a5%e5%bf%97%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;3.2 日志配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Redo Log 大小&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_log_file_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1G&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_log_buffer_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 刷盘策略&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1：每次提交都刷盘（最安全）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2：每次提交写入OS缓存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 0：每秒刷盘&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;innodb_flush_log_at_trx_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 双1配置（生产推荐）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;sync_binlog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="33-连接配置"&gt;&lt;a href="#33-%e8%bf%9e%e6%8e%a5%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;3.3 连接配置
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 最大连接数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;max_connections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 连接超时&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;wait_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;interactive_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;600&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 线程缓存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;thread_cache_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 表缓存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;table_open_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;4096&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;table_definition_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="34-查询缓存mysql-80-已移除"&gt;&lt;a href="#34-%e6%9f%a5%e8%af%a2%e7%bc%93%e5%ad%98mysql-80-%e5%b7%b2%e7%a7%bb%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;3.4 查询缓存（MySQL 8.0 已移除）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MySQL 5.7 及以下&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;query_cache_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0 # 建议关闭&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;query_cache_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="35-排序和临时表"&gt;&lt;a href="#35-%e6%8e%92%e5%ba%8f%e5%92%8c%e4%b8%b4%e6%97%b6%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;3.5 排序和临时表
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 排序缓冲区&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;sort_buffer_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;4M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# JOIN 缓冲区&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;join_buffer_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;4M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 临时表大小&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;tmp_table_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;max_heap_table_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 读缓冲区&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;read_buffer_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;read_rnd_buffer_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;8M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="四架构优化"&gt;&lt;a href="#%e5%9b%9b%e6%9e%b6%e6%9e%84%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;四、架构优化
&lt;/h2&gt;&lt;h3 id="41-读写分离"&gt;&lt;a href="#41-%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb" class="header-anchor"&gt;&lt;/a&gt;4.1 读写分离
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌─────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 应用程序 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └──────┬──────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌──────▼──────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 代理层 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ (ProxySQL) │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └──────┬──────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌──────────────┼──────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ┌──────▼──────┐ ┌────▼────┐ ┌───────▼──────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ Master │ │ Slave 1 │ │ Slave 2 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ (写) │ │ (读) │ │ (读) │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─────────────┘ └─────────┘ └──────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ProxySQL 配置示例：&lt;/strong&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="c1"&gt;-- 添加后端MySQL服务器
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mysql_servers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hostgroup_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;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;10.0.0.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 写组
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;10.0.0.2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 读组
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;10.0.0.3&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 读组
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&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;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mysql_query_rules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rule_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;match_pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;destination_hostgroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^SELECT.*FOR UPDATE&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 写操作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^SELECT&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 读操作
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="42-分库分表"&gt;&lt;a href="#42-%e5%88%86%e5%ba%93%e5%88%86%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;4.2 分库分表
&lt;/h3&gt;&lt;h4 id="垂直分库"&gt;&lt;a href="#%e5%9e%82%e7%9b%b4%e5%88%86%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;垂直分库
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;用户库 (user_db)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── users
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── user_profiles
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── user_settings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;订单库 (order_db)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── orders
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── order_items
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── payments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;商品库 (product_db)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── products
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── categories
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── inventory
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="水平分表"&gt;&lt;a href="#%e6%b0%b4%e5%b9%b3%e5%88%86%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;水平分表
&lt;/h4&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="c1"&gt;-- 按用户ID分表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;orders_0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- user_id % 4 = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;orders_1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- user_id % 4 = 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;orders_2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- user_id % 4 = 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;orders_3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- user_id % 4 = 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- ShardingSphere 配置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shardingsphere&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datasource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ds0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ds1&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="n"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shardingsphere&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ds$&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;orders_$&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;}&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="n"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shardingsphere&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharding&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;column&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&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="n"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shardingsphere&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sharding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;table&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;orders_$&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_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;4&lt;/span&gt;&lt;span class="err"&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;h3 id="43-缓存策略"&gt;&lt;a href="#43-%e7%bc%93%e5%ad%98%e7%ad%96%e7%95%a5" class="header-anchor"&gt;&lt;/a&gt;4.3 缓存策略
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌──────────┐ ┌──────────┐ ┌──────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ 应用程序 │───▶│ Redis │───▶│ MySQL │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└──────────┘ └──────────┘ └──────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 1.查询缓存 │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │──────────────▶│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 2.返回缓存 │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │◀──────────────│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 3.缓存未命中│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │──────────────────────────────▶│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 4.查询数据库│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │◀──────────────────────────────│
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ 5.写入缓存 │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │──────────────▶│ │
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;缓存更新策略：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Cache Aside Pattern&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="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 1. 先查缓存&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&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="s"&gt;&amp;#34;user:&amp;#34;&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="n"&gt;userId&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&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="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&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="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 2. 缓存未命中，查数据库&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&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="n"&gt;userMapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;selectById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 3. 写入缓存&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&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;span class="line"&gt;&lt;span class="cl"&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;h3 id="44-表设计优化"&gt;&lt;a href="#44-%e8%a1%a8%e8%ae%be%e8%ae%a1%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;4.4 表设计优化
&lt;/h3&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="c1"&gt;-- 1. 选择合适的数据类型
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;INT&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UNSIGNED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AUTO_INCREMENT&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TINYINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UNSIGNED&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;span class="line"&gt;&lt;span class="cl"&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="n"&gt;TINYINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;InnoDB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CHARSET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utf8mb4&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 2. 避免NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 使用 NOT NULL + DEFAULT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 3. 主键设计
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 使用自增ID作为主键
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 避免使用UUID作为主键（无序，影响插入性能）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="五监控与诊断"&gt;&lt;a href="#%e4%ba%94%e7%9b%91%e6%8e%a7%e4%b8%8e%e8%af%8a%e6%96%ad" class="header-anchor"&gt;&lt;/a&gt;五、监控与诊断
&lt;/h2&gt;&lt;h3 id="51-慢查询日志"&gt;&lt;a href="#51-%e6%85%a2%e6%9f%a5%e8%af%a2%e6%97%a5%e5%bf%97" class="header-anchor"&gt;&lt;/a&gt;5.1 慢查询日志
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[mysqld]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 开启慢查询日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;slow_query_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;slow_query_log_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/var/log/mysql/slow.log&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;long_query_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1 # 超过1秒记录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;log_queries_not_using_indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ON&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 分析慢查询日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mysqldumpslow -s t -t &lt;span class="m"&gt;10&lt;/span&gt; /var/log/mysql/slow.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使用 pt-query-digest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pt-query-digest /var/log/mysql/slow.log &amp;gt; slow_report.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="52-性能监控sql"&gt;&lt;a href="#52-%e6%80%a7%e8%83%bd%e7%9b%91%e6%8e%a7sql" class="header-anchor"&gt;&lt;/a&gt;5.2 性能监控SQL
&lt;/h3&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="c1"&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;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- 查看InnoDB状态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INNODB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;STATUS&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;table_schema&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;table_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_length&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;1024&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;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_mb&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index_length&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;1024&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;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_mb&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&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;table_schema&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;your_database&amp;#39;&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;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&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;span class="line"&gt;&lt;span class="cl"&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="c1"&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;SELECT&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="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_schema&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;index_name&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_star&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_read&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count_fetch&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table_io_waits_summary_by_index_usage&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;object_schema&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;your_database&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;h3 id="53-诊断工具"&gt;&lt;a href="#53-%e8%af%8a%e6%96%ad%e5%b7%a5%e5%85%b7" class="header-anchor"&gt;&lt;/a&gt;5.3 诊断工具
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Percona Toolkit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 安装&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install percona-toolkit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 分析慢查询&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pt-query-digest /var/log/mysql/slow.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 检查重复/冗余索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pt-duplicate-key-checker --host&lt;span class="o"&gt;=&lt;/span&gt;localhost --user&lt;span class="o"&gt;=&lt;/span&gt;root --password&lt;span class="o"&gt;=&lt;/span&gt;xxx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查看索引使用情况&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pt-index-usage --host&lt;span class="o"&gt;=&lt;/span&gt;localhost --user&lt;span class="o"&gt;=&lt;/span&gt;root --password&lt;span class="o"&gt;=&lt;/span&gt;xxx /var/log/mysql/slow.log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="六调优清单"&gt;&lt;a href="#%e5%85%ad%e8%b0%83%e4%bc%98%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;六、调优清单
&lt;/h2&gt;&lt;h3 id="61-sql-层面"&gt;&lt;a href="#61-sql-%e5%b1%82%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;6.1 SQL 层面
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 所有查询都使用了合适的索引&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 避免了 &lt;code&gt;SELECT *&lt;/code&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; 避免了深分页（LIMIT offset 过大）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; JOIN 查询关联字段有索引&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 避免了索引失效的写法&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="62-索引层面"&gt;&lt;a href="#62-%e7%b4%a2%e5%bc%95%e5%b1%82%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;6.2 索引层面
&lt;/h3&gt;&lt;ul&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; 区分度低的字段不建索引&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;/ul&gt;
&lt;h3 id="63-配置层面"&gt;&lt;a href="#63-%e9%85%8d%e7%bd%ae%e5%b1%82%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;6.3 配置层面
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Buffer Pool 设置为物理内存的 70-80%&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; 配置合适的日志刷盘策略&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="64-架构层面"&gt;&lt;a href="#64-%e6%9e%b6%e6%9e%84%e5%b1%82%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;6.4 架构层面
&lt;/h3&gt;&lt;ul&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; 引入缓存层（热点数据）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 表设计规范化&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;MySQL 调优是一个系统工程，需要从多个维度综合考虑：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SQL 优化是基础&lt;/strong&gt;：写好 SQL 是最直接的优化手段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;索引设计是核心&lt;/strong&gt;：合理的索引能提升查询性能数倍&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置调优是保障&lt;/strong&gt;：正确的配置能最大化硬件利用率&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;架构优化是根本&lt;/strong&gt;：当单机瓶颈时，架构扩展是必由之路&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;建议按照本文的调优清单逐步检查，结合监控数据持续优化。&lt;/p&gt;</description></item><item><title>达梦数据库 DM8 与 MySQL 差异全解析：迁移避坑指南</title><link>https://blog.waihost.com/posts/dm8-vs-mysql-migration-guide/</link><pubDate>Wed, 24 Jun 2026 11:00:00 +0000</pubDate><guid>https://blog.waihost.com/posts/dm8-vs-mysql-migration-guide/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/dm8-vs-mysql-migration-guide.svg" alt="Featured image of post 达梦数据库 DM8 与 MySQL 差异全解析：迁移避坑指南" /&gt;&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;随着国内信创（信息技术应用创新）政策的推进，越来越多的项目需要从 MySQL 迁移到国产数据库。&lt;strong&gt;达梦数据库（DM8）&lt;/strong&gt; 是最主流的国产关系型数据库之一，兼容大部分 SQL 标准，但与 MySQL 在语法、函数、数据类型等方面仍存在不少差异。&lt;/p&gt;
&lt;p&gt;本文从实际迁移角度出发，系统梳理 DM8 与 MySQL 的核心差异，帮助开发者少踩坑。&lt;/p&gt;
&lt;h2 id="1-架构差异"&gt;&lt;a href="#1-%e6%9e%b6%e6%9e%84%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;1. 架构差异
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;对比项&lt;/th&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;达梦 DM8&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;数据库模型&lt;/td&gt;
					&lt;td&gt;单实例多数据库（&lt;code&gt;database&lt;/code&gt;）&lt;/td&gt;
					&lt;td&gt;单数据库多 Schema（一个用户对应一个 Schema）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;默认端口&lt;/td&gt;
					&lt;td&gt;3306&lt;/td&gt;
					&lt;td&gt;5236&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;存储引擎&lt;/td&gt;
					&lt;td&gt;InnoDB / MyISAM 等可选&lt;/td&gt;
					&lt;td&gt;单一存储引擎&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;大小写&lt;/td&gt;
					&lt;td&gt;默认不区分（可配置）&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;默认区分大小写&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;空字符串&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;''&lt;/code&gt; 和 &lt;code&gt;NULL&lt;/code&gt; 是不同的&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;''&lt;/code&gt; 等同于 &lt;code&gt;NULL&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

 &lt;blockquote&gt;
 &lt;p&gt;⚠️ &lt;strong&gt;重点注意&lt;/strong&gt;：DM8 中空字符串 &lt;code&gt;''&lt;/code&gt; 就是 &lt;code&gt;NULL&lt;/code&gt;，这是迁移中最容易踩的坑。MySQL 中 &lt;code&gt;WHERE col = ''&lt;/code&gt; 和 &lt;code&gt;WHERE col IS NULL&lt;/code&gt; 结果完全不同，在 DM8 中两者等价。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="2-数据类型映射"&gt;&lt;a href="#2-%e6%95%b0%e6%8d%ae%e7%b1%bb%e5%9e%8b%e6%98%a0%e5%b0%84" class="header-anchor"&gt;&lt;/a&gt;2. 数据类型映射
&lt;/h2&gt;&lt;h3 id="21-数值类型"&gt;&lt;a href="#21-%e6%95%b0%e5%80%bc%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;2.1 数值类型
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;TINYINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TINYINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;MEDIUMINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 无 MEDIUMINT&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DOUBLE&lt;/code&gt; / &lt;code&gt;NUMBER&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;建议用 DOUBLE&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DECIMAL(p,s)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NUMBER(p,s)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;精度一致&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="22-字符串类型"&gt;&lt;a href="#22-%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;2.2 字符串类型
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CHAR(n)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CHAR(n)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;VARCHAR(n)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;VARCHAR2(n)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 推荐用 VARCHAR2&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;TEXT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLOB&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;大文本用 CLOB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;MEDIUMTEXT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLOB&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LONGTEXT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLOB&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ENUM&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;VARCHAR2&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 无 ENUM，存为字符串&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SET&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;VARCHAR2&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 无 SET&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="23-日期时间类型"&gt;&lt;a href="#23-%e6%97%a5%e6%9c%9f%e6%97%b6%e9%97%b4%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;2.3 日期时间类型
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;MySQL 只存日期，DM 的 DATE &lt;strong&gt;包含时间&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATETIME&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt; / &lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 的 DATE 就带时间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 支持 TIME 类型，可直接映射&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;YEAR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CHAR(4)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 无 YEAR 类型&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="24-其他类型"&gt;&lt;a href="#24-%e5%85%b6%e4%bb%96%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;2.4 其他类型
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;BLOB&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BLOB&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLOB&lt;/code&gt; / &lt;code&gt;JSONB&lt;/code&gt;（新版本）&lt;/td&gt;
					&lt;td&gt;旧版用 CLOB 存储&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BIT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;AUTO_INCREMENT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;IDENTITY(1,1)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;自增语法不同&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="3-函数差异对照"&gt;&lt;a href="#3-%e5%87%bd%e6%95%b0%e5%b7%ae%e5%bc%82%e5%af%b9%e7%85%a7" class="header-anchor"&gt;&lt;/a&gt;3. 函数差异对照
&lt;/h2&gt;&lt;p&gt;这是迁移中改动量最大的部分。&lt;/p&gt;
&lt;h3 id="31-字符串函数"&gt;&lt;a href="#31-%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;3.1 字符串函数
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CONCAT(a, b)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;a || b&lt;/code&gt; 或 &lt;code&gt;CONCAT(a, b)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 推荐用 &lt;code&gt;||&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SUBSTRING(str, pos, len)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SUBSTR(str, pos, len)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;少了个 &lt;code&gt;ING&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;LOCATE(sub, str)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;INSTR(str, sub)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;参数顺序相反&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GROUP_CONCAT(col)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;LISTAGG(col, ',') WITHIN GROUP (ORDER BY col)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;语法差异大&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;REPLACE(str, old, new)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;REPLACE(str, old, new)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="32-日期函数"&gt;&lt;a href="#32-%e6%97%a5%e6%9c%9f%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;3.2 日期函数
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;NOW()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SYSDATE&lt;/code&gt; 或 &lt;code&gt;CURRENT_TIMESTAMP&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CURDATE()&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CURRENT_DATE&lt;/code&gt; 或 &lt;code&gt;SYSDATE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATE_FORMAT(d, '%Y-%m-%d')&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TO_CHAR(d, 'YYYY-MM-DD')&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;格式化语法不同&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;STR_TO_DATE(s, '%Y-%m-%d')&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;TO_DATE(s, 'YYYY-MM-DD')&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATE_ADD(d, INTERVAL 1 DAY)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;d + 1&lt;/code&gt; 或 &lt;code&gt;ADD_DAYS(d, 1)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATE_SUB(d, INTERVAL 1 MONTH)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ADD_MONTHS(d, -1)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DATEDIFF(d1, d2)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;d1 - d2&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 直接相减&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;YEAR(d)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;EXTRACT(YEAR FROM d)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;MONTH(d)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;EXTRACT(MONTH FROM d)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="33-条件与空值函数"&gt;&lt;a href="#33-%e6%9d%a1%e4%bb%b6%e4%b8%8e%e7%a9%ba%e5%80%bc%e5%87%bd%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;3.3 条件与空值函数
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;IF(cond, v1, v2)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CASE WHEN cond THEN v1 ELSE v2 END&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;DM 无 IF 函数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;IFNULL(expr, default)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;NVL(expr, default)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;也可用 COALESCE&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;IFNULL&lt;/code&gt; 多层嵌套&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;COALESCE(a, b, c)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;推荐用 COALESCE&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="34-类型转换"&gt;&lt;a href="#34-%e7%b1%bb%e5%9e%8b%e8%bd%ac%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;3.4 类型转换
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CONVERT(expr, type)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CONVERT(type, expr)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;参数顺序相反&lt;/strong&gt; ⚠️&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;CAST(expr AS type)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CAST(expr AS type)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;兼容&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="4-sql-语法差异"&gt;&lt;a href="#4-sql-%e8%af%ad%e6%b3%95%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;4. SQL 语法差异
&lt;/h2&gt;&lt;h3 id="41-自增主键"&gt;&lt;a href="#41-%e8%87%aa%e5%a2%9e%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;4.1 自增主键
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&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="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- DM8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IDENTITY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&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;span class="line"&gt;&lt;span class="cl"&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="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;span class="line"&gt;&lt;span class="cl"&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;h3 id="42-分页查询"&gt;&lt;a href="#42-%e5%88%86%e9%a1%b5%e6%9f%a5%e8%af%a2" class="header-anchor"&gt;&lt;/a&gt;4.2 分页查询
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OFFSET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8（兼容 LIMIT 或使用 ROWNUM）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OFFSET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8 传统写法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &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;span class="line"&gt;&lt;span class="cl"&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;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROWNUM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rn&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="p"&gt;(&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="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="o"&gt;*&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&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="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ROWNUM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&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="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&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;blockquote&gt;
 &lt;p&gt;DM8 较新版本已支持 &lt;code&gt;LIMIT offset, count&lt;/code&gt; 语法，但 &lt;code&gt;ROWNUM&lt;/code&gt; 仍是 DM 的保留关键字，不要用作列名。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="43-多行插入"&gt;&lt;a href="#43-%e5%a4%9a%e8%a1%8c%e6%8f%92%e5%85%a5" class="header-anchor"&gt;&lt;/a&gt;4.3 多行插入
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Charlie&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ALL&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Alice&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bob&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Charlie&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;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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="n"&gt;dual&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;h3 id="44-多表更新"&gt;&lt;a href="#44-%e5%a4%9a%e8%a1%a8%e6%9b%b4%e6%96%b0" class="header-anchor"&gt;&lt;/a&gt;4.4 多表更新
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;col&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="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;t2&lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8（使用 MERGE INTO）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;MERGE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;USING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;t2&lt;/span&gt;&lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MATCHED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;THEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;col&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="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;col&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;h3 id="45-多表删除"&gt;&lt;a href="#45-%e5%a4%9a%e8%a1%a8%e5%88%a0%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;4.5 多表删除
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&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="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;t2&lt;/span&gt;&lt;span class="p"&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="mi"&gt;0&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;DELETE&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="n"&gt;t1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&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="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="n"&gt;t2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&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="mi"&gt;0&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;h3 id="46-修改列名"&gt;&lt;a href="#46-%e4%bf%ae%e6%94%b9%e5%88%97%e5%90%8d" class="header-anchor"&gt;&lt;/a&gt;4.6 修改列名
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CHANGE&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="n"&gt;full_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;RENAME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COLUMN&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;TO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;full_name&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;h3 id="47-删除列"&gt;&lt;a href="#47-%e5%88%a0%e9%99%a4%e5%88%97" class="header-anchor"&gt;&lt;/a&gt;4.7 删除列
&lt;/h3&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="c1"&gt;-- MySQL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DROP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COLUMN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DROP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&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;h2 id="5-group-by-语义差异重要"&gt;&lt;a href="#5-group-by-%e8%af%ad%e4%b9%89%e5%b7%ae%e5%bc%82%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;5. GROUP BY 语义差异（重要！）
&lt;/h2&gt;&lt;p&gt;这是迁移中&lt;strong&gt;最容易出 bug&lt;/strong&gt; 的地方。&lt;/p&gt;
&lt;h3 id="51-mysql-的宽松模式"&gt;&lt;a href="#51-mysql-%e7%9a%84%e5%ae%bd%e6%9d%be%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;5.1 MySQL 的宽松模式
&lt;/h3&gt;&lt;p&gt;MySQL 默认允许 &lt;code&gt;SELECT&lt;/code&gt; 中出现未在 &lt;code&gt;GROUP BY&lt;/code&gt; 中声明的非聚合列（&lt;code&gt;ONLY_FULL_GROUP_BY&lt;/code&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="c1"&gt;-- MySQL 可以执行（但结果不确定）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;department&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;h3 id="52-dm8-的严格模式"&gt;&lt;a href="#52-dm8-%e7%9a%84%e4%b8%a5%e6%a0%bc%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;5.2 DM8 的严格模式
&lt;/h3&gt;&lt;p&gt;DM8 严格执行 SQL 标准，&lt;code&gt;SELECT&lt;/code&gt; 中的非聚合列必须出现在 &lt;code&gt;GROUP BY&lt;/code&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="c1"&gt;-- DM8 必须这样写
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;department&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;h3 id="53-group-by-主键--distinct"&gt;&lt;a href="#53-group-by-%e4%b8%bb%e9%94%ae--distinct" class="header-anchor"&gt;&lt;/a&gt;5.3 GROUP BY 主键 ≠ DISTINCT
&lt;/h3&gt;&lt;p&gt;迁移时不要轻易把 &lt;code&gt;GROUP BY id&lt;/code&gt; 改成 &lt;code&gt;SELECT DISTINCT&lt;/code&gt;，当 JOIN 导致行数膨胀时，两者结果不同。&lt;/p&gt;
&lt;h2 id="6-其他语义陷阱"&gt;&lt;a href="#6-%e5%85%b6%e4%bb%96%e8%af%ad%e4%b9%89%e9%99%b7%e9%98%b1" class="header-anchor"&gt;&lt;/a&gt;6. 其他语义陷阱
&lt;/h2&gt;&lt;h3 id="61-别名引用"&gt;&lt;a href="#61-%e5%88%ab%e5%90%8d%e5%bc%95%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;6.1 别名引用
&lt;/h3&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="c1"&gt;-- MySQL：HAVING 可以引用 SELECT 别名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alias_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnt&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alias_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;HAVING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8：HAVING 不能引用别名，必须用原始表达式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alias_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cnt&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&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;HAVING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&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;h3 id="62-别名引号"&gt;&lt;a href="#62-%e5%88%ab%e5%90%8d%e5%bc%95%e5%8f%b7" class="header-anchor"&gt;&lt;/a&gt;6.2 别名引号
&lt;/h3&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="c1"&gt;-- MySQL：单引号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;姓名&amp;#39;&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="n"&gt;users&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8：双引号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;姓名&amp;#34;&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="n"&gt;users&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;h3 id="63-隐式类型转换"&gt;&lt;a href="#63-%e9%9a%90%e5%bc%8f%e7%b1%bb%e5%9e%8b%e8%bd%ac%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;6.3 隐式类型转换
&lt;/h3&gt;&lt;p&gt;DM8 类型检查更严格，字符串列与数字比较会报错：&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="c1"&gt;-- MySQL 可以执行（隐式转换）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phone&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;13800138000&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;span class="line"&gt;&lt;span class="cl"&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="c1"&gt;-- DM8 必须类型一致
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;phone&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;13800138000&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;h2 id="7-jdbc-连接配置"&gt;&lt;a href="#7-jdbc-%e8%bf%9e%e6%8e%a5%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;7. JDBC 连接配置
&lt;/h2&gt;&lt;h3 id="71-驱动配置"&gt;&lt;a href="#71-%e9%a9%b1%e5%8a%a8%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;7.1 驱动配置
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;配置项&lt;/th&gt;
					&lt;th&gt;MySQL&lt;/th&gt;
					&lt;th&gt;DM8&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;驱动类&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;com.mysql.cj.jdbc.Driver&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;dm.jdbc.driver.DmDriver&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;JDBC URL&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;jdbc:mysql://host:3306/db&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;jdbc:dm://host:5236&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;默认端口&lt;/td&gt;
					&lt;td&gt;3306&lt;/td&gt;
					&lt;td&gt;5236&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="72-hibernate--mybatis-方言"&gt;&lt;a href="#72-hibernate--mybatis-%e6%96%b9%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;7.2 Hibernate / MyBatis 方言
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-properties" data-lang="properties"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MySQL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.datasource.driver-class-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://localhost:3306/mydb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.jpa.database-platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.hibernate.dialect.MySQLDialect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# DM8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.datasource.driver-class-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dm.jdbc.driver.DmDriver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:dm://localhost:5236&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;spring.jpa.database-platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dm.hibernate.dialect.DmDialect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="73-指定-schema"&gt;&lt;a href="#73-%e6%8c%87%e5%ae%9a-schema" class="header-anchor"&gt;&lt;/a&gt;7.3 指定 Schema
&lt;/h3&gt;&lt;p&gt;DM8 默认一个用户对应一个 Schema，连接时可以通过 JDBC 参数指定：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jdbc:dm://localhost:5236?schema&lt;span class="o"&gt;=&lt;/span&gt;MY_SCHEMA
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="8-建库注意事项"&gt;&lt;a href="#8-%e5%bb%ba%e5%ba%93%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;8. 建库注意事项
&lt;/h2&gt;&lt;p&gt;DM8 一个实例即对应一个数据库，&lt;strong&gt;字符集在实例初始化（&lt;code&gt;dminit&lt;/code&gt;）阶段确定，之后不可更改&lt;/strong&gt;，没有 MySQL 那样的 &lt;code&gt;CREATE DATABASE ... CHARSET=&lt;/code&gt; 语句。务必在初始化时就选择 UTF-8：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 初始化实例时指定字符集（CHARSET：0=GB18030，1=UTF-8，2=EUC-KR）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dminit &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dm/data &lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mydb &lt;span class="nv"&gt;INSTANCE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mydb &lt;span class="nv"&gt;CHARSET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;PAGE_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果字符集选错，中文数据会出现乱码，且修改成本很高。&lt;/p&gt;
&lt;h2 id="9-迁移工具推荐"&gt;&lt;a href="#9-%e8%bf%81%e7%a7%bb%e5%b7%a5%e5%85%b7%e6%8e%a8%e8%8d%90" class="header-anchor"&gt;&lt;/a&gt;9. 迁移工具推荐
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;方向&lt;/th&gt;
					&lt;th&gt;语言&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://github.com/Greenplumwine/sql-dialect-adapter" target="_blank" rel="noopener"
 &gt;sql-dialect-adapter&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;MySQL ↔ DM&lt;/td&gt;
					&lt;td&gt;Java&lt;/td&gt;
					&lt;td&gt;SQL 方言自动转换，支持 6 个方向&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://github.com/mcmartin666/MySQL2DM" target="_blank" rel="noopener"
 &gt;MySQL2DM&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;MySQL → DM&lt;/td&gt;
					&lt;td&gt;Python&lt;/td&gt;
					&lt;td&gt;多线程数据迁移，自动类型映射&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://github.com/Tumicc/DM2MySQL" target="_blank" rel="noopener"
 &gt;DM2MySQL&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;DM → MySQL&lt;/td&gt;
					&lt;td&gt;Go&lt;/td&gt;
					&lt;td&gt;企业级反向迁移工具&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;a class="link" href="https://github.com/whigg/mysqltodmsqltransfer" target="_blank" rel="noopener"
 &gt;mysqltodmsqltransfer&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;MySQL → DM&lt;/td&gt;
					&lt;td&gt;Java&lt;/td&gt;
					&lt;td&gt;MyBatis 插件，运行时自动转换 SQL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DM 数据迁移工具 (DTS)&lt;/td&gt;
					&lt;td&gt;多种 → DM&lt;/td&gt;
					&lt;td&gt;GUI&lt;/td&gt;
					&lt;td&gt;达梦官方工具，图形化操作&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="10-迁移检查清单"&gt;&lt;a href="#10-%e8%bf%81%e7%a7%bb%e6%a3%80%e6%9f%a5%e6%b8%85%e5%8d%95" class="header-anchor"&gt;&lt;/a&gt;10. 迁移检查清单
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 建库时选择 UTF-8 字符集&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;AUTO_INCREMENT&lt;/code&gt; 改为 &lt;code&gt;IDENTITY(1,1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;VARCHAR&lt;/code&gt; 改为 &lt;code&gt;VARCHAR2&lt;/code&gt;，&lt;code&gt;TEXT&lt;/code&gt; 改为 &lt;code&gt;CLOB&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;NOW()&lt;/code&gt; 改为 &lt;code&gt;SYSDATE&lt;/code&gt;，&lt;code&gt;DATE_FORMAT&lt;/code&gt; 改为 &lt;code&gt;TO_CHAR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;GROUP_CONCAT&lt;/code&gt; 改为 &lt;code&gt;LISTAGG&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;IF()&lt;/code&gt; 改为 &lt;code&gt;CASE WHEN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;code&gt;IFNULL()&lt;/code&gt; 改为 &lt;code&gt;NVL()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 检查所有 &lt;code&gt;GROUP BY&lt;/code&gt; 语句是否符合严格模式&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 检查空字符串 &lt;code&gt;''&lt;/code&gt; 的业务逻辑（DM 中等同于 NULL）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 检查隐式类型转换（字符串 vs 数字比较）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 更新 JDBC 驱动和连接 URL&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 更新 ORM 方言配置（Hibernate / MyBatis）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 测试分页查询是否兼容&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; 测试多行 INSERT、多表 UPDATE/DELETE 语法&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Docker 安装达梦 DM8</title><link>https://blog.waihost.com/posts/docker-install-dm8/</link><pubDate>Tue, 28 Apr 2026 10:00:00 +0000</pubDate><guid>https://blog.waihost.com/posts/docker-install-dm8/</guid><description>&lt;img src="https://blog.waihost.com/images/covers/docker-install-dm8.svg" alt="Featured image of post Docker 安装达梦 DM8" /&gt;&lt;h2 id="背景"&gt;&lt;a href="#%e8%83%8c%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;背景
&lt;/h2&gt;&lt;p&gt;近期开源项目 SmartAdmin 的很多用户反馈需要支持达梦数据库，现在将 docker 安装达梦数据库记录下来，以便让更多有需要的技术人员看到，节省时间。&lt;/p&gt;
&lt;h2 id="1提前准备"&gt;&lt;a href="#1%e6%8f%90%e5%89%8d%e5%87%86%e5%a4%87" class="header-anchor"&gt;&lt;/a&gt;1、提前准备
&lt;/h2&gt;&lt;p&gt;环境为：Linux 系统 CentOS 8，达梦数据库为达梦 DM8 版本，单机版。&lt;/p&gt;
&lt;h2 id="2下载达梦镜像"&gt;&lt;a href="#2%e4%b8%8b%e8%bd%bd%e8%be%be%e6%a2%a6%e9%95%9c%e5%83%8f" class="header-anchor"&gt;&lt;/a&gt;2、下载达梦镜像
&lt;/h2&gt;&lt;p&gt;达梦官方下载地址为：&lt;a class="link" href="https://eco.dameng.com/download/" target="_blank" rel="noopener"
 &gt;eco.dameng.com/download/&lt;/a&gt;，可能已经不提供 Docker 镜像下载。&lt;/p&gt;
&lt;p&gt;所以请从笔者百度网盘下载：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;链接: &lt;a class="link" href="https://pan.baidu.com/s/1SsQK7mlJjSlkTLFBZOFsKg" target="_blank" rel="noopener"
 &gt;pan.baidu.com/s/1SsQK7mlJ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;提取码: &lt;code&gt;d83h&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;下载文件：&lt;code&gt;dm8_20240715_x86_rh6_rq_single.tar.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="3上传并解压"&gt;&lt;a href="#3%e4%b8%8a%e4%bc%a0%e5%b9%b6%e8%a7%a3%e5%8e%8b" class="header-anchor"&gt;&lt;/a&gt;3、上传并解压
&lt;/h2&gt;&lt;p&gt;1）将 &lt;code&gt;dm8_20240715_x86_rh6_rq_single.tar.zip&lt;/code&gt; 上传到 Linux 服务器 CentOS 中&lt;/p&gt;
&lt;p&gt;2）将其解压：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;unzip dm8_20240715_x86_rh6_rq_single.tar.zip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="4加载-dm8-镜像到-docker-中"&gt;&lt;a href="#4%e5%8a%a0%e8%bd%bd-dm8-%e9%95%9c%e5%83%8f%e5%88%b0-docker-%e4%b8%ad" class="header-anchor"&gt;&lt;/a&gt;4、加载 DM8 镜像到 Docker 中
&lt;/h2&gt;&lt;p&gt;1）进入镜像 &lt;code&gt;dm8_20240715_x86_rh6_rq_single.tar&lt;/code&gt; 文件所在目录&lt;/p&gt;
&lt;p&gt;2）执行加载命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker load -i dm8_20240715_x86_rh6_rq_single.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3）检查是否成功加载 DM8 镜像：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker images
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="5明确启动容器参数"&gt;&lt;a href="#5%e6%98%8e%e7%a1%ae%e5%90%af%e5%8a%a8%e5%ae%b9%e5%99%a8%e5%8f%82%e6%95%b0" class="header-anchor"&gt;&lt;/a&gt;5、明确启动容器参数
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;端口 &lt;code&gt;15236&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;容器名字 &lt;code&gt;dm8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不开启大小写敏感 &lt;code&gt;-e CASE_SENSITIVE=0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;数据映射目录：&lt;code&gt;/home/database/dm8/data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;字符集 UTF-8 &lt;code&gt;-e UNICODE_FLAG=1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;实例名称 &lt;code&gt;-e INSTANCE_NAME=dm8_smartadmin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终明确启动参数如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -dit &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-p 15236:5236 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--restart&lt;span class="o"&gt;=&lt;/span&gt;always &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--name dm8 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--privileged&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;PAGE_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/dmdbms/bin &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;EXTENT_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;32&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;BLANK_PAD_MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;LOG_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;UNICODE_FLAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;LENGTH_IN_CHAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;CASE_SENSITIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;INSTANCE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dm8_smartadmin &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-v /home/database/dm8/data:/opt/dmdbms/data &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dm8_single:dm8_20240715_rev232765_x86_rh6_64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="6启动容器"&gt;&lt;a href="#6%e5%90%af%e5%8a%a8%e5%ae%b9%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;6、启动容器
&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-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker ps
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="7启动停止重启"&gt;&lt;a href="#7%e5%90%af%e5%8a%a8%e5%81%9c%e6%ad%a2%e9%87%8d%e5%90%af" class="header-anchor"&gt;&lt;/a&gt;7、启动/停止/重启
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker stop dm8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker start dm8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker restart dm8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="8进入容器"&gt;&lt;a href="#8%e8%bf%9b%e5%85%a5%e5%ae%b9%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;8、进入容器
&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-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it dm8 bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="9其他注意事项"&gt;&lt;a href="#9%e5%85%b6%e4%bb%96%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9" class="header-anchor"&gt;&lt;/a&gt;9、其他注意事项
&lt;/h2&gt;&lt;p&gt;Docker 镜像中数据库默认用户名/密码为 &lt;code&gt;SYSDBA/SYSDBA001&lt;/code&gt;&lt;/p&gt;</description></item></channel></rss>