<?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>Planetscale on Tarragon</title><link>https://tarrragon.github.io/blog/tags/planetscale/</link><description>Recent content in Planetscale 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/planetscale/index.xml" rel="self" type="application/rss+xml"/><item><title>MySQL → PlanetScale：managed Vitess + branch-based schema workflow 的 hybrid shift</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/</guid><description>&lt;blockquote>
&lt;p>本文是跨 vendor migration playbook、cross-link 到 &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> 跟 PlanetScale。走 &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;table>
 &lt;thead>
 &lt;tr>
 &lt;th>維度&lt;/th>
 &lt;th>自管 MySQL&lt;/th>
 &lt;th>PlanetScale&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Sharding&lt;/td>
 &lt;td>自己配 Vitess 或不 shard&lt;/td>
 &lt;td>Vitess 透明（即使單 keyspace 也走 Vitess）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema migration&lt;/td>
 &lt;td>gh-ost / pt-osc 跑 ALTER&lt;/td>
 &lt;td>&lt;strong>Branch + Deploy Request&lt;/strong> workflow&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Failover&lt;/td>
 &lt;td>Orchestrator 自管&lt;/td>
 &lt;td>PlanetScale 自動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Branching&lt;/td>
 &lt;td>不存在概念&lt;/td>
 &lt;td>&lt;strong>DB branch（git-like）+ revert&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Connection limit&lt;/td>
 &lt;td>max_connections 自己設&lt;/td>
 &lt;td>PlanetScale connection pool / per-plan limit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Foreign key&lt;/td>
 &lt;td>支援&lt;/td>
 &lt;td>有限支援（Vitess 18+ / 2023 起、需明確啟用）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>SUPER&lt;/code> privilege&lt;/td>
 &lt;td>自己有&lt;/td>
 &lt;td>&lt;strong>無&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-region&lt;/td>
 &lt;td>自己配 binlog ship&lt;/td>
 &lt;td>PlanetScale 內建（Boost feature）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Per-month cost&lt;/td>
 &lt;td>EC2 + EBS + ops&lt;/td>
 &lt;td>per-row-read + per-row-written + storage&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>從 &lt;em>application 連線&lt;/em> 視角：跟 &lt;a href="https://tarrragon.github.io/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 踩雷、何時維持原路線。">Aurora MySQL migration&lt;/a> 一樣低、connection string 換就完事。從 &lt;em>schema management&lt;/em> 視角：PlanetScale 強推 &lt;em>branch-based workflow&lt;/em> — 改 schema 不再是「跑 gh-ost」、是「開 branch → Deploy Request → review → merge」。整個 schema change 工作流跟 git 同型、跟 application code review 同 workflow。&lt;/p>
&lt;p>這是 &lt;em>workflow + schema-tooling shift&lt;/em> — Aurora 是「同 workflow + managed」、PlanetScale 是「同 protocol + 不同 schema workflow + branch tooling」。Database paradigm（OLTP relational）跟 application change 都 Low、主要 shift 在 DBA / dev 操作介面。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是跨 vendor migration playbook、cross-link 到 <a href="/blog/backend/01-database/vendors/mysql/" data-link-title="MySQL" data-link-desc="高併發網路服務常用關聯式資料庫、Vitess / PlanetScale 分片生態、GitHub / Shopify / Facebook 規模驗證">MySQL</a> 跟 PlanetScale。走 <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>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>自管 MySQL</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Sharding</td>
          <td>自己配 Vitess 或不 shard</td>
          <td>Vitess 透明（即使單 keyspace 也走 Vitess）</td>
      </tr>
      <tr>
          <td>Schema migration</td>
          <td>gh-ost / pt-osc 跑 ALTER</td>
          <td><strong>Branch + Deploy Request</strong> workflow</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>Orchestrator 自管</td>
          <td>PlanetScale 自動</td>
      </tr>
      <tr>
          <td>Branching</td>
          <td>不存在概念</td>
          <td><strong>DB branch（git-like）+ revert</strong></td>
      </tr>
      <tr>
          <td>Connection limit</td>
          <td>max_connections 自己設</td>
          <td>PlanetScale connection pool / per-plan limit</td>
      </tr>
      <tr>
          <td>Foreign key</td>
          <td>支援</td>
          <td>有限支援（Vitess 18+ / 2023 起、需明確啟用）</td>
      </tr>
      <tr>
          <td><code>SUPER</code> privilege</td>
          <td>自己有</td>
          <td><strong>無</strong></td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>自己配 binlog ship</td>
          <td>PlanetScale 內建（Boost feature）</td>
      </tr>
      <tr>
          <td>Per-month cost</td>
          <td>EC2 + EBS + ops</td>
          <td>per-row-read + per-row-written + storage</td>
      </tr>
  </tbody>
</table>
<p>從 <em>application 連線</em> 視角：跟 <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 踩雷、何時維持原路線。">Aurora MySQL migration</a> 一樣低、connection string 換就完事。從 <em>schema management</em> 視角：PlanetScale 強推 <em>branch-based workflow</em> — 改 schema 不再是「跑 gh-ost」、是「開 branch → Deploy Request → review → merge」。整個 schema change 工作流跟 git 同型、跟 application code review 同 workflow。</p>
<p>這是 <em>workflow + schema-tooling shift</em> — Aurora 是「同 workflow + managed」、PlanetScale 是「同 protocol + 不同 schema workflow + branch tooling」。Database paradigm（OLTP relational）跟 application change 都 Low、主要 shift 在 DBA / dev 操作介面。</p>
<h2 id="為什麼是-type-eparadigm--operational--schema-多軸">為什麼是 Type E（Paradigm + Operational + Schema 多軸）</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-High</td>
          <td>MySQL wire protocol 一致、FK 有限支援（Vitess 18+）、部分 INSTANT DDL 行為差</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>branch lifecycle、Deploy Request workflow、connection pooler 不同</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>High</td>
          <td>branch-based schema management、跟自管 gh-ost / pt-osc 思維完全不同</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Medium</td>
          <td>PlanetScale CLI / Console / API / connection pooler 都進團隊工具</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>connection string + 移除 FK 約束</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low-Medium</td>
          <td>Vitess 透明 sharding 即使單 keyspace</td>
      </tr>
  </tbody>
