<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Major-Upgrade on Tarragon</title><link>https://tarrragon.github.io/blog/tags/major-upgrade/</link><description>Recent content in Major-Upgrade on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 19 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/major-upgrade/index.xml" rel="self" type="application/rss+xml"/><item><title>MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/major-version-upgrade/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/major-version-upgrade/</guid><description>&lt;blockquote>
&lt;p>本文是 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL&lt;/a> 內 version upgrade migration playbook、走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology&lt;/a> Type E paradigm shift 結構。&lt;/p>&lt;/blockquote>
&lt;p>5.7 → 8.0 看起來是 &lt;em>minor bump&lt;/em>（從 5.7.40 升到 8.0.36）、但不是。Oracle 把這個 release boundary 當成 &lt;em>清庫存的機會&lt;/em> — 同時推出 3 個 &lt;em>behavioral paradigm shift&lt;/em>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Paradigm&lt;/th>
 &lt;th>5.7 default&lt;/th>
 &lt;th>8.0 default&lt;/th>
 &lt;th>影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Character set&lt;/td>
 &lt;td>latin1 / utf8（=utf8mb3）&lt;/td>
 &lt;td>utf8mb4&lt;/td>
 &lt;td>string column 儲存 + emoji / 4-byte UTF-8&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Authentication plugin&lt;/td>
 &lt;td>mysql_native_password&lt;/td>
 &lt;td>caching_sha2_password&lt;/td>
 &lt;td>client / library 需要支援新 plugin&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DDL atomicity&lt;/td>
 &lt;td>Non-atomic（crash 留 orphan）&lt;/td>
 &lt;td>Atomic（crash recovery 乾淨）&lt;/td>
 &lt;td>開發信心、crash recovery 行為&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>對應 &lt;em>任意一個&lt;/em> paradigm 升級失誤、production 都會 down。三條同時換、必須 &lt;em>三條都規劃&lt;/em>。&lt;/p>
&lt;p>這條 upgrade 比 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &amp;#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL major-version-upgrade&lt;/a> 工作量大 — PG major upgrade 主要是 &lt;em>pg_upgrade&lt;/em> 工具流程、MySQL 是 &lt;em>behavioral compatibility audit + ecosystem 全 review&lt;/em>。&lt;/p>
&lt;h2 id="為什麼是-type-e不是-minor-upgrade">為什麼是 Type E（不是 minor upgrade）&lt;/h2>
&lt;p>跑 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit&lt;/a>：&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是 <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a> 內 version upgrade migration playbook、走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration playbook methodology</a> Type E paradigm shift 結構。</p></blockquote>
<p>5.7 → 8.0 看起來是 <em>minor bump</em>（從 5.7.40 升到 8.0.36）、但不是。Oracle 把這個 release boundary 當成 <em>清庫存的機會</em> — 同時推出 3 個 <em>behavioral paradigm shift</em>：</p>
<table>
  <thead>
      <tr>
          <th>Paradigm</th>
          <th>5.7 default</th>
          <th>8.0 default</th>
          <th>影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Character set</td>
          <td>latin1 / utf8（=utf8mb3）</td>
          <td>utf8mb4</td>
          <td>string column 儲存 + emoji / 4-byte UTF-8</td>
      </tr>
      <tr>
          <td>Authentication plugin</td>
          <td>mysql_native_password</td>
          <td>caching_sha2_password</td>
          <td>client / library 需要支援新 plugin</td>
      </tr>
      <tr>
          <td>DDL atomicity</td>
          <td>Non-atomic（crash 留 orphan）</td>
          <td>Atomic（crash recovery 乾淨）</td>
          <td>開發信心、crash recovery 行為</td>
      </tr>
  </tbody>
