MySQL 複製 - 效能與擴充套件性的基石 2:部署及其配置

北國丶風光發表於2019-04-03

正所謂理論造航母,現實小帆船。單有理論,不動手實踐,學到的知識猶如空中樓閣。接下來,我們一起來看下如何一步步進行 MySQL Replication 的配置。

為 MySQL 伺服器配置複製非常簡單。但由於場景不同,基本的步驟還是有所差異。最基本的場景是新安裝主庫和備庫,總得來說分為以下幾步:

  1. 在每臺伺服器上建立複製賬號。
  2. 配置主庫和備庫。
  3. 通知備庫連線到主庫並從主庫複製資料。

此外,由於主備部署需要多臺伺服器,但是這種要求對大多數人來說並不怎麼友好,畢竟沒有必要為了學習部署主備結構,多買個雲伺服器。因此,為了測試方便,我們通過 docker 容器技術在同臺機器上部署多個容器,從而實現在一臺機器上部署主備結構。

這裡我們先假定大部分配置採用預設值,在主庫和備庫都是全新安裝並且擁有同樣的資料。接下來,我們將展示如何通過 docker 技術一步步進行復制配置。

此外,我們將推薦一些“安全配置”,以便在不清楚如何配置時,確保資料的安全。

1 部署 docker 環境

1) 部署 docker

什麼?docker 還沒部署?趕緊參考這裡配一個,docker 都沒玩,怎麼和麵試官吹水呀!

2) 拉取 MySQL 映象

docker pull mysql:5.7
複製程式碼

3) 使用 mysql 映象啟動容器

docker run -p 3339:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7 # 啟動 master 容器
docker run -p 3340:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7 # 啟動 slave 容器
複製程式碼

master 對外的埠是 3339,slave 對外的埠是 3340,我們在使用客戶端連線要使用對應的埠連線對應 mysql。

4) 使用命令檢視正在執行的容器

docker ps
複製程式碼

docker-ps

5) 使用客戶端連線工具測試麗連線 mysql

接測試

2 配置 Master 和 Slave

1) 配置 master 通過以下命令進入容器內部

docker exec -it mysql-master /bin/bash
複製程式碼

a) 更新 apt-get 源

apt-get update
複製程式碼

b) 安裝 vim

apt-get install vim
複製程式碼

c) 配置 my.cnf

vim /etc/mysql/my.cnf
// 在my.cnf 中新增如下配置
server-id=110 # 伺服器 id,同一區域網內唯一
log-bin=/var/lib/mysql/mysql-bin # 二進位制日誌路徑
複製程式碼

d) 重啟 mysql 服務使配置生效

service mysql restart
複製程式碼

e) 啟動容器 重啟 mysql 服務時會使得 docker 容器停止,需要重啟容器。

docker start mysql-master
複製程式碼

f) 建立資料同步使用者並授權

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
複製程式碼

2) 配置 slave 通過以下命令進入容器內部

docker exec -it mysql-slave /bin/bash
複製程式碼

a) 配置 my.cnf

vim /etc/mysql/my.cnf
// 在my.cnf 中新增如下配置
server-id=120 # 伺服器 id,同一區域網內唯一
log-bin=/var/lib/mysql/mysql-bin # 二進位制日誌路徑
relay_log=/path/to/logs/relay-bin # 中繼日誌路徑
複製程式碼

** 3) 關聯 master 和 slave** 配置完 master 和 slave,接下來就要讓 master 和 slave 相關聯。 回到我們的伺服器,先找出 master 和 slave 容器的 IP,執行:

docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master
複製程式碼

master IP

因此,我們知道了 mysql-master 容器的 IP 是:172.17.0.3。同樣的方法,mysq-slave 容器的 IP 是:172.17.0.4。記住這兩個值,後面的配置需要用到。

我們首先配置 master。在 master 容器內通過 mysql -u root -p 進入 MySQL 命令列,執行 show master status;

master狀態

