[MySQL] 8.0 replica

最近剛好需要幫公司的資料庫做 replica, 但由於之前的資料庫沒有開啟 binlog,
所以研究了一下該怎麼操作。

如果是剛開始建立服務,建議 binlog 的設定要記得打開,如果沒有打開的話,變成要實作 replica 就需要先將資料備份出來,然後在備份出來的 master 資料還原給 slave,之後再去開啟 master 的 binlog,與建立要給 slave 同步用的帳號。

稍微解釋一下主從式架構,主要是由 master 來執行讀與寫,然後每個操作會記錄在 binlog 中,master 會透過 REPLICATION 這個權限讓 slave 可以去取回 binlog 的操作,藉由非同步的方式同步資料。

預先提醒,如果 slave 是由 master 透過複製虛擬機出來的,如果遇到
Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs;  these UUIDs must be different for replication to work
這個錯誤,就是代表 MySQL Server 的 UUID 重複,這時候只需要把 slave 的
/var/lib/mysql/auto.cnf 這個檔案刪除,之後執行
service mysql restart
就可以解決問題囉!

Master

1. 以 Ubuntu 20.10 為例,MySQL 設定 replica 的設定檔在
/etc/mysql/mysql.conf.d/mysqld.cnf
在該檔案中加入

binlog_do_db = 指定的資料庫
bind-address = 0.0.0.0
server_id = 1
log_bin = /var/lib/mysql/mysql-bin.log
log-slave-updates = 0
expire_logs_days = 10
# 如果開始 sync_binlog = 1 與innodb_flush_log_at_trx_commit
# 一致性會是最好,但會影響效能。
sync_binlog = 0
innodb_flush_log_at_trx_commit = 0
# innodb_buffer_pool_size 建議是整個主機記憶體的 80%
innodb_buffer_pool_size = 2G


存擋之後執行
service mysql restart

讓設定檔生效

之後建立一個 replication 的 mysql 用戶,讓 slave 可以抓取 binlog
先透過 mysql-client-cli:
mysql -uroot -p

mysql > create user 'replication'@'%' IDENTIFIED by '指定的密碼';
mysql > ALTER USER 'replication'@'%' IDENTIFIED WITH mysql_native_password BY '指定的密碼';
mysql > GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';
mysql > FLUSH PRIVILEGES;
接下來要記 File & Position
mysql > SHOW MASTER STATUS;

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 |      550 | 指定的資料庫      |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

在這邊就是記住 mysql-bin.000002 與 550

Slave

1. 以 Ubuntu 20.10 為例,MySQL 設定 replica 的設定檔在
/etc/mysql/mysql.conf.d/mysqld.cnf
在該檔案中加入

# server_id 必須跟 master 不同,如果有多台 slave,id 都需要不同。

server_id = 2
log_bin = /var/lib/mysql/mysql-bin.log
relay-log = /var/log/mysql/mysql-relay-bin.log
log-slave-updates = 0
expire_logs_days = 10
sync_binlog = 0
innodb_flush_log_at_trx_commit = 0
innodb_buffer_pool_size = 2G
# 加入 read_only = 1 是防止程式端對 slave 寫入,造成不一致,也可不用。
read_only = 1

接著一樣
# mysql -uroot -p


如果 slave 已經有執行的話,先停止 slave
mysql > STOP SLAVE;


接下來
mysql > CHANGE MASTER TO MASTER_HOST='master的 IP',MASTER_USER='replication', MASTER_PASSWORD='指定的密碼', MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=  550;
mysql > START SLAVE;


要看有沒有成功:
mysql > SHOW SLAVE STATUS;

如果有看到
Waiting for master to send event
那就是成功了!

備註:
MySQL 5.7 建立用戶是
create user 'neil'@'%' IDENTIFIED by '指定的密碼';
GRANT ALL privileges on 指定的資料庫名稱.* to neil@'%'identified by '指定的密碼';
但這樣會造成使用 mysql gui client 連線不上(MySQL 8.0)
所以如果資料庫是 8.0 以上的版本
create user 'neil'@'%' IDENTIFIED by '指定的密碼';
GRANT ALL PRIVILEGES ON *.* TO 'neil'@'%' WITH GRANT OPTION;
ALTER USER 'neil'@'%' IDENTIFIED WITH mysql_native_password BY '指定的密碼';

Ref:

留言

這個網誌中的熱門文章

[翻譯] 介紹現代網路負載平衡與代理伺服器

Grafana K6

Linux 事件驅動筆記