</table>
<p>對應 <em>任意一個</em> paradigm 升級失誤、production 都會 down。三條同時換、必須 <em>三條都規劃</em>。</p>
<p>這條 upgrade 比 <a href="/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL major-version-upgrade</a> 工作量大 — PG major upgrade 主要是 <em>pg_upgrade</em> 工具流程、MySQL 是 <em>behavioral compatibility audit + ecosystem 全 review</em>。</p>
<h2 id="為什麼是-type-e不是-minor-upgrade">為什麼是 Type E（不是 minor upgrade）</h2>
<p>跑 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/#%e5%af%ab%e5%89%8d%e7%9a%84-diff-dimension-audit" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">6 維 diff dimension audit</a>：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>評</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>Medium</td>
          <td>SQL 一致、reserved keyword 新增、collation 預設變</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>Medium-High</td>
          <td>binary upgrade flow 簡單、但 ecosystem 工具兼容性 audit 工作量大</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>3 條 default paradigm shift（charset / auth / atomic DDL）</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>同 MySQL 引擎、不引新 component</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Medium-High</td>
          <td>client library / driver / connection string 都可能要改</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>部署 topology 不變</td>
      </tr>
  </tbody>
</table>
<p>Paradigm = High + App change = Medium-High → <strong>Type E paradigm shift</strong>。</p>
<p>雖然是 <em>同一個 vendor 的 major version</em>、實際的 <em>application 行為差異</em> 跨越多個 paradigm、6 type 框架仍適用、結構走 partial migration 收斂。</p>
<h2 id="4-phase-upgrade">4-phase upgrade</h2>
<h3 id="phase-1pre-check-audit">Phase 1：Pre-check audit</h3>
<p>8.0 升級前用 <em>MySQL Shell upgrade checker</em> + 手動 audit：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mysqlsh root@5.7-primary.example.com -- util check-for-server-upgrade</span></span></code></pre></div><p>Upgrade checker 報告：</p>
<ul>
<li><em>Reserved keyword</em> 衝突（5.7 不是 keyword 但 8.0 是、例如 <code>WINDOW</code> / <code>RANK</code> / <code>LATERAL</code>）</li>
<li>舊 character set / collation 使用點（latin1 / utf8mb3）</li>
<li>Deprecated feature 使用（GROUP BY 隱含 ORDER BY 等）</li>
<li>Datatype 變動（DATETIME 行為微差）</li>
</ul>
<p>手動 audit：</p>
<ul>
<li>Application driver / library 版本是否支援 caching_sha2_password</li>
<li>Connection string 內 <code>default-authentication-plugin</code> 設定</li>
<li>ORM / framework 是否假設 utf8 而非 utf8mb4</li>
</ul>
<p>完成標準：寫出 <em>blocker list</em>（必須在升級前修） + <em>warning list</em>（可在升級後處理）。</p>
<h3 id="phase-2shadow-upgrade--replica-升-80">Phase 2：Shadow upgrade — Replica 升 8.0</h3>
<p>從 <em>non-critical replica</em> 升起。先升一個 replica、跑 production traffic（read-only）2-4 週：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. Stop replica</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">systemctl stop mysql
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. Backup（XtraBackup）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">xtrabackup --backup --target-dir<span class="o">=</span>/backup/pre-upgrade
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 3. Install MySQL 8.0 binary（apt / yum 升級）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">apt-get install mysql-server-8.0
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 4. 啟動 8.0、自動 upgrade data dictionary</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">systemctl start mysql
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 5. 8.0 自動跑 server-upgrade（8.0.16+ 內建、mysql_upgrade utility 已 deprecated）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 若 5.7 升 8.0.16 之前 server、才需要手動跑 mysql_upgrade -u root -p</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 6. 重新 attach 為 5.7 primary 的 replica（8.0 replica 可 attach 5.7 primary）</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">CHANGE MASTER TO <span class="nv">MASTER_AUTO_POSITION</span><span class="o">=</span>1<span class="p">;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">START SLAVE<span class="p">;</span></span></span></code></pre></div><p>跑 production read traffic 觀察：</p>
<ul>
<li>Query result 是否跟 5.7 一致（特別 character set 相關）</li>
<li>Replication lag 是否在 baseline 範圍</li>
<li>8.0-specific feature 是否需要（hash join / window function 等）</li>
</ul>
<h3 id="phase-3promote-80-為-primary">Phase 3：Promote 8.0 為 primary</h3>
<p>確認 shadow replica 穩定後：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. 升其他 replica 到 8.0</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"># （per-replica 跑 Phase 2 流程）</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. Application application 改用 8.0-compatible driver</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 把 connection string 加 default-authentication-plugin=caching_sha2_password</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 或仍用 mysql_native_password（user 端設定）</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 3. Failover：promote 8.0 replica 為 primary</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 用 Orchestrator / 自管 failover 流程</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 4. 5.7 primary 變成 8.0 replica、升 5.7 → 8.0</span></span></span></code></pre></div><p>完成標準：所有 server 都是 8.0、application 連 8.0 endpoint 無 error。</p>
<h3 id="phase-4decommission-57--套用-80-paradigm">Phase 4：Decommission 5.7 + 套用 8.0 paradigm</h3>
<p>完成 binary upgrade 不是真正完成 — 還要逐步遷移 paradigm：</p>
<ul>
<li>
<p><strong>Character set 升級</strong>：歷史 latin1 / utf8 table 改 utf8mb4</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">orders</span><span class="w"> </span><span class="k">CONVERT</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="nb">CHARACTER</span><span class="w"> </span><span class="k">SET</span><span class="w"> </span><span class="n">utf8mb4</span><span class="w"> </span><span class="k">COLLATE</span><span class="w"> </span><span class="n">utf8mb4_0900_ai_ci</span><span class="p">;</span></span></span></code></pre></div><p>每張 table 走 gh-ost / pt-osc（避免 production 阻塞）</p>
</li>
<li>
<p><strong>Authentication 升級</strong>：逐步把 user 從 <code>mysql_native_password</code> 改 <code>caching_sha2_password</code></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">USER</span><span class="w"> </span><span class="s1">&#39;app&#39;</span><span class="o">@</span><span class="s1">&#39;%&#39;</span><span class="w"> </span><span class="n">IDENTIFIED</span><span class="w"> </span><span class="k">WITH</span><span class="w"> </span><span class="n">caching_sha2_password</span><span class="w"> </span><span class="k">BY</span><span class="w"> </span><span class="s1">&#39;new_password&#39;</span><span class="p">;</span></span></span></code></pre></div><p>需確認 application driver 已支援新 plugin（多數 modern driver OK、legacy 可能要升級）</p>
</li>
<li>
<p><strong>Reserved keyword 處理</strong>：column / table 名稱跟新 reserved word 衝突的、改名</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">ALTER</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">events</span><span class="w"> </span><span class="k">RENAME</span><span class="w"> </span><span class="k">COLUMN</span><span class="w"> </span><span class="n">window</span><span class="w"> </span><span class="k">TO</span><span class="w"> </span><span class="n">event_window</span><span class="p">;</span></span></span></code></pre></div></li>
</ul>
<p>多數 org 在 Phase 3 停留更久 — paradigm 升級不是一次 big bang、是漸進。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-authentication-plugin--application-突然連不上">1. Authentication plugin — Application 突然連不上</h3>
<p>升 8.0 後 <em>new user</em> 預設用 caching_sha2_password、舊 application driver（&lt; 5 年版本）不支援、connect error: <code>Authentication plugin 'caching_sha2_password' cannot be loaded</code>。</p>
<p>修法：</p>
<ul>
<li><em>先升 driver</em>：每個 application 升級 mysql-connector-* 到支援 caching_sha2 的版本（多數 modern release 已支援）</li>
<li>短期 workaround：用 <code>mysql_native_password</code>（new user 顯式 create with <code>IDENTIFIED WITH mysql_native_password</code>）</li>
<li>設 <code>default_authentication_plugin=mysql_native_password</code>、強制保留舊 default</li>
</ul>
<h3 id="2-character-set-4-byte-utf-8--emoji-進不去">2. Character set 4-byte UTF-8 — Emoji 進不去</h3>
<p>5.7 latin1 / utf8（=utf8mb3）column 升 8.0 後 <em>仍是 utf8mb3</em>、不會自動升 utf8mb4。Application 寫入 emoji（4-byte UTF-8）會被 <em>truncate / 拒絕</em>。</p>
<p>修法：</p>
<ul>
<li><em>逐 table CONVERT</em>：gh-ost / pt-osc 跑 <code>ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4</code></li>
<li>新建 table 預設用 utf8mb4（<code>character_set_server=utf8mb4</code> 設定）</li>
<li>Application 連線 charset 設定一致（<code>character_set_client / connection / results</code>）</li>
</ul>
<h3 id="3-reserved-keyword--application-query-突然-syntax-error">3. Reserved keyword — Application query 突然 syntax error</h3>
<p>5.7 跑得好的 query：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="n">window</span><span class="p">,</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="p">;</span></span></span></code></pre></div><p>8.0 報錯：<code>window</code> 跟 <code>rank</code> 都是 reserved keyword、必須 backtick：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="o">`</span><span class="n">window</span><span class="o">`</span><span class="p">,</span><span class="w"> </span><span class="o">`</span><span class="n">rank</span><span class="o">`</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">events</span><span class="p">;</span></span></span></code></pre></div><p>修法：</p>
<ul>
<li>Phase 1 upgrade checker 已抓出來、Application code review 改 SQL</li>
<li>推薦 <em>predefer table / column 名 backtick</em> policy（一律加 backtick、避免未來 reserved word 衝突）</li>
<li>ORM 多數會自動 backtick、raw SQL 容易踩</li>
</ul>
<h3 id="4-group-replication--新-feature-開了就不能-rollback">4. Group Replication / 新 feature 開了就不能 rollback</h3>
<p>8.0 升級後 <em>誘惑使用 8.0-only feature</em>：</p>
<ul>
<li>Group Replication（5.7 也有但 8.0 更穩）</li>
<li>Resource Group（5.7 沒有）</li>
<li>Histograms（5.7 沒有）</li>
<li>CTE / window function（5.7 沒有）</li>
</ul>
<p>一旦 application 用了這些 feature、不能 rollback 5.7（feature 不存在、query 失敗）。</p>
<p>修法：</p>
<ul>
<li><em>Phase 1-3 期間禁用 8.0-only feature</em>、保留 rollback option</li>
<li><em>Phase 4 完成</em> 且穩定運作 30+ 天後、才開始 evaluate 8.0-only feature</li>
<li>加 8.0-only feature 時 <em>明確記錄不可 rollback</em></li>
</ul>
<h3 id="5-collation-default-變動--sort-order-跟-unique-行為改變">5. Collation default 變動 — Sort order 跟 unique 行為改變</h3>
<p>5.7 utf8mb4 預設 collation = <code>utf8mb4_general_ci</code>、8.0 預設 = <code>utf8mb4_0900_ai_ci</code>。兩者排序行為不一致：</p>
<ul>
<li><code>utf8mb4_general_ci</code>：簡化 collation、不嚴格遵循 Unicode</li>
<li><code>utf8mb4_0900_ai_ci</code>：Unicode 9.0 compliance、accent-insensitive</li>
</ul>
<p>對 <em>已存在的 table</em>、collation 不會被 8.0 升級改變（保留 5.7 設定）。但 <em>新建 table</em> 預設用 0900_ai_ci、UNION / JOIN 跨不同 collation 的 column 可能 error: <code>Illegal mix of collations</code>。</p>
<p>修法：</p>
<ul>
<li>統一 collation：要麼 <em>所有 table 改 0900_ai_ci</em>、要麼 <em>所有 table 保留 general_ci</em></li>
<li>Schema migration 走 OSC 工具</li>
<li>Application 內 sort-dependent logic（leaderboard / search ranking）要驗證新 collation 結果</li>
</ul>
<h2 id="capability-gap57-有但-80-沒有">Capability gap：5.7 有但 8.0 沒有</h2>
<p>少數 8.0 <em>拿走</em> 的能力：</p>
<ul>
<li><strong>Query Cache</strong>：5.7 內建（但已 deprecated）、8.0 <em>完全移除</em>。Query cache 在高並發場景 actually slowing down、移除是好事</li>
<li><strong>InnoDB MEMORY engine</strong>：5.7 部分支援、8.0 限制更多</li>
<li><strong>Some MyISAM optimizations</strong>：8.0 強制 InnoDB-first、MyISAM-specific 工作流 broken</li>
</ul>
<p>對 Query Cache user：升 8.0 前評估是否依賴、考慮改 application-side cache（Redis）。</p>
<h2 id="容量與成本對照">容量與成本對照</h2>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>5.7</th>
          <th>8.0</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cost</td>
          <td>Free (CE) / Enterprise</td>
          <td>Free (CE) / Enterprise</td>
      </tr>
      <tr>
          <td>升級 hosts × 時間</td>
          <td>-</td>
          <td>per-instance ~30 分鐘 binary upgrade</td>
      </tr>
      <tr>
          <td>Application 改動</td>
          <td>-</td>
          <td>driver upgrade + SQL review</td>
      </tr>
      <tr>
          <td>Character set conversion</td>
          <td>-</td>
          <td>per-table OSC、大表小時級</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>-</td>
          <td>1-2 個 DBA × 2-4 週</td>
      </tr>
      <tr>
          <td>對 production 影響</td>
          <td>-</td>
          <td>Phase 2-3 漸進升級、無大 downtime</td>
      </tr>
  </tbody>
