事情的緣由是想要進行 DB server 的升級,做法有不少種,而最重要的是要將 down time 降低。由於未來有考慮把 DB server 移到 AWS RDB 上頭,參考 AWS RDB 的 import/export 方式,故選擇從 replication slave 來摸摸。
建立 Replication Slave 的流程:
-
將原先的 db1 server 調整成可以成為 master db 的功能
- $ vim /etc/mysql/my.cnf
- 拿掉 bind-address 127.0.0.1
- 指定 server-id = 1
- 指定 log_bin = /var/log/mysql/mysql-bin.log
- innodb_flush_log_at_trx_commit=1
- sync_binlog=1
- $ sudo service mysql restart
- 在 master db 上建立 replication slave 存取權限
- master:mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY 'repl_password';
- 在 master db 上匯出資料
- master:mysql> FLUSH TABLES WITH READ LOCK;
- master:mysql> SHOW MASTER STATUS;
- $ mysqldump -u root -p --all-databases --lock-all-tables > all.sql
- master:mysql> UNLOCK TABLES;
- 想辦法把 all.sql 弄到 slave db server
- 在 db2 server 設定可以成為 slave db 功能
- $ vim /etc/mysql/my.cnf
- 拿掉 bind-address 127.0.0.1
- 指定 server-id = 2
- 指定 log_bin = /var/log/mysql/mysql-bin.log
- $ sudo service mysql restart
- 在 db server 匯入 master db 的資料
- 從 master db server 取得 all.sql
- $ mysql -u root -p < all.sql
- 在 slave db 設定 master db 資訊
- slave:mysql> CHANGE MASTER TO
MASTER_HOST='MasterDBIP',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='File',
MASTER_LOG_POS=Position;
- slave:mysql> START SLAVE;
- slave:mysql> SHOW MASTER STATUS;
- slave:mysql> SHOW SLAVE STATUS;
如此一來,就可以看到 Slave 跟 Master 一直保持同步了,可以用一些指令,如 SELECT count(*) FROM TABLE; 來比較看看。
以上就是架設 MySQL Replication Slave 的流程,接下來是進行 DB Server 移機的過程,目的就是將上述的 db1 server 下線,並改用 db2 server 當 master,有點像是把 switch slave server to master 的味道,過程:
- 鎖住 db1 server
- db1:mysql> FLUSH TABLES WITH READ LOCK;
- 確認 db2 server 資料有 sync
- 在 db2 server 取消 slave 行為
- db2:mysql> STOP SLAVE;
- db2:mysql> RESET SLAVE;
- 將所有相關的 application 的 db 連線導到 db2 server
透過上述 MySQL Replication 移機的方式,所造成的 down time 會小很多。另外,更好的解法是先處理好 primary key (例如 2N 與 2N+1)的問題,然後先把 application db 切到 db2,過一陣子後再把 db1 shutdown ,就可以避免資料遺失問題。
最後補充一下,在 Master DB Server 新增帳號時,在 Slave DB server 並沒有 sync ,解法除了一開始在設定 Slave 前就把帳號建立好外,另一種解法就是讓 Slave DB 先暫停 Slave 角色,接著新增完帳號再重回 Slave 角色,而新資料又可以從 Master sync 回來。
- slave:mysql> STOP SLAVE;
- slave:mysql> 新增使用者;
- slave:mysql> START SLAVE;
關於新增帳號的問題是在於要把 db2(Slave) 轉成 Master 時,需要更新帳號能夠存取 db2 的權限,然而透過上述 mysqldump -u root -p --all-databases --lock-all-tables 更新方式,db2 裡的資料都是以 db1 的環境去設定的。