<?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/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Master Slave Replication｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/master-slave-replication/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>Master Slave Replication｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/master-slave-replication/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Thu, 25 Mar 2021 16:45:58 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/master-slave-replication/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MySQL Master Slave Replication 主從式架構設定教學</title>
      <link>https://deanlin.net/blog/202103/mysql-master-slave-replication/</link>
      <pubDate>Thu, 25 Mar 2021 16:45:58 +0800</pubDate>
      <guid>https://deanlin.net/blog/202103/mysql-master-slave-replication/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>Master Slave Replication 是一個 Web 工程師需要具備的基礎概念，我們可以透過這個技術有效的降低 Database server 負荷，同時給使用者提供更穩定順暢的體驗；本文除了讓你了解這個技術的原理外還會以 MySQL…</description>
      <media:content url="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-og_hu_19e34a7748bd18bb.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-01.webp" width="1400" height="783" alt="MySQL Master Slave Replication 主從式架構設定教學（圖 1）" fetchpriority="high" decoding="async"></p>
<p>Master Slave Replication 是一個 Web 工程師需要具備的基礎概念，我們可以透過這個技術有效的降低 Database server 負荷，同時給使用者提供更穩定順暢的體驗；本文除了讓你了解這個技術的原理外還會以 MySQL 這門資料庫語言一步步透過實作讓你理解如何實現它。</p>
<pre tabindex="0"><code>一、30 秒認識 Master Slave Replication 是什麼
  ∙ 為什麼需要 Master Slave Replication 的架構？
  ∙ Master Slave Replication 為什麼能夠解決這些問題？
  ∙ Master Slave Replication 的架構
二、實作 MySQL Master Slave replication
  ∙ 前置作業
  ∙ 建立MySQL Replication
三、驗證 Master、Slave DB 是否同步
</code></pre><h2 id="一30-秒認識-master-slave-replication-是什麼">一、30 秒認識 Master Slave Replication 是什麼<a class="h-anchor" href="#%e4%b8%8030-%e7%a7%92%e8%aa%8d%e8%ad%98-master-slave-replication-%e6%98%af%e4%bb%80%e9%ba%bc" aria-label="這個段落的連結"></a></h2>
<h3 id="為什麼需要-master-slave-replication-的架構">為什麼需要 Master Slave Replication 的架構？<a class="h-anchor" href="#%e7%82%ba%e4%bb%80%e9%ba%bc%e9%9c%80%e8%a6%81-master-slave-replication-%e7%9a%84%e6%9e%b6%e6%a7%8b" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>網站需要面對大流量</strong>：新聞媒體類的網站無論哪個時段都會被大量的檢索，如果資料庫只用一個 server 來處理會無法負荷瞬間的高流量。</li>
<li><strong>資料庫內容需要被分析</strong>：公司如果有資料分析部門，他們也會隨時監控資料庫的變化來產生報表，但如果跟一般使用者一樣 query 同一台 server 會使這台 server 增加不必要的負荷導致使用者體驗下降。</li>
</ul>
<h3 id="master-slave-replication-為什麼能夠解決這些問題">Master Slave Replication 為什麼能夠解決這些問題？<a class="h-anchor" href="#master-slave-replication-%e7%82%ba%e4%bb%80%e9%ba%bc%e8%83%bd%e5%a4%a0%e8%a7%a3%e6%b1%ba%e9%80%99%e4%ba%9b%e5%95%8f%e9%a1%8c" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>主從式架構</strong>：將資料庫的 server 區分成 Master(1台) 與 Slave(N台) 兩種，Master 負責資料寫入，Slave 提供資料檢索；這樣就把壓力分散到幾台 Server 上面。</li>
<li><strong>資料庫同步</strong>：Slave 會同步 Master 的資料，這樣除了分散 server 壓力外，資料也獲得了備份。</li>
</ul>
<h3 id="master-slave-replication-的架構">Master Slave Replication 的架構<a class="h-anchor" href="#master-slave-replication-%e7%9a%84%e6%9e%b6%e6%a7%8b" aria-label="這個段落的連結"></a></h3>
<ol>
<li>在 master 的 server 執行的 SQL command 會被記錄在 Binary Log 裡面</li>
<li>master 將 Binary Log 傳送到 slave 的 Relay Log</li>
<li>slave 依據 Relay Log 做資料的變更</li>
</ol>
<figure class="figure"><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-02.webp" width="1194" height="738" alt="Relay Log 與 Binary Log檔案格式、內容都一樣，不同在於 slave 在執行完 Relay Log 的 SQL 之後，會自己刪除當前的 Relay Log" loading="lazy" decoding="async">
  <figcaption>Relay Log 與 Binary Log檔案格式、內容都一樣，不同在於 slave 在執行完 Relay Log 的 SQL 之後，會自己刪除當前的 Relay Log</figcaption>