</table>
<p>5.7 → 8.0 upgrade 整體成本是 <em>1-2 個 FTE 月</em> 規模。對中型 deployment（100+ DB）可能更多。</p>
<h2 id="何時不升">何時不升</h2>
<ul>
<li><strong>App 用 Query Cache 重度</strong>：8.0 沒了、要 application 改造</li>
<li><strong>Old driver 不能升</strong>：legacy enterprise application 用 10 年前 driver、driver vendor 已倒、無法升 8.0-compatible</li>
<li><strong>Compliance freeze</strong>：某些金融 / 醫療場景 freeze technology 多年、升級需要重 audit + recertification</li>
<li><strong>5.7 已 EOL（2023-10）後仍堅持不升</strong>：security risk 高、應該 <em>優先升</em></li>
</ul>
<h2 id="跟-postgresql-major-version-upgrade-對比">跟 PostgreSQL Major Version Upgrade 對比</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>MySQL 5.7 → 8.0</th>
          <th>PostgreSQL N → N+1</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Tool</td>
          <td>binary upgrade + 自動 server-upgrade（8.0.16+；舊版用 mysql_upgrade）</td>
          <td>pg_upgrade（in-place）</td>
      </tr>
      <tr>
          <td>Downtime</td>
          <td>&lt; 5 分鐘 per instance（binary + DD upgrade）</td>
          <td>&lt; 1 分鐘 per instance（pg_upgrade）</td>
      </tr>
      <tr>
          <td>Paradigm shift</td>
          <td>3 條（charset / auth / atomic DDL）</td>
          <td>一般 0-1 條（PG major 多保 compat）</td>
      </tr>
      <tr>
          <td>App 必須改</td>
          <td>多（driver + query）</td>
          <td>少（多數 query 兼容）</td>
      </tr>
      <tr>
          <td>Risk</td>
          <td>高（paradigm 多）</td>
          <td>中-低</td>
      </tr>
      <tr>
          <td>Rollback</td>
          <td>不可（一旦 atomic DDL data 寫入、5.7 不認）</td>
          <td>不可（pg_upgrade 不可逆）</td>
      </tr>
  </tbody>