</table>
<p>Paradigm + Operational + Schema 三軸 High。按優先序 Schema &gt; Paradigm &gt; Operational、預設選 Type A。但 <em>讀者最關心</em> 的是 schema workflow paradigm 轉變、不是 schema field translation — Type E 結構更貼合「不收斂、部分 adopt」的真實 migration 流程。</p>
<p>→ <strong>Type E paradigm shift</strong>、4-phase partial migration（多數 org 停 Phase 2-3 hybrid）。</p>
<h2 id="driverbranch-based-workflow--vitess-transparent-sharding--zero-dba">Driver：Branch-based workflow + Vitess transparent sharding + zero DBA</h2>
<p>從自管 MySQL 遷 PlanetScale 的核心 driver 有三條：</p>
<p><strong>Branch-based schema workflow</strong>：</p>
<ul>
<li>改 schema 開 branch（<code>pscale branch create</code>）、在 branch 上跑 ALTER、跑 application code 改、merge 進 main 前 Deploy Request review</li>
<li>Deploy Request 顯示 schema diff、跟 GitHub PR 同概念</li>
<li>Merge 後 PlanetScale 自動跑 <em>no-downtime schema migration</em>（內部 VReplication）</li>
<li>出問題可 <em>revert</em>（48 小時內、用 Vitess VReplication 反向 ship 資料）</li>
</ul>
<p>這條 workflow 對 <em>developer ergonomic</em> 拉力大 — schema change 不再是「DBA 工作」、是「dev 自己處理、跟 code review 同流程」。</p>
<p><strong>Vitess transparent sharding</strong>：</p>
<ul>
<li>PlanetScale 強制每個 cluster 走 Vitess（即使單 keyspace 看似 unsharded）</li>
<li>寫吞吐成長到需要 shard 時、加 shard 是 PlanetScale internal 操作、application 看不到</li>
<li>不用養 Vitess SRE 團隊</li>
</ul>
<p><strong>Zero DBA</strong>：</p>
<ul>
<li>PlanetScale 接管所有 ops（failover / backup / parameter / scaling）</li>
<li>跟 Aurora 同等級「managed」、加上 branch workflow</li>
</ul>
<p>FK 處理：早期 Vitess（&lt; 18）不支援 FK、PlanetScale 對應期間建議全 drop FK + 改 application enforcement。Vitess 18（2023 末）後加 FK 支援、PlanetScale 在合適 plan 內可啟用、但 <em>cross-shard FK</em> 仍受限。Phase 1 audit 重點不再是「全 drop FK」、而是「驗證 FK 行為（特別 cascade / cross-shard）跟自管 MySQL 預期一致」。</p>
<h2 id="4-phase-partial-migration不收斂">4-phase partial migration（不收斂）</h2>
<h3 id="phase-1fk-行為驗證--schema-auditplanetscale-shadow-cluster-起來">Phase 1：FK 行為驗證 + schema audit、PlanetScale shadow cluster 起來</h3>
<p>第一步是 <em>FK 行為驗證</em> + schema layout audit。Vitess 18+ / PlanetScale 已支援 FK、但行為跟自管 MySQL 有差異：</p>
<ul>
<li>列所有 FK：<code>SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL</code></li>
<li>對每個 FK 評估：
<ul>
<li><em>Cross-shard FK</em>：PlanetScale 不允許 FK 跨 shard、parent 跟 child 必須同 shard（透過 Vindex 設計）</li>
<li><em>Cascade 行為</em>：cross-shard DELETE cascade 在 PlanetScale 不執行、改 application 層處理</li>
<li><em>Native FK 啟用 vs application enforcement</em>：依 Vitess 18+ 行為決定保留 FK 或改 app-level</li>
</ul>
</li>
<li><em>PlanetScale shadow cluster</em> 起來、跑 application schema、用 Vitess Connector 從自管 binlog ship 資料</li>
</ul>
<p>工作主要塊：</p>
<ul>
<li>FK 行為 audit + 改 cross-shard cascade（依 FK 數量、weeks 工作量）</li>
<li>Schema dump → PlanetScale import（用 <code>pscale shell</code>）</li>
<li>Vitess Connector 設定 binlog stream</li>
</ul>
<p>完成標準：PlanetScale shadow cluster 有完整 production schema、cross-shard FK 已處理、binlog stream lag &lt; 1 秒。</p>
<h3 id="phase-2read-traffic-切-planetscale">Phase 2：Read traffic 切 PlanetScale</h3>
<p>跟 <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 踩雷、何時維持原路線。">Aurora migration</a> Phase 2 同概念：read query 切 PlanetScale connection string、寫入仍自管 MySQL。</p>
<p>差異：</p>
<ul>
<li>PlanetScale connection 有 <em>per-plan rate limit</em>（Scaler Plan: 10K connections、Enterprise: 100K）</li>
<li>必須走 <em>PlanetScale connection pool</em>（不是直接連、有 SSL handshake overhead）</li>
<li>監控 <code>pscale_io_read_query_throttled_total</code> 確認沒撞 plan limit</li>
</ul>
<p>跑 2-4 週、確認：</p>
<ul>
<li>PlanetScale read latency 跟自管 replica latency 接近（PlanetScale Boost cache 可能比自管快）</li>
<li>Vitess Connector stream 穩定</li>
<li>Application 對 PlanetScale row read 量符合 cost forecast</li>
</ul>
<h3 id="phase-3schema-workflow-切-planetscale--write-cutover">Phase 3：Schema workflow 切 PlanetScale + write cutover</h3>
<p>關鍵 paradigm shift：<em>停 gh-ost / pt-osc</em>、改用 PlanetScale branch workflow。</p>
<p>訓練步驟：</p>
<ol>
<li><em>第一個 small schema change</em> 用 PlanetScale branch + Deploy Request 跑</li>
<li>開發團隊熟悉 <code>pscale branch create</code> / <code>pscale deploy-request create</code> CLI</li>
<li>CI integration：把 PlanetScale CLI 加進 deploy pipeline</li>
<li>退役 gh-ost / pt-osc CI integration</li>
</ol>
<p>完成 schema workflow 訓練後 write cutover：</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. PlanetScale 把 shadow cluster promote 為 primary（用 PlanetScale console / API）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 透過 PlanetScale Console 啟用 production write 或用 `pscale` CLI 對應 promotion 命令</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># （CLI 命令名稱隨 pscale 版本變動、以 pscale --help 為準）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 2. Application connection string 切 PlanetScale writer</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># 自管 → mysql://primary.example.com:3306/production</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># PlanetScale → mysql://...@xxx.connect.psdb.cloud/production?sslaccept=strict</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="c1"># 3. Vitess Connector 反向（PlanetScale → 自管）作為 rollback insurance</span></span></span></code></pre></div><p>完成標準：寫入流量 100% 進 PlanetScale、自管 MySQL 接 PlanetScale binlog（rollback buffer）。</p>
<h3 id="phase-4自管-mysql-退役--保留作-rollback-buffer">Phase 4：自管 MySQL 退役 / 保留作 rollback buffer</h3>
<p>跟 Aurora migration Phase 4 同模式：</p>
<ul>
<li>自管保留 30-90 天作 cold buffer</li>
<li>確認 PlanetScale cost forecast 跟 actual 一致（per-row read / write 計費可能超預期）</li>
<li>確認 branch workflow 在 production team 內 adopt（不是「PlanetScale 在用、但團隊還是用 gh-ost on staging」這種 stuck 狀態）</li>
</ul>
<p>多數 org 在 <em>Phase 3</em> 停留更久（半年-一年）— Vitess Connector 反向 binlog ship 是穩定 rollback path、Phase 4 不急。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-cross-shard-fk--planetscale-跟-native-mysql-行為不同">1. Cross-shard FK — PlanetScale 跟 native MySQL 行為不同</h3>
<p>Vitess 18+ / PlanetScale 已支援 FK、但 <em>cross-shard cascade</em> 不執行。同 shard 內 FK 跟 native MySQL 一致；parent 跟 child 跨 shard 時、<code>ON DELETE CASCADE</code> 在 PlanetScale 不會跨 shard 觸發 child delete、結果 application 看到 <em>orphan row</em>。</p>
<p>修法：</p>
<ul>
<li>Phase 1 audit 出哪些 FK 跨 shard（Vindex 設計決定 parent / child 是否同 shard）</li>
<li>同 shard FK：直接保留、行為跟自管 MySQL 一致</li>
<li>Cross-shard cascade：改 application 層 transaction 內 explicit DELETE child、或 <em>background reconciliation job</em>（定期掃 orphan）</li>
<li>把 <em>parent / child 強制同 shard</em>（用相同 Vindex column）是預防 cross-shard FK 議題的根本解</li>
</ul>
<h3 id="2-deploy-request-思維轉換不到位--團隊仍用跑-alter心智模型">2. Deploy Request 思維轉換不到位 — 團隊仍用「跑 ALTER」心智模型</h3>
<p>DBA / SRE 習慣 <em>直接連 PlanetScale 跑 ALTER</em> —但 PlanetScale 在 production branch 上 <em>禁止 DDL</em>（必須走 Deploy Request）。失敗訊息 <em>not actionable</em>（ERROR: not authorized）、DBA 找不到原因、production maintenance 卡住。</p>
<p>修法：</p>
<ul>
<li>Phase 3 <em>訓練步驟</em> 不能跳：找一個 small schema change 在 staging 走完整 branch workflow、團隊每個 DBA / SRE 都 hands-on 過</li>
<li>在 ops runbook 寫明 <em>production schema change must go through Deploy Request</em>、列 CLI 命令模板</li>
<li>緊急 schema change（事故中）也走 branch + Deploy Request、PlanetScale 可加速 Deploy（不能 bypass workflow）</li>
</ul>
<h3 id="3-schema-diff-邊界--planetscale-看不到-application-level-insert-changes">3. Schema diff 邊界 — PlanetScale 看不到 application-level INSERT changes</h3>
<p>Deploy Request 顯示 <em>schema-level diff</em>（CREATE / ALTER / DROP）、不顯示 <em>data diff</em>。如果 branch 上有 INSERT 進去（測試資料 / seed data）、merge 進 main 時 <em>資料不會搬</em>（只搬 schema）、application 預期有資料但 production 沒。</p>
<p>修法：</p>
<ul>
<li>把 <em>seed data INSERT</em> 放 application migration / fixture、不在 PlanetScale branch 內</li>
<li>用 PlanetScale CLI <em>export branch data</em> 跟 <em>import to main</em>（手動操作）作為 escape hatch</li>
<li>教育團隊：PlanetScale branch = <em>schema branch</em>、不是 git-like <em>data branch</em></li>
</ul>
<h3 id="4-branch-lifecycle-ops-cost--100-個-stale-branch">4. Branch lifecycle ops cost — 100 個 stale branch</h3>
<p>每個 PR 都開一個 PlanetScale branch、PR merge 後忘記刪、累積 100 個 stale branch。每個 branch 佔 storage cost、PlanetScale plan limit 也限制 branch 數量。</p>
<p>修法：</p>
<ul>
<li>CI integration：PR close 自動 <code>pscale branch delete &lt;branch-name&gt;</code></li>
<li>設 <em>branch retention policy</em>（30 天無活動自動刪）</li>
<li>監控 <code>pscale branch list | wc -l</code> 數量、超 threshold alert</li>
<li>把 branch lifecycle 寫進 <em>team playbook</em>（不是 PlanetScale 教、是團隊內部規範）</li>
</ul>
<h3 id="5-無-super-privilege--部分操作不可行">5. 無 <code>SUPER</code> privilege — 部分操作不可行</h3>
<p>PlanetScale connection 拿到的 MySQL user 沒有 <code>SUPER</code> privilege。需要 <code>SUPER</code> 的操作直接失敗：</p>
<ul>
<li><code>SET GLOBAL</code>（不能改 runtime variable）</li>
<li><code>KILL</code> 別人的 query（PlanetScale console 提供 alt 介面）</li>
<li><code>SHOW MASTER STATUS</code> / <code>SHOW SLAVE STATUS</code>（PlanetScale 抽象掉、不暴露）</li>
<li><code>INSTALL PLUGIN</code>（managed、不允許）</li>
<li><code>STOP SLAVE</code> / <code>START SLAVE</code>（Vitess 內部）</li>
</ul>
<p>修法：</p>
<ul>
<li>評估 application 跟 ops tool 是否依賴 <code>SUPER</code> privilege</li>
<li>改用 PlanetScale console / API 等價操作</li>
<li>部分監控 query（<code>SHOW SLAVE STATUS</code>）用 <em>PlanetScale 內建 dashboard</em> 代替</li>
</ul>
<h2 id="schema-translation-主要工作量塊">Schema translation 主要工作量塊</h2>
<p>雖然 Type E 結構不以 schema translation 為主、但 schema diff 在 Phase 1 仍佔多數時間：</p>
<table>
  <thead>
      <tr>
          <th>自管 MySQL</th>
          <th>PlanetScale (Vitess)</th>
          <th>翻譯難度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FOREIGN KEY constraint</td>
          <td>（無）+ application enforcement</td>
          <td>高</td>
      </tr>
      <tr>
          <td>INSTANT DDL</td>
          <td>部分支援、其他走 Vitess online DDL</td>
          <td>低-中</td>
      </tr>
      <tr>
          <td>Stored procedure</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Trigger</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>User-defined function</td>
          <td>受限</td>
          <td>中</td>
      </tr>
      <tr>
          <td>INSERT 跨表（CTE）</td>
          <td>支援</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Cross-shard JOIN</td>
          <td>必須用 Vindex（user_id 等 shard key 同表）</td>
          <td>中-高</td>
      </tr>
      <tr>
          <td><code>SUPER</code> 行為</td>
          <td>不支援</td>
          <td>中（ops tool 改）</td>
      </tr>
      <tr>
          <td><code>RELOAD</code> privilege</td>
          <td>不支援</td>
          <td>中</td>
      </tr>
  </tbody>