</figure>

<h2 id="二實作-mysql-master-slave-replication">二、實作 MySQL Master Slave replication<a class="h-anchor" href="#%e4%ba%8c%e5%af%a6%e4%bd%9c-mysql-master-slave-replication" aria-label="這個段落的連結"></a></h2>
<h2 id="前置作業">前置作業<a class="h-anchor" href="#%e5%89%8d%e7%bd%ae%e4%bd%9c%e6%a5%ad" aria-label="這個段落的連結"></a></h2>
<h3 id="-準備兩台-ubuntu-server-自己實驗建議使用-vmware筆者環境配置如下">準備兩台 ubuntu server (自己實驗建議使用 VMWARE)，筆者環境配置如下<a class="h-anchor" href="#-%e6%ba%96%e5%82%99%e5%85%a9%e5%8f%b0-ubuntu-server-%e8%87%aa%e5%b7%b1%e5%af%a6%e9%a9%97%e5%bb%ba%e8%ad%b0%e4%bd%bf%e7%94%a8-vmware%e7%ad%86%e8%80%85%e7%92%b0%e5%a2%83%e9%85%8d%e7%bd%ae%e5%a6%82%e4%b8%8b" aria-label="這個段落的連結"></a></h3>
<blockquote>
<p>硬體配置一定會影響到效能，筆者只是建置一個提供實驗的環境而已</p>
</blockquote>
<ul>
<li>OS version：ubuntu 16.04</li>
<li>RAM：1G</li>
<li>ROM：8G</li>
</ul>
<h3 id="-給兩台-sever-安裝-mysql">給兩台 sever 安裝 MySQL<a class="h-anchor" href="#-%e7%b5%a6%e5%85%a9%e5%8f%b0-sever-%e5%ae%89%e8%a3%9d-mysql" aria-label="這個段落的連結"></a></h3>
<p>安裝指令如下</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update
</span></span><span style="display:flex;"><span>sudo apt install mysql-server
</span></span></code></pre></div><p>安裝完成後你可以先登入 MySQL 看看安裝版本資訊</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mysql -u root -p
</span></span></code></pre></div><p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-03.webp" width="1400" height="491" alt="給兩台 sever 安裝 MySQL（圖 3）" loading="lazy" decoding="async"></p>
<h2 id="建立mysql-replication">建立MySQL Replication<a class="h-anchor" href="#%e5%bb%ba%e7%ab%8bmysql-replication" aria-label="這個段落的連結"></a></h2>
<h3 id="-master-server-設定">Master server 設定<a class="h-anchor" href="#-master-server-%e8%a8%ad%e5%ae%9a" aria-label="這個段落的連結"></a></h3>
<p><strong>STEP 1</strong>：設定 Master server 的 my.cnf</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo vi /etc/mysql/my.cnf
</span></span></code></pre></div><pre tabindex="0"><code>[mysqld]
# 在這裡設定已蓋過預設的127.0.0.1(只能連本機)
bind-address = 0.0.0.0

# id為唯一值，每個server不可重覆
server-id = 1