上圖中,File 和 Position 欄位對應的值要記錄下來,後續在 slave 配置時需要用到這兩個值。要注意的是,記錄完這兩個值後,就不能在 master 庫上做任何操作,否則會出現資料不同步的情況。

接下來配置 slave,同樣的,在 slave 上進入 MySQL 命令列。然後執行下面語句:

change master to master_host='172.17.0.3', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos=42852, master_connect_retry=30;
複製程式碼

change master to 是 slave 配置 master 的命令,相關引數含義如下:

  • master_host:master 的IP,就是我們上面獲取的 IP 地址
  • master_port:master 的埠號,也就是我們 master mysql 的埠號
  • master_user:進行資料同步的使用者
  • master_password:同步使用者的密碼
  • master_log_file:指定 slave 從 master 的哪個日誌檔案開始複製資料,也就是我們上面提到的 File 欄位的值
  • master_log_pos:從 master 日誌檔案的那個位置開始讀,上面提到的 Position 欄位的值
  • master_connect_retry:重試時間間隔。單位是秒,預設 60

3 啟動複製

配置完 slave 後,可以通過 show slave status\G; 檢視 slave 的狀態。

lave 狀態

正常情況下,剛配置完 slave 的 Slave_IO_Running 和 Slave_SQL_Runing 都是 NO,因為我們還沒開啟主從複製。使用 start slave 開啟主從複製,然後再查下 slave 狀態。

開啟主從複製後的 slave 狀態

slave 的 Slave_IO_Running 和 Slave_SQL_Runing 都是 YES,說明主從複製已成功啟動。此時,可以通過客戶端能否成功複製資料。

我們在 master 新建 replication 庫,然後觀察 slave 庫是否建立了 replication 庫,如下圖,表示複製成功。

主從複製測試

另外,開啟主從複製後,如果出現以下情況:

Slave_IO_Running: CONNECTING
Slave_SQL_RUNNING: Yes
複製程式碼

表示開啟主從複製後, slave 的 IO 程式連線 master 出現問題,一直在重試連線。我們可以根據 Last_IO_Error 的提示進行解決:

  1. 網路不通。檢查 IP、port。
  2. 密碼錯誤。檢查配置的同步使用者和密碼是否正確。
  3. pos 錯誤。檢查 slave 配置的 Position 的值 與 master 是否一致。

4 從另一個伺服器開始複製

前面的設定都是假定主備庫均為剛剛安裝好且都是預設的資料,也就是說兩臺伺服器上資料相同,並且知道當前主庫的二進位制日誌。但在實際環境中,大多數情況下是有一個一級執行了一段時間的主庫,然後用一臺新安裝的備庫與之同步,此時這臺備庫還沒有資料。

有幾種方法來初始化備庫或者從其他伺服器克隆資料到備庫。包括從主庫複製資料、從另外一臺備庫克隆資料,以及使用最近的一次備份來啟動備庫等。而這些方法都需要有三個條件來讓主庫與備庫保持同步:

  • 在某個時間點的主庫的資料快照。
  • 主庫當前的二進位制日誌檔案,和獲得資料快照時在該二進位制日誌檔案中的偏移量。我們把這兩個值稱為日誌檔案座標(log file coordinates)。通過這兩個值可以確定二進位制日誌的位置。可以通過 SHOW MASTER STATUS 命令來獲取這些值。
  • 從快照時間到現在的二進位制日誌。