</table>
<h2 id="容量與成本對照">容量與成本對照</h2>
<p>PlanetScale 計費 <em>很不同</em>：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>自管 MySQL（EC2）</th>
          <th>PlanetScale Scaler Pro</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Per-row read</td>
          <td>不計費</td>
          <td>按量計費、$1 per 1B row read</td>
      </tr>
      <tr>
          <td>Per-row written</td>
          <td>不計費</td>
          <td>按量計費、$1.50 per 1M row write</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>EBS、$0.10/GB-month</td>
          <td>$1.50/GB-month + replication overhead</td>
      </tr>
      <tr>
          <td>Connection limit</td>
          <td>max_connections 自己設</td>
          <td>per-plan limit、可加 Connection pooler</td>
      </tr>
      <tr>
          <td>Branch</td>
          <td>不適用</td>
          <td>每 branch 含 storage cost</td>
      </tr>
      <tr>
          <td>Boost cache</td>
          <td>不適用</td>
          <td>additional cost</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>1-2 FTE</td>
          <td>&lt; 0.2 FTE</td>
      </tr>
  </tbody>
</table>
<p>PlanetScale 適合 <em>小-中規模 + high developer productivity priority</em>：</p>
<ul>
<li>流量 &lt; 10K WPS：cost 接近自管、developer productivity 顯著提升</li>
<li>流量 10-50K WPS：cost 開始貴、但 ops saving 仍大於 cost increase</li>
<li>流量 &gt; 100K WPS：PlanetScale Enterprise 議價、要 commit pricing</li>
</ul>
<p>對 high-traffic 場景 cost forecast 必須跑 <em>真實 workload trace</em> — PlanetScale 提供 <code>pscale analytics</code> 預估 read / write 量、用 production binlog replay 在 staging 跑、估算 row read / write 計費。</p>
<h2 id="何時不要遷">何時不要遷</h2>
<ul>
<li><strong>FK 是 application core constraint</strong>：cascade DELETE / SET NULL 廣泛使用、application 改不動</li>
<li><strong>大量 <code>SUPER</code>-required ops 自動化</strong>：DBA tools / monitoring 寫死 <code>SUPER</code>、改不動</li>
<li><strong>OS-level customization 需求</strong>：跟 Aurora 一樣、PlanetScale 完全 managed</li>
<li><strong>流量極大 + 預算敏感</strong>：&gt; 100K WPS row read 計費可能比 EC2 貴 5x、需要 Enterprise commit pricing</li>
<li><strong>跨雲 portability 是 requirement</strong>：PlanetScale 跑在自家 cloud（背後 AWS / GCP）、不像自管 Vitess 可跨雲</li>
</ul>
<h2 id="跟-aurora-mysql-對比同-batch-的選擇">跟 Aurora MySQL 對比（同 batch 的選擇）</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Aurora MySQL</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Type</td>
          <td>C operational hybrid</td>
          <td>E paradigm shift</td>
      </tr>
      <tr>
          <td>工作量主軸</td>
          <td>parameter group + IAM + endpoint</td>
          <td>FK audit + branch workflow</td>
      </tr>
      <tr>
          <td>Sharding</td>
          <td>不 shard、single-region scaling</td>
          <td>Vitess 透明 sharding</td>
      </tr>
      <tr>
          <td>Schema workflow</td>
          <td>仍用 gh-ost / pt-osc</td>
          <td>Branch + Deploy Request</td>
      </tr>
      <tr>
          <td>FK</td>
          <td>支援</td>
          <td>不支援</td>
      </tr>
      <tr>
          <td>Cost model</td>
          <td>per-hour instance + per-GB storage</td>
          <td>per-row read / write + per-GB storage</td>
      </tr>
      <tr>
          <td>適合規模</td>
          <td>100 GB - 50 TB</td>
          <td>100 GB - 1 PB</td>
      </tr>
      <tr>
          <td>跨雲</td>
          <td>AWS-only</td>
          <td>PlanetScale 背後 AWS / GCP</td>
      </tr>
  </tbody>