</table>
<p>PG major upgrade 比 MySQL 簡單。MySQL 5.7 → 8.0 是 <em>特例</em> — Oracle 把多年 deprecated 一次清。8.0 → 8.4 / 9.x 預期更平順。</p>
<h2 id="跟其他模組整合">跟其他模組整合</h2>
<h3 id="跟-replication-topology">跟 Replication topology</h3>
<p>8.0 replica 可 attach 5.7 primary（向下兼容）、但 5.7 replica <em>不能 attach 8.0 primary</em>（向上不兼容）。Upgrade 順序必須 <em>replica 先升、primary 後升</em>。詳見 <a href="/blog/backend/01-database/vendors/mysql/replication-topology/" data-link-title="MySQL Replication Topology：async / semi-sync / GTID 不是三選一、是三個 trade-off 軸的疊加" data-link-desc="MySQL replication 不是「選 async 還是 semi-sync」、是 *durability / latency / consistency* 三個 trade-off 軸的疊加；GTID 是跨 mode 的 infrastructure layer、不是第三種 mode。本文走 3 軸取捨模型 → async / semi-sync 行為對比 → GTID 替代 binlog-position 的好處 → 配置 step-by-step → 5 production 踩雷（lag 暴衝 / semi-sync 退回 async / GTID gap / Loss-Less semi-sync 真的 loss-less / chained replication 雪崩）→ 跟 Aurora MySQL / Vitess / ProxySQL / Orchestrator 整合">Replication Topology</a>。</p>
<h3 id="跟-innodb-tuning">跟 InnoDB Tuning</h3>
<p>8.0 InnoDB 改寫了 redo log（atomic、可動態調整）、<code>innodb_log_file_size</code> 升級後可以 <em>online 改</em>、不必停機。詳見 <a href="/blog/backend/01-database/vendors/mysql/innodb-tuning/" data-link-title="MySQL InnoDB Tuning：為什麼一個 100 GB DB 在 64 GB RAM server 上 query 慢 5 倍" data-link-desc="InnoDB 是 MySQL 預設 storage engine、預設值給 256 MB buffer pool（早期 default）。本文從一個常見痛點開場（DB &gt; RAM 但 server 仍 swap）、走 4 個 critical knob（buffer pool / redo log / flush method / IO capacity）、各自如何影響讀寫吞吐、配置 step-by-step、5 production 踩雷（buffer pool warm-up / log file 大小 / 設 sync_binlog=0 換速度 / IO scheduler / undo log 膨脹）、跟 SSD / NVMe / EBS 的 IO 假設">InnoDB Tuning</a>。</p>
<h3 id="跟-modern-sql-features">跟 Modern SQL Features</h3>
<p>8.0 補 CTE / window / JSON_TABLE / hash join — 是 <em>為什麼要升 8.0</em> 的 driver。詳見 <a href="/blog/backend/01-database/vendors/mysql/modern-sql-features/" data-link-title="MySQL 8.0 Modern SQL：CTE / window function / JSON_TABLE 不是「終於跟上 PG」、是進入 SQL 工程深度的入場券" data-link-desc="MySQL 8.0 在 SQL 特性上 *終於補齊* CTE、window function、lateral derived table、JSON_TABLE、hash join 等現代 SQL 特性。本文走 5 個關鍵特性、各自實際 production 場景、跟 PostgreSQL 對應特性的行為差異（特別是 JSON_TABLE vs PG JSONB / jsonb_path_query）、配置 / migration 注意事項、5 production 踩雷（CTE 不 materialize / window function 大量 sort spill / JSON_TABLE 跟 generated column 取捨 / hash join 預設沒開 / recursive CTE 深度上限）">Modern SQL Features</a>。</p>
<h3 id="跟-group-replication">跟 Group Replication</h3>
<p>GR 在 5.7 有、但 8.0 才成熟。Group Replication 的 <em>MySQL Shell + Router</em> 整套 stack 主要在 8.0 才完整。詳見 <a href="/blog/backend/01-database/vendors/mysql/group-replication/" data-link-title="MySQL Group Replication / InnoDB Cluster：single-primary vs multi-primary mode 對 transaction certification 的影響" data-link-desc="MySQL Group Replication 提供 synchronous multi-primary replication、用 Paxos-like Group Communication Engine（GCE）達成 quorum-based commit。但「multi-primary」不是「single-primary 多開幾個 write 入口」、是 *transaction conflict detection &#43; certification* 整個機制不同。本文走 GR 機制（GCE &#43; certification &#43; applier）、single-primary vs multi-primary mode、InnoDB Cluster 跟 MySQL Shell / Router 整合、5 production 踩雷（cert lag / write conflict / large transaction / network partition / member 加入 catch-up）、何時用 GR 何時用傳統 replication">Group Replication</a>。</p>
<h3 id="跟-aurora--planetscale-等-managed">跟 Aurora / PlanetScale 等 managed</h3>
<p>從 5.7 升 8.0 是個好時機 <em>同時評估</em> 是否要遷 Aurora / PlanetScale — 既然要做 paradigm shift、不如一次到位。詳見 <a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">migrate-to-aurora</a> / <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">migrate-to-planetscale</a>。</p>
<h2 id="相關連結">相關連結</h2>
<ul>
<li><a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL vendor overview</a></li>
<li><a href="/blog/backend/01-database/vendors/mysql/replication-topology/" data-link-title="MySQL Replication Topology：async / semi-sync / GTID 不是三選一、是三個 trade-off 軸的疊加" data-link-desc="MySQL replication 不是「選 async 還是 semi-sync」、是 *durability / latency / consistency* 三個 trade-off 軸的疊加；GTID 是跨 mode 的 infrastructure layer、不是第三種 mode。本文走 3 軸取捨模型 → async / semi-sync 行為對比 → GTID 替代 binlog-position 的好處 → 配置 step-by-step → 5 production 踩雷（lag 暴衝 / semi-sync 退回 async / GTID gap / Loss-Less semi-sync 真的 loss-less / chained replication 雪崩）→ 跟 Aurora MySQL / Vitess / ProxySQL / Orchestrator 整合">MySQL Replication Topology</a>（升級順序 replica-first）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/modern-sql-features/" data-link-title="MySQL 8.0 Modern SQL：CTE / window function / JSON_TABLE 不是「終於跟上 PG」、是進入 SQL 工程深度的入場券" data-link-desc="MySQL 8.0 在 SQL 特性上 *終於補齊* CTE、window function、lateral derived table、JSON_TABLE、hash join 等現代 SQL 特性。本文走 5 個關鍵特性、各自實際 production 場景、跟 PostgreSQL 對應特性的行為差異（特別是 JSON_TABLE vs PG JSONB / jsonb_path_query）、配置 / migration 注意事項、5 production 踩雷（CTE 不 materialize / window function 大量 sort spill / JSON_TABLE 跟 generated column 取捨 / hash join 預設沒開 / recursive CTE 深度上限）">MySQL Modern SQL Features</a>（升 8.0 的主要 driver）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/group-replication/" data-link-title="MySQL Group Replication / InnoDB Cluster：single-primary vs multi-primary mode 對 transaction certification 的影響" data-link-desc="MySQL Group Replication 提供 synchronous multi-primary replication、用 Paxos-like Group Communication Engine（GCE）達成 quorum-based commit。但「multi-primary」不是「single-primary 多開幾個 write 入口」、是 *transaction conflict detection &#43; certification* 整個機制不同。本文走 GR 機制（GCE &#43; certification &#43; applier）、single-primary vs multi-primary mode、InnoDB Cluster 跟 MySQL Shell / Router 整合、5 production 踩雷（cert lag / write conflict / large transaction / network partition / member 加入 catch-up）、何時用 GR 何時用傳統 replication">MySQL Group Replication</a>（8.0 成熟）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/innodb-tuning/" data-link-title="MySQL InnoDB Tuning：為什麼一個 100 GB DB 在 64 GB RAM server 上 query 慢 5 倍" data-link-desc="InnoDB 是 MySQL 預設 storage engine、預設值給 256 MB buffer pool（早期 default）。本文從一個常見痛點開場（DB &gt; RAM 但 server 仍 swap）、走 4 個 critical knob（buffer pool / redo log / flush method / IO capacity）、各自如何影響讀寫吞吐、配置 step-by-step、5 production 踩雷（buffer pool warm-up / log file 大小 / 設 sync_binlog=0 換速度 / IO scheduler / undo log 膨脹）、跟 SSD / NVMe / EBS 的 IO 假設">MySQL InnoDB Tuning</a>（8.0 redo log 改寫）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/migrate-to-aurora/" data-link-title="MySQL → Aurora MySQL：storage layer 轉手到 AWS、replication / HA / backup 全部 outsource" data-link-desc="自管 MySQL → Aurora MySQL 是 Type C operational hybrid migration — wire protocol 一致、ops 責任轉到 AWS。本文走 6 維 audit（Operational High）、Aurora storage architecture 衝擊、4-phase migration、5 production 踩雷、何時維持原路線。">migrate-to-aurora</a> / <a href="/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &#43; Operational &#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">migrate-to-planetscale</a></li>
<li><a href="/blog/backend/01-database/vendors/postgresql/major-version-upgrade/" data-link-title="PostgreSQL major version upgrade (14 → 17)：為什麼這篇不套 5 type migration" data-link-desc="PostgreSQL major version upgrade 是 *5 type 漏類* 的實證 — source/target 同 vendor、5 維度都 Low 但 *upgrade-specific audit* 是核心；本文結構接近 deep article methodology 的 6-section &#43; 額外 upgrade audit 段；涵蓋 pg_upgrade / logical replication / blue-green 三方法、extension 相容性、5 production 踩雷">PostgreSQL Major Version Upgrade</a>（PG sibling）</li>
<li>方法論：<a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook Methodology</a>（Type E paradigm shift）</li>
<li>官方：<a href="https://dev.mysql.com/doc/refman/8.0/en/upgrading.html">MySQL 8.0 Upgrade Guide</a></li>
</ul>
]]></content:encoded></item></channel></rss>