# 指定產生bin log檔案名稱，使MySQL記錄所有DB交易記錄
log-bin=mysql-bin
</code></pre><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/a555262a58eb9245c7ffcbcf891791ca" rel="noopener">my.cnf</a>（GitHub Gist）</p>
<p>儲存後，重啟 MySQL 才會生效</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo /etc/init.d/mysql restart
</span></span></code></pre></div><p><strong>STEP 2</strong>：在 Master server 建立給 Slave 複製資料的帳號</p>
<p>登入 MySQL</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo mysql -u root -p
</span></span></code></pre></div><p>建立有 REPLICATION、SLAVE 權限的 user 帳號</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">/*建立使用者*/</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>mysql<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">CREATE</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">USER</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;account&#39;</span><span style="color:#ff7b72;font-weight:bold">@</span><span style="color:#a5d6ff">&#39;ip&#39;</span><span style="color:#6e7681"> </span>IDENTIFIED<span style="color:#6e7681"> </span><span style="color:#ff7b72">BY</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;password&#39;</span>;<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">/*給使用者權限*/</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>mysql<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">GRANT</span><span style="color:#6e7681"> </span>REPLICATION<span style="color:#6e7681"> </span>SLAVE<span style="color:#6e7681"> </span><span style="color:#ff7b72">ON</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">*</span>.<span style="color:#ff7b72;font-weight:bold">*</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">TO</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#39;account&#39;</span><span style="color:#ff7b72;font-weight:bold">@</span><span style="color:#a5d6ff">&#39;ip&#39;</span>;<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">/*使權限生效*/</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>mysql<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>FLUSH<span style="color:#6e7681"> </span><span style="color:#ff7b72">PRIVILEGES</span>;<span style="color:#6e7681">
</span></span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/68f42b828e24df0209600dee7a7030c7" rel="noopener">create_slave_user.sql</a>（GitHub Gist）</p>
<p><strong>STEP 3</strong>：備份 Master server 的 DB</p>
<blockquote>
<p>執行此步驟時如果系統已經上線，一定要發出公告說明系統維護時間</p>
</blockquote>
<p>在完成 DB Replication 前，為了保證 Master 與 Slave 的資料相同，你需要先把 DB Lock 成 read only：</p>
<pre tabindex="0"><code>mysql&gt; FLUSH TABLES WITH READ LOCK;
</code></pre><p>備份指令：</p>
<pre tabindex="0"><code>mysqldump -uroot -p  --all-databases &gt; master.sql
</code></pre><p>解除 read only：</p>
<pre tabindex="0"><code>mysql&gt; UNLOCK TABLES;
</code></pre><p><strong>STEP 4</strong>：檢查 Master 是否已經啟動</p>
<pre tabindex="0"><code>mysql&gt; SHOW MASTER STATUS \G
</code></pre><p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-04.webp" width="1142" height="330" alt="Master server 設定（圖 4）" loading="lazy" decoding="async"></p>
<h3 id="-slave-server-設定">Slave server 設定<a class="h-anchor" href="#-slave-server-%e8%a8%ad%e5%ae%9a" aria-label="這個段落的連結"></a></h3>
<p><strong>STEP 1</strong>：將剛剛備份的 <code>master.sql</code> 還原到 Slave server 的 DB</p>
<p>先複製 master.sql 到 Slave server 的目錄下</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo scp master.sql &lt;username&gt;@&lt;IP or hostname&gt;:&lt;Destination&gt;
</span></span></code></pre></div><p>下指令還原 DB</p>
<pre tabindex="0"><code>mysql -u root -p — default-character-set=utf8 &lt; master.sql
</code></pre><h3 id="step-2設定-slave-server-的-mycnf">STEP 2：設定 Slave server 的 my.cnf<a class="h-anchor" href="#step-2%e8%a8%ad%e5%ae%9a-slave-server-%e7%9a%84-mycnf" aria-label="這個段落的連結"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo vi /etc/mysql/my.cnf
</span></span></code></pre></div><pre tabindex="0"><code>[mysqld]
#注意：不可與剛剛設定的 Master 重複
server-id=2 