</table>
<p>選擇邏輯：</p>
<ul>
<li><em>AWS-heavy ecosystem + 不想 schema workflow paradigm shift</em> → Aurora</li>
<li><em>Developer-first culture + 想 branch-based schema workflow + 接受 FK 限制</em> → PlanetScale</li>
</ul>
<p>兩者不互斥、有 org 用 Aurora 給 OLTP core、PlanetScale 給 newer microservices（branch workflow 帶價值）。</p>
<h2 id="相關連結">相關連結</h2>
<ul>
<li>平行 batch：→ Aurora MySQL migration playbook（同 batch、不同 paradigm）</li>
<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> / <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding 設計</a></li>
<li>跨章節：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">6.13 Performance Regression Gate</a> — Deploy Request workflow 對 release gate 的影響</li>
<li>既有 vendor 對照：<a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor page</a> / <a href="https://planetscale.com/">PlanetScale 官方</a></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://planetscale.com/docs/imports/migrate-from-mysql">PlanetScale Migration Guide</a></li>
</ul>
]]></content:encoded></item><item><title>自管 Vitess → PlanetScale：Vitess component ops outsource、加 schema workflow shift</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-vitess-to-planetscale/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-vitess-to-planetscale/</guid><description>&lt;blockquote>
&lt;p>本文是跨 vendor migration playbook、cross-link 到 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding&lt;/a> 跟 PlanetScale。走 &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 C operational hybrid 結構。&lt;/p>&lt;/blockquote>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>元件&lt;/th>
 &lt;th>自管 Vitess&lt;/th>
 &lt;th>PlanetScale&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>VTGate&lt;/td>
 &lt;td>自己部署 + LB&lt;/td>
 &lt;td>Managed、隱藏在 PlanetScale endpoint 後&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VTTablet&lt;/td>
 &lt;td>自己 per-MySQL deploy&lt;/td>
 &lt;td>Managed&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VReplication&lt;/td>
 &lt;td>自己 trigger workflow&lt;/td>
 &lt;td>Managed、透過 Console / API&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>VSchema&lt;/td>
 &lt;td>自己維護（YAML / API）&lt;/td>
 &lt;td>Managed、Console UI 編輯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>MySQL backend&lt;/td>
 &lt;td>自己 EC2 / on-prem&lt;/td>
 &lt;td>Managed (Aurora-like underlying)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema migration&lt;/td>
 &lt;td>gh-ost / pt-osc 或 Vitess online DDL&lt;/td>
 &lt;td>&lt;strong>Branch + Deploy Request workflow&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Failover&lt;/td>
 &lt;td>自己用 VTOrc&lt;/td>
 &lt;td>Managed&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Multi-region&lt;/td>
 &lt;td>自己配 VReplication 跨 region&lt;/td>
 &lt;td>Boost / per-region cluster&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cost model&lt;/td>
 &lt;td>EC2 + EBS + ops headcount&lt;/td>
 &lt;td>Per-row read / write + storage&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這條 migration 跟 &lt;a href="https://tarrragon.github.io/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 踩雷、何時維持原路線。">→ Aurora MySQL&lt;/a> 相似（self-managed → managed），但 &lt;em>target 是 Vitess-native managed&lt;/em>、保留 sharding 能力。同時加上 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/migrate-to-planetscale/" data-link-title="MySQL → PlanetScale：managed Vitess &amp;#43; branch-based schema workflow 的 hybrid shift" data-link-desc="自管 MySQL → PlanetScale 加上 Vitess sharding 跟 branch-based schema workflow。本文走 6 維 audit（Paradigm &amp;#43; Operational &amp;#43; Schema 多軸）、4-phase migration、5 production 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL&lt;/a> 的 branch workflow paradigm。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是跨 vendor migration playbook、cross-link 到 <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding</a> 跟 PlanetScale。走 <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 C operational hybrid 結構。</p></blockquote>
