<?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>GitHub on Tarragon</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/cases/github/</link><description>Recent content in GitHub on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 01 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/github/index.xml" rel="self" type="application/rss+xml"/><item><title>GitHub 2018 Oct21 MySQL Topology Incident</title><link>https://tarrragon.github.io/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/</guid><description>&lt;p>2018 年 GitHub Oct21 事故的核心教訓是：跨區資料庫在 network partition 後，最困難的是如何在可用性與資料一致性之間做出可回放的決策，切換本身只是其中一步。&lt;/p>
&lt;h2 id="事故摘要">事故摘要&lt;/h2>
&lt;p>GitHub 在 2018-10-21 22:52 UTC 因例行網路設備維護引發 network partition，導致跨區 MySQL replication topology 進入異常狀態。應用層在切換後持續寫入新主站，形成跨區未對齊寫入，事故最終歷時約 24 小時 11 分鐘。&lt;/p>
&lt;p>官方 post-incident analysis 指出，團隊選擇 fail-forward，而不是直接切回原主站，原因是要優先保護資料完整性，避免產生更大不一致。&lt;/p>
&lt;h2 id="判讀訊號">判讀訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>事故中代表什麼&lt;/th>
 &lt;th>第一波決策價值&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>多個服務同時顯示資料過舊或不一致&lt;/td>
 &lt;td>replication topology 已跨區失衡&lt;/td>
 &lt;td>先凍結變更與部署，避免拓撲再變化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Orchestrator 顯示非預期跨區主從關係&lt;/td>
 &lt;td>自動切換已進入複雜狀態&lt;/td>
 &lt;td>轉人工決策，先保資料一致性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>webhook / Pages backlog 快速累積&lt;/td>
 &lt;td>控制面與資料面都受影響&lt;/td>
 &lt;td>將積壓處理納入恢復計畫，而非只看 API 健康度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>status 更新頻率下降&lt;/td>
 &lt;td>指揮資訊與恢復節奏未對齊&lt;/td>
 &lt;td>補 decision log 與分階段狀態更新&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="事故路徑">事故路徑&lt;/h2>
&lt;ol>
&lt;li>例行網路設備維護造成 East 與主資料中心連線中斷。&lt;/li>
&lt;li>Orchestrator 在 partition 下進行主從重新選舉與切換。&lt;/li>
&lt;li>連線恢復後，應用寫入已落在新主站，形成跨站寫入差異。&lt;/li>
&lt;li>團隊凍結部署並轉人工處理拓撲與一致性風險。&lt;/li>
&lt;li>選擇 fail-forward，逐步恢復服務與處理 backlog。&lt;/li>
&lt;li>事故結束後回寫跨資料中心設計、通訊粒度與演練策略。&lt;/li>
&lt;/ol>
&lt;h2 id="可回寫控制面">可回寫控制面&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>控制面&lt;/th>
 &lt;th>這次事故暴露的缺口&lt;/th>
 &lt;th>回寫方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cross-DC replication guardrail&lt;/td>
 &lt;td>partition 後拓撲變更過快&lt;/td>
 &lt;td>增加拓撲變更保護與人工切換門檻&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Consistency-first decision path&lt;/td>
 &lt;td>可用性與一致性取捨缺標準化準則&lt;/td>
 &lt;td>在 decision log 固定記錄 fail-forward / fail-back 判準&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Backlog recovery strategy&lt;/td>
 &lt;td>webhook / Pages 積壓恢復節奏缺共識&lt;/td>
 &lt;td>將 backlog drain 納入 recovery completion 定義&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Incident communication granularity&lt;/td>
 &lt;td>只用單一顏色狀態無法表達部分恢復&lt;/td>
 &lt;td>對外更新按子服務與恢復階段拆分&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>事故通訊： &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-communication/" data-link-title="8.4 事故通訊與狀態更新" data-link-desc="建立內外部通報節奏與狀態更新格式">8.4 Incident Communication&lt;/a>&lt;/li>