下面是一些從別的伺服器克隆備庫的方法:

  1. 使用冷備份。最基本的方法是關閉主庫,把資料複製到備庫。重啟主庫後,會使用一個新的二進位制日誌檔案,我們在備庫通過執行 CHANGE MASTER TO 指向這個檔案的起始處。不過這個方法的缺點很明顯:在複製資料時需要關閉主庫。
  2. 使用熱備份。如果僅使用了 MyISAM 表,可以在主庫執行時使用 mysqlhotcopy 或 rsync 來複制資料。
  3. 使用 mysqldump。如果只包含 InnoDB 表,可以使用以下命令來轉儲主庫資料並將其載入到備庫,然後設定相應的二進位制日誌座標:mysqldump --single-transaction --all-databases --master-data=1 --host=server1 | mysql --host=server2。選項 --single-transaction 使得轉儲的資料為事務開始前的資料。如果使用的是非事務型表,可以使用 --lock-all-tables 選項來獲得所有表的一致性轉儲。
  4. 使用快照或備份。只要知道對應的二進位制日誌座標,就可以使用主庫的快照或者備份來初始化備庫。(如果使用備份,需要確保從備份的時間點開始的主庫二進位制日誌都要存在)。只需要把備份或快照恢復到備庫,然後使用 CHANGE MASTER TO 指定二進位制日誌的座標。
  5. 使用 Percona Xtrabackup。Percona 的 Xtrabackup 是一款開源的熱備份工具。它能夠在備份時不阻塞伺服器的操作,因此可以在不影響主庫的情況下設定備庫。可以通過克隆主庫或另一個已存在的備庫的方式來建立備庫。
  6. 使用另外的備庫。可以使用任何一種克隆或拷貝技術從任意一臺備庫上將資料克隆到另外一臺伺服器。但是如果使用的是 mysqldump,--master-data 選項就會不起作用。此外,不能使用 SHOW MASTER STATUS 來獲得主庫的二進位制日誌座標,而是在獲取快照時使用 SHOW SLAVE STATUS 來獲取備庫在主庫上的執行位置。使用另外的備庫進行資料克隆最大的缺點是,如果這臺備庫的資料已經和主庫不同步,克隆得到的就是髒資料。

5 推薦的複製配置

我們知道,MySQL 的複製有許多引數可以控制,其中一些會對資料安全和效能產生影響。這裡,我們介紹一種“安全配置”,可以最小化問題發生的概率。

在主庫上二進位制日誌最重要的選項是 sync_binlog:

sync_binlog=1 如果開啟該選項,MySQL 每次在提交事務前會將二進位制日誌同步到磁碟上,保證在伺服器崩潰時不會丟失時間。如果禁止該選項,伺服器會少做一些工作,但二進位制日誌檔案可能在伺服器崩潰時損壞或丟失資訊。在一個不需要作為主庫的備庫上 ,該選項會帶來不必要的開銷。要注意的是,它只適用於二進位制日誌,而非中繼日誌。

如果無法接受伺服器崩潰導致表損壞,推薦使用 InnoDB。MyISAM 表在備庫伺服器崩潰重啟後,可能已經處於不一致狀態。

如果使用 InnoDB,推薦設定如下選項:

innodb_flush_logs_at_trx_commit=1 # 每次事務提交時,將 log buffer 寫入到日誌檔案並重新整理到磁碟。預設值為 1
innodb_safe_binlog
複製程式碼

明確指定二進位制日誌檔案的名稱。當伺服器間轉移檔案、克隆新的備庫、轉儲備份或者其他場景下,如果以伺服器名來命名二進位制日誌可能會導致很多問題。因此,我們需要給 log_bin 選項指定一個引數。

log_bin=/var/lib/mysql/mysql-bin
複製程式碼

在備庫上,同樣開啟如下培訓,為中繼日誌指定絕對路徑:

relay_log=/path/to/logs/relay-bin
skip_slave_start
read_only
複製程式碼

通過設定 relay_log 可以避免中繼日誌檔案基於機器名來命名,防止之前提到的可能在主庫上發生的問題。而 skip_slave_start 選項能夠阻止備庫在崩潰後自動啟動複製,以留出時間修復可能發生的問題。read_only 選項可以阻止大部分使用者更改非臨時表。

6 小結

  1. 複製初始化配置三部曲:建立賬號、配置主備庫、備庫連線到主庫開始複製;
  2. 從已有伺服器複製時,可用熱備份或 mysqldump 命令進行備份;
  3. 在不確定相關配置時,選擇最安全的配置準沒錯;

相關文章