<table>
  <thead>
      <tr>
          <th>元件</th>
          <th>自管 Vitess</th>
          <th>PlanetScale</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VTGate</td>
          <td>自己部署 + LB</td>
          <td>Managed、隱藏在 PlanetScale endpoint 後</td>
      </tr>
      <tr>
          <td>VTTablet</td>
          <td>自己 per-MySQL deploy</td>
          <td>Managed</td>
      </tr>
      <tr>
          <td>VReplication</td>
          <td>自己 trigger workflow</td>
          <td>Managed、透過 Console / API</td>
      </tr>
      <tr>
          <td>VSchema</td>
          <td>自己維護（YAML / API）</td>
          <td>Managed、Console UI 編輯</td>
      </tr>
      <tr>
          <td>MySQL backend</td>
          <td>自己 EC2 / on-prem</td>
          <td>Managed (Aurora-like underlying)</td>
      </tr>
      <tr>
          <td>Schema migration</td>
          <td>gh-ost / pt-osc 或 Vitess online DDL</td>
          <td><strong>Branch + Deploy Request workflow</strong></td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>自己用 VTOrc</td>
          <td>Managed</td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>自己配 VReplication 跨 region</td>
          <td>Boost / per-region cluster</td>
      </tr>
      <tr>
          <td>Cost model</td>
          <td>EC2 + EBS + ops headcount</td>
          <td>Per-row read / write + storage</td>
      </tr>
  </tbody>
</table>
<p>這條 migration 跟 <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 踩雷、何時維持原路線。">→ Aurora MySQL</a> 相似（self-managed → managed），但 <em>target 是 Vitess-native managed</em>、保留 sharding 能力。同時加上 <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 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL</a> 的 branch workflow paradigm。</p>
<p>對 <em>已花心力建 Vitess team 但 ops cost 太大</em> 的 org 來說、這條 migration 比 <em>Vitess → distributed SQL</em> 風險低、保留 sharding investment。</p>
<h2 id="為什麼是-type-c不是-type-a-或-type-e">為什麼是 Type C（不是 Type A 或 Type E）</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>Low</td>
          <td>Vitess wire protocol + VSchema 概念一致</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>High</td>
          <td>4 個 component 的 ops 全部 outsource、branch workflow 是新 paradigm</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>Medium</td>
          <td>Vitess paradigm 不變、但加 branch workflow</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>Low</td>
          <td>同 Vitess engine</td>
      </tr>
      <tr>
          <td>App change</td>
          <td>Low</td>
          <td>Connection string 改、無 schema rewrite</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>Low</td>
          <td>Vitess sharding 結構保留</td>
      </tr>
  </tbody>