&lt;li>止血與回復： &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3 Containment / Recovery Strategy&lt;/a>&lt;/li>
&lt;li>事中決策紀錄： &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log&lt;/a>&lt;/li>
&lt;li>證據回寫流程： &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back&lt;/a>&lt;/li>
&lt;li>資料庫轉換實作： &lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 資料庫轉換實作&lt;/a>&lt;/li>
&lt;li>Migration rollout evidence： &lt;a href="https://tarrragon.github.io/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 Schema Migration Rollout 證據&lt;/a>&lt;/li>
&lt;li>選型決策層： &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/" data-link-title="營運後技術轉換：語言、工具與架構何時該換" data-link-desc="服務營運一段時間後，如何判讀何時該轉語言、工具或架構，並用案例說明轉換動機。">0.C4 營運後技術轉換&lt;/a>&lt;/li>
&lt;li>穩態與恢復完成： &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22 Steady State Definition&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="引用源">引用源&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.blog/2018-10-30-oct21-post-incident-analysis/">October 21 post-incident analysis&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.blog/news-insights/company-news/october21-incident-report/">October 21 Incident Report&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>2018 年 GitHub Oct21 事故的核心教訓是：跨區資料庫在 network partition 後，最困難的是如何在可用性與資料一致性之間做出可回放的決策，切換本身只是其中一步。</p>
<h2 id="事故摘要">事故摘要</h2>
<p>GitHub 在 2018-10-21 22:52 UTC 因例行網路設備維護引發 network partition，導致跨區 MySQL replication topology 進入異常狀態。應用層在切換後持續寫入新主站，形成跨區未對齊寫入，事故最終歷時約 24 小時 11 分鐘。</p>
<p>官方 post-incident analysis 指出，團隊選擇 fail-forward，而不是直接切回原主站，原因是要優先保護資料完整性，避免產生更大不一致。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>事故中代表什麼</th>
          <th>第一波決策價值</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多個服務同時顯示資料過舊或不一致</td>
          <td>replication topology 已跨區失衡</td>
          <td>先凍結變更與部署，避免拓撲再變化</td>
      </tr>
      <tr>
          <td>Orchestrator 顯示非預期跨區主從關係</td>
          <td>自動切換已進入複雜狀態</td>
          <td>轉人工決策，先保資料一致性</td>
      </tr>
      <tr>
          <td>webhook / Pages backlog 快速累積</td>
          <td>控制面與資料面都受影響</td>
          <td>將積壓處理納入恢復計畫，而非只看 API 健康度</td>
      </tr>
      <tr>
          <td>status 更新頻率下降</td>
          <td>指揮資訊與恢復節奏未對齊</td>
          <td>補 decision log 與分階段狀態更新</td>
      </tr>
  </tbody>
</table>
<h2 id="事故路徑">事故路徑</h2>
<ol>
<li>例行網路設備維護造成 East 與主資料中心連線中斷。</li>
<li>Orchestrator 在 partition 下進行主從重新選舉與切換。</li>
<li>連線恢復後，應用寫入已落在新主站，形成跨站寫入差異。</li>
<li>團隊凍結部署並轉人工處理拓撲與一致性風險。</li>
<li>選擇 fail-forward，逐步恢復服務與處理 backlog。</li>
<li>事故結束後回寫跨資料中心設計、通訊粒度與演練策略。</li>
</ol>
<h2 id="可回寫控制面">可回寫控制面</h2>
<table>
  <thead>
      <tr>
          <th>控制面</th>
          <th>這次事故暴露的缺口</th>
          <th>回寫方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cross-DC replication guardrail</td>
          <td>partition 後拓撲變更過快</td>
          <td>增加拓撲變更保護與人工切換門檻</td>
      </tr>
      <tr>
          <td>Consistency-first decision path</td>
          <td>可用性與一致性取捨缺標準化準則</td>
          <td>在 decision log 固定記錄 fail-forward / fail-back 判準</td>
      </tr>
      <tr>
          <td>Backlog recovery strategy</td>
          <td>webhook / Pages 積壓恢復節奏缺共識</td>
          <td>將 backlog drain 納入 recovery completion 定義</td>
      </tr>
      <tr>
          <td>Incident communication granularity</td>
          <td>只用單一顏色狀態無法表達部分恢復</td>
          <td>對外更新按子服務與恢復階段拆分</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>事故通訊： <a href="/blog/backend/08-incident-response/incident-communication/" data-link-title="8.4 事故通訊與狀態更新" data-link-desc="建立內外部通報節奏與狀態更新格式">8.4 Incident Communication</a></li>
<li>止血與回復： <a href="/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3 Containment / Recovery Strategy</a></li>
<li>事中決策紀錄： <a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></li>
<li>證據回寫流程： <a href="/blog/backend/08-incident-response/incident-evidence-write-back/" data-link-title="8.22 Incident Evidence Write-back" data-link-desc="把事故證據、決策與復盤結論回寫到 observability、reliability 與 runbook">8.22 Incident Evidence Write-back</a></li>
<li>資料庫轉換實作： <a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 資料庫轉換實作</a></li>
<li>Migration rollout evidence： <a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 Schema Migration Rollout 證據</a></li>
<li>選型決策層： <a href="/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/" data-link-title="營運後技術轉換：語言、工具與架構何時該換" data-link-desc="服務營運一段時間後，如何判讀何時該轉語言、工具或架構，並用案例說明轉換動機。">0.C4 營運後技術轉換</a></li>
<li>穩態與恢復完成： <a href="/blog/backend/06-reliability/steady-state-definition/" data-link-title="6.22 Steady State Definition" data-link-desc="在 chaos 與 failover 前先定義系統應維持的穩定狀態與可接受退化">6.22 Steady State Definition</a></li>
</ul>
<h2 id="引用源">引用源</h2>
<ul>
<li><a href="https://github.blog/2018-10-30-oct21-post-incident-analysis/">October 21 post-incident analysis</a></li>
<li><a href="https://github.blog/news-insights/company-news/october21-incident-report/">October 21 Incident Report</a></li>
</ul>
]]></content:encoded></item></channel></rss>