#Slave server 的 DB 開啟唯獨避免被寫入
read-only=on
</code></pre><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/54144c2099368bfc91f2681a47f9bf94" rel="noopener">slave_my.cnf</a>（GitHub Gist）</p>
<p>儲存後，重啟 MySQL 才會生效</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo /etc/init.d/mysql restart
</span></span></code></pre></div><p><strong>STEP 3</strong>：設定 SlaveDB，指定 Master DB 登入資訊，並啟動 Replication</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">/* 這裡的帳號密碼就上面 Master 設定的那組 */</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>mysql<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>CHANGE<span style="color:#6e7681"> </span>MASTER<span style="color:#6e7681"> </span><span style="color:#ff7b72">TO</span><span style="color:#6e7681"> </span>MASTER_HOST<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#39;master_ip&#39;</span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">              </span>MASTER_USER<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#39;account&#39;</span>,<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">              </span>MASTER_PASSWORD<span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#a5d6ff">&#39;password&#39;</span>;<span style="color:#6e7681">
</span></span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/e09739d509230e0b270f7b374c8ba553" rel="noopener">setting_slave_info.sql</a>（GitHub Gist）</p>
<p>啟動 Slave Replication：</p>
<pre tabindex="0"><code>mysql&gt; START SLAVE;
</code></pre><p><strong>STEP 4</strong>：檢查 replication 狀態</p>
<pre tabindex="0"><code>SHOW SLAVE STATUS \G
</code></pre><p>如果下圖紅框皆顯示 Yes 就代表你成功嚕！</p>
<p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-05.webp" width="582" height="268" alt="STEP 2：設定 Slave server 的 my.cnf（圖 5）" loading="lazy" decoding="async"></p>
<p>如果你看到下面這個畫面，可能是因為你的 Master MySQL 的設定有問題，最有可能是『使用者帳號、密碼錯誤』、『bind-address 沒有調整』</p>
<p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-06.webp" width="582" height="268" alt="STEP 2：設定 Slave server 的 my.cnf（圖 6）" loading="lazy" decoding="async"></p>
<h2 id="三驗證-masterslave-db-是否同步">三、驗證 Master、Slave DB 是否同步<a class="h-anchor" href="#%e4%b8%89%e9%a9%97%e8%ad%89-masterslave-db-%e6%98%af%e5%90%a6%e5%90%8c%e6%ad%a5" aria-label="這個段落的連結"></a></h2>
<p>先在 Master 確認是不是真的有跟 Slave 串接成功</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff7b72">show</span><span style="color:#6e7681"> </span>slave<span style="color:#6e7681"> </span>hosts;<span style="color:#6e7681">
</span></span></span></code></pre></div><p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-07.webp" width="1400" height="274" alt="三、驗證 Master、Slave DB 是否同步（圖 7）" loading="lazy" decoding="async"></p>
<p>確認連接成功後我們在 Master server 上面新增一個 DB</p>
<p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-08.webp" width="342" height="479" alt="三、驗證 Master、Slave DB 是否同步（圖 8）" loading="lazy" decoding="async"></p>
<p>回到 Slave server 就會看到 DB 被同步過來嚕～</p>
<p><img src="https://deanlin.net/blog/202103/mysql-master-slave-replication/images/mysql-master-slave-replication-09.webp" width="342" height="217" alt="三、驗證 Master、Slave DB 是否同步（圖 9）" loading="lazy" decoding="async"></p>
<hr>
<p>這篇文章是針對 MySQL Master Slave Replication 做說明，但你依照上面的做法完成後還需要思考幾個問題：</p>
<ul>
<li>我們知道 Master server 是用來更新資料，Slave server 是用來檢索資料；但他們都是獨立的 ip，總不能每個 api 執行時都連不一樣的 ip 吧？</li>
<li>Slave 的資料是從 Master 上複製過來的，會複製就代表會有延遲，要如何保持資料的一致性呢？</li>
</ul>
<pre tabindex="0"><code>如果你想深入了解上面的問題如何解決可以參考我的文章：
👍 在 MySQL 5.7 解決主從複製的延遲問題
👍 Ubuntu 用 Atlas 實現 MySQL Proxy 讀寫分離 read/write splitting
</code></pre><hr>
<p>參考資源：<a href="https://dotblogs.com.tw/eric_obay_talk/2018/10/24/160017">MySQL Master Slave replication</a>、<a href="https://ithelp.ithome.com.tw/articles/10236724">打造MySQL Replication</a></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