</table>
<p>Operational = High（其他 Low / Medium） → <strong>Type C operational hybrid</strong>。Branch workflow 是 <em>Medium paradigm shift</em> 但不是 dominant — 主要工作量在 <em>operational ownership 轉移</em>。</p>
<p>跟 <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 踩雷、何時不要遷。">自管 MySQL → PlanetScale</a>（Type E paradigm shift）對比：那條 path 是 <em>no-Vitess → Vitess + branch</em>、要學 Vitess 概念 + branch；本條是 <em>已有 Vitess + 加 branch</em>、只學 branch、複雜度低很多。</p>
<h2 id="driverops-headcount--branch-workflow--vitess-feature-加速">Driver：Ops headcount + Branch workflow + Vitess feature 加速</h2>
<p>從自管 Vitess 遷 PlanetScale 的核心 driver：</p>
<p><strong>Ops headcount 削減</strong>：</p>
<ul>
<li>自管 Vitess 通常需要 <em>2-5 個 SRE/DBA 撐 production</em> —VTGate / VTTablet / VReplication / VSchema 各有議題</li>
<li>PlanetScale 把這層全部 outsource、團隊 ops headcount 可降到 &lt; 1 FTE</li>
<li>對 50-200 人 eng team、ops cost saving 是顯著 driver</li>
</ul>
<p><strong>Branch workflow paradigm</strong>：</p>
<ul>
<li>自管 Vitess 仍用 gh-ost / pt-osc 或 Vitess online DDL 跑 schema migration、是 DBA 主導</li>
<li>PlanetScale branch workflow 把 schema migration 變 <em>developer self-service</em>、開 branch / Deploy Request / merge、跟 git workflow 同節奏</li>
<li>對 <em>high-velocity engineering culture</em> 是文化升級</li>
</ul>
<p><strong>Vitess upstream feature</strong>：</p>
<ul>
<li>PlanetScale team 是 Vitess 的主要 contributor、新 feature 通常 PlanetScale 先 ship</li>
<li>自管 Vitess 升級慢、PlanetScale 用戶看到新 feature 早 3-6 個月</li>
</ul>
<p>不適合 <em>跨雲 portability priority high</em> 或 <em>strict on-prem deployment</em> 的 org — PlanetScale 是 cloud-only。</p>
<h2 id="4-phase-migration">4-phase migration</h2>
<h3 id="phase-1topology--vschema-audit">Phase 1：Topology + VSchema audit</h3>
<p>把當前自管 Vitess cluster 完整盤點：</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"># Vitess cluster topology</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">vtctldclient GetKeyspaces
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">vtctldclient GetShards &lt;keyspace&gt;
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">vtctldclient GetTablets
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># VSchema</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">vtctldclient GetVSchema &lt;keyspace&gt;
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 跨 keyspace VReplication workflow</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">vtctldclient GetWorkflows</span></span></code></pre></div><p>對每個 keyspace 檢查：</p>
<ul>
<li><em>Shard 數量</em>：PlanetScale plan 對 shard 數量有 limit（Enterprise 才能超大規模）</li>
<li><em>VSchema features</em>：自管可能用 <em>PlanetScale 不支援的 Vindex</em>（custom Vindex）</li>
<li><em>Foreign key</em>：Vitess 18+（2023 末）才支援 FK、自管 Vitess 大多 &lt; 18、cluster 內已 application-enforced；遷 PlanetScale 後可選擇啟用 native FK（同 shard 內）或繼續 application enforcement</li>
<li><em>Stored procedure / trigger</em>：PlanetScale 受限、確認是否 application 依賴</li>
</ul>
<p>完成標準：寫 <em>blocker list</em>（PlanetScale 不支援的功能）+ <em>compatibility list</em>（功能對應）。</p>
<h3 id="phase-2dual-cluster--binlog-stream">Phase 2：Dual cluster + binlog stream</h3>
<p>PlanetScale 內建 <em>Vitess Connector</em>、從外部 MySQL（包括其他 Vitess cluster）binlog stream import：</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. 用 PlanetScale CLI 建 cluster</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">pscale database create production --region us-east
</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. Import schema（從自管 Vitess export）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">pscale shell production main &lt; schema.sql
</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. 設 Vitess Connector 從自管 cluster import 資料</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># （透過 PlanetScale Console）</span></span></span></code></pre></div><p>Vitess Connector 從自管 VTTablet 的 MySQL primary 讀 binlog、寫進 PlanetScale。Lag 通常 &lt; 1 秒。</p>
<p>跑 1-2 週、確認：</p>
<ul>
<li>Schema 完整 migrate</li>
<li>VSchema 對應正確（Vindex 行為一致）</li>
<li>Lag 穩定</li>
</ul>
<h3 id="phase-3application-read-切-planetscale">Phase 3：Application read 切 PlanetScale</h3>
<p>跟 Aurora migration Phase 2 同概念。Application read query 切 PlanetScale endpoint：</p>
<ul>
<li>連 PlanetScale connection string（<code>xxx.connect.psdb.cloud</code>）</li>
<li>仍寫自管 Vitess、Vitess Connector 同步 PlanetScale</li>
</ul>
<p>跑 2-4 週、驗證：</p>
<ul>
<li>Query result 一致</li>
<li>PlanetScale read latency 接近自管（PlanetScale Boost cache 可能加速）</li>
<li>PlanetScale row read 計費跟預估一致</li>
</ul>
<h3 id="phase-4write-cutover--自管-vitess-退役">Phase 4：Write cutover + 自管 Vitess 退役</h3>





<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. PlanetScale 把 cluster promote 為 primary（透過 Console）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"># 透過 PlanetScale Console 啟用 production write 或用 `pscale` CLI 對應 promotion 命令</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># （CLI 命令名稱隨 pscale 版本變動、以 pscale --help 為準）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. Application 寫 connection string 切 PlanetScale</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 自管 Vitess → PlanetScale</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. Vitess Connector 反向（PlanetScale → 自管）作為 rollback buffer</span>
</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. 跑 1-2 週確認、開始 decommission 自管 Vitess</span></span></span></code></pre></div><p>Decommission 自管 Vitess 是大工程：</p>
<ul>
<li>VTGate / VTTablet pods 一個個關</li>
<li>VReplication workflow 停掉</li>
<li>MySQL backend 保留作 cold backup 1-3 月、然後 EBS snapshot + terminate</li>
</ul>
<p>完成標準：所有 traffic 在 PlanetScale、自管 Vitess 資源全 release、ops headcount confirm 下降。</p>
<h2 id="5-個-production-踩雷">5 個 Production 踩雷</h2>
<h3 id="1-vschema-不完全兼容--custom-vindex-必須改">1. VSchema 不完全兼容 — Custom Vindex 必須改</h3>
<p>自管 Vitess 可能用了 <em>custom Vindex</em>（自寫 Go plugin）、PlanetScale 不支援 custom Vindex（只支援 built-in：hash / lookup_hash / unicode 等）。</p>
<p>修法：</p>
<ul>
<li>Phase 1 audit 出所有 custom Vindex</li>
<li>對每個 custom Vindex 評估能否用 built-in 替代</li>
<li>不能替代的、考慮 <em>application 層 logic 取代 Vindex</em>（application 自己算 shard key）</li>
<li>或 <em>暫不遷該 keyspace</em>、保留自管 Vitess 跑 custom Vindex keyspace、其他遷 PlanetScale</li>
</ul>
<h3 id="2-branch-workflow-訓練不到位--dba-仍用vitess-online-ddl心智模型">2. Branch workflow 訓練不到位 — DBA 仍用「Vitess online DDL」心智模型</h3>
<p>自管 Vitess team 習慣 <code>vtctldclient ApplySchema --strategy=vitess</code> 跑 online DDL、遷 PlanetScale 後仍想直接這樣 — 但 PlanetScale production branch 禁止 schema change、必須走 Deploy Request。</p>
<p>修法：</p>
<ul>
<li>Phase 3 <em>訓練步驟</em>：team 每個 DBA / SRE 都跑過完整 branch + Deploy Request workflow</li>
<li>寫 <em>team runbook</em>：production schema change must 走 branch</li>
<li>緊急 schema change（事故中）也走 branch、PlanetScale 可加速 Deploy</li>
</ul>
<h3 id="3-super-privilege-移除--自管-admin-tool-失效">3. SUPER privilege 移除 — 自管 admin tool 失效</h3>
<p>自管 Vitess 用 <code>SUPER</code> privilege 跑 admin script、PlanetScale 沒給 SUPER。常見失效：</p>
<ul>
<li>自寫 monitor script 跑 <code>SHOW SLAVE STATUS</code>、PlanetScale 抽象掉</li>
<li>自寫 backup script 跑 <code>FLUSH TABLES WITH READ LOCK</code>、PlanetScale 不允許</li>
<li>自寫 cleanup script 跑 <code>KILL QUERY</code>、PlanetScale 受限</li>
</ul>
<p>修法：</p>
<ul>
<li>Phase 1 audit 所有 admin script</li>
<li>改用 <em>PlanetScale Console / CLI / API</em> 等價操作</li>
<li>PlanetScale 提供的 monitoring 介面替代自管監控</li>
</ul>
<h3 id="4-connection-limit--planetscale-plan-比預期緊">4. Connection limit — PlanetScale plan 比預期緊</h3>
<p>PlanetScale Scaler Plan: 10K connection、Enterprise: 100K。自管 Vitess VTGate 通常設 50K-200K connection、遷 PlanetScale 後 hit limit。</p>
<p>修法：</p>
<ul>
<li>Phase 1 <em>connection forecast</em>：peak hour 多少 active connection</li>
<li>升 PlanetScale plan（Scaler Pro / Enterprise）</li>
<li>或在 application 端加 connection pool（HikariCP / pgBouncer 等價）降低 connection count</li>
</ul>
<h3 id="5-cost-model-翻盤--per-row-read-計費超預期">5. Cost model 翻盤 — Per-row read 計費超預期</h3>
<p>PlanetScale 計費是 <em>per row read / written</em>。自管 Vitess cost = EC2 + EBS（線性 with infrastructure scale）。遷 PlanetScale 後計費跟 <em>application access pattern</em> 直接相關。</p>
<p>常見 surprise：</p>
<ul>
<li>Heavy analytics query（COUNT *、aggregation）讀大量 row、計費高</li>
<li>N+1 query pattern（application 跑很多小 SELECT）讀很多 row、計費高</li>
<li>Read-heavy workload 沒 Boost cache、每次 query 都 hit billing</li>
</ul>
<p>修法：</p>
<ul>
<li>Phase 1 <em>cost forecast</em>：用 <code>pscale analytics</code> 預估 row read / write 量、估算月帳</li>
<li>Phase 2 期間實際對 PlanetScale 跑 traffic、看實際 billing</li>
<li>Heavy analytics 改 <em>材料化 view</em> / <em>async aggregation</em>、不是每次 query</li>
<li>高 read frequency 開 Boost cache（額外 cost、但比 row read 便宜）</li>
</ul>
<h2 id="capability-mapping">Capability mapping</h2>
<table>
  <thead>
      <tr>
          <th>自管 Vitess</th>
          <th>PlanetScale 對應</th>
          <th>兼容度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VTGate</td>
          <td>PlanetScale endpoint</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>VTTablet</td>
          <td>PlanetScale managed</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>VReplication</td>
          <td>PlanetScale Console + Deploy Request</td>
          <td>90%（內部使用更受限）</td>
      </tr>
      <tr>
          <td>VSchema</td>
          <td>PlanetScale Console / pscale CLI</td>
          <td>95%（custom Vindex 不支援）</td>
      </tr>
      <tr>
          <td>Vitess online DDL</td>
          <td>Deploy Request workflow</td>
          <td>不同 paradigm、功能等價</td>
      </tr>
      <tr>
          <td>Backup</td>
          <td>PlanetScale 自動</td>
          <td>100%（且更好）</td>
      </tr>
      <tr>
          <td>Failover</td>
          <td>PlanetScale 自動</td>
          <td>100%</td>
      </tr>
      <tr>
          <td>Multi-region</td>
          <td>PlanetScale Boost / per-region cluster</td>
          <td>90%</td>
      </tr>
      <tr>
          <td>Custom plugin</td>
          <td>不支援</td>
          <td>0%</td>
      </tr>
      <tr>
          <td>SUPER privilege</td>
          <td>不支援</td>
          <td>0%</td>
      </tr>
  </tbody>
</table>
<h2 id="容量與成本對照">容量與成本對照</h2>
<p>對 200 人 eng team 用自管 Vitess（10 shard、20 TB 資料、50K WPS）：</p>
<table>
  <thead>
      <tr>
          <th>項目</th>
          <th>自管 Vitess（自管 EC2）</th>
          <th>PlanetScale Scaler Pro</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Infrastructure</td>
          <td>~$15K-25K / mo（EC2 + EBS + LB）</td>
          <td>Variable（per row read / write）</td>
      </tr>
      <tr>
          <td>Ops headcount</td>
          <td>2-3 FTE × $150K / yr = $300K-450K / yr</td>
          <td>&lt; 0.5 FTE × $150K = $75K / yr</td>
      </tr>
      <tr>
          <td>Vitess upgrade cost</td>
          <td>每年 1-2 個 SRE × 2 週</td>
          <td>自動</td>
      </tr>
      <tr>
          <td>Per-row read</td>
          <td>不計費</td>
          <td>$1 per 1B row read</td>
      </tr>
      <tr>
          <td>Per-row written</td>
          <td>不計費</td>
          <td>$1.50 per 1M row write</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>EBS $2K-5K / mo</td>
          <td>$1.50 / GB / mo</td>
      </tr>
      <tr>
          <td><strong>總帳</strong></td>
          <td>~$400K-550K / yr</td>
          <td>~$200K-350K / yr（看 traffic）</td>
      </tr>
  </tbody>
</table>
<p>對中型規模、PlanetScale 通常 break-even 或更便宜。對極大規模（&gt; 200K WPS / &gt; 100 TB）PlanetScale Enterprise 需要 commit pricing、不一定划算。</p>
<h2 id="何時不要遷">何時不要遷</h2>
<ul>
<li><strong>跨雲 / on-prem 是 requirement</strong>：PlanetScale cloud-only</li>
<li><strong>Custom Vindex / 特殊 plugin</strong> 大量使用：兼容度低、改造工作量大</li>
<li><strong>規模極大</strong> &gt; 500K WPS / &gt; 200 TB：PlanetScale plan 對應 Enterprise commit、議價辛苦</li>
<li><strong>強合規 / 資料主權限制</strong>：金融 / 政府 / 醫療場景、PlanetScale 不一定能 cover compliance</li>
<li><strong>既有 Vitess team 強 + ops cost 低</strong>：如果 ops 已經精實、不必為 outsource 而 outsource</li>
</ul>
<h2 id="跟其他模組整合">跟其他模組整合</h2>
<h3 id="跟-vitess-sharding">跟 <a href="/blog/backend/01-database/vendors/mysql/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess sharding</a></h3>
<p>本 migration 保留 Vitess sharding 概念、application code 視角幾乎不變。Phase 1 audit 是 <em>Vitess concept 對應 PlanetScale concept</em>、不是 <em>拆 Vitess 換 distributed SQL</em>。</p>
<h3 id="跟--planetscale-from-self-managed-mysql">跟 <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 踩雷、何時不要遷。">→ PlanetScale (from self-managed MySQL)</a></h3>
<p>本 migration 是 <em>Vitess → PlanetScale</em>、前者是 <em>MySQL → PlanetScale</em>。差異：</p>
<ul>
<li><em>MySQL → PlanetScale</em> (Type E)：要學 Vitess 概念 + branch workflow + FK 處理</li>
<li><em>Vitess → PlanetScale</em> (Type C)：只學 branch workflow + ops outsource、保留所有 Vitess investment</li>
</ul>
<p>選哪條 path 取決於起點。</p>
<h3 id="跟-major-version-upgrade">跟 <a href="/blog/backend/01-database/vendors/mysql/major-version-upgrade/" data-link-title="MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌" data-link-desc="MySQL 5.7 → 8.0 三條 default 同時改：charset utf8 → utf8mb4、auth plugin native_password → caching_sha2_password、DDL non-atomic → atomic。本文走 Type E paradigm shift 結構、6 維 audit、4-phase upgrade、5 production 踩雷、何時不要升級。">Major Version Upgrade</a></h3>
<p>從自管 Vitess 上 MySQL 5.7 遷 PlanetScale 也是 <em>同時跨 major version</em>（PlanetScale 跑 8.0+ Vitess）。Application 必須同時處理 5.7 → 8.0 paradigm shift（charset / auth）。</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/vitess-sharding/" data-link-title="MySQL Vitess Sharding：VTGate / VTTablet / VReplication / VSchema 四件套協作" data-link-desc="Vitess 不只是 MySQL sharding proxy、是 4 個 component 協作的完整 sharding 系統 — VTGate（query routing layer）、VTTablet（per-MySQL agent）、VReplication（跨 shard 資料移動）、VSchema（sharding metadata）。本文走 4 件套各自責任、keyspace / shard / tablet 架構、shard key 設計（Vindex）、配置 step-by-step、5 production 踩雷（cross-shard transaction / VStream lag / Vindex 不均勻 / resharding 切流 / VReplication 卡住）、跟自管 sharding 跟 PlanetScale 的對比">Vitess Sharding</a>（self-managed source）</li>
<li><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 踩雷、何時不要遷。">→ PlanetScale from self-managed MySQL</a>（不同起點）</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 踩雷、何時維持原路線。">→ Aurora MySQL</a>（另一條 self-managed → managed path）</li>
<li><a href="/blog/backend/01-database/vendors/mysql/major-version-upgrade/" data-link-title="MySQL 5.7 → 8.0 Major Version Upgrade：character set / authentication / atomic DDL 三條 paradigm 同時換軌" data-link-desc="MySQL 5.7 → 8.0 三條 default 同時改：charset utf8 → utf8mb4、auth plugin native_password → caching_sha2_password、DDL non-atomic → atomic。本文走 Type E paradigm shift 結構、6 維 audit、4-phase upgrade、5 production 踩雷、何時不要升級。">Major Version Upgrade</a>（5.7 → 8.0 同期考量）</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 C operational hybrid）</li>
<li>官方：<a href="https://planetscale.com/docs/imports">PlanetScale Migration Guide</a> / <a href="https://github.com/planetscale/vitess-operator">Vitess Operator</a></li>
</ul>
]]></content:encoded></item></channel></rss>