乘風破浪,遇見雲原生(Cloud Native)之Docker Desktop for Windows 運行MYSQL多實例並實現主從(Master-Slave)部署

什麼是MYSQL主從模式

image

主從複製過程使數據庫管理員能夠同時複製或拷貝存儲在多個服務器中的數據。這有助於數據庫管理員一直創建數據庫的實時備份。在某些情況下,當主從機出現任何問題時,他們可以立即切換到從機數據庫,並保持應用程序正常運行。複製過程確保你的應用程序根本不會面臨任何形式的停機。

在這種複製中,有各種類型的複製過程。你可以有一個主站和多個從站,或者多個主站和多個從站等。

在這個過程中,它總是一個單一的或單向的數據傳輸。數據首先存儲在主站,然後再複製到從站。因此,寫操作只在主數據庫中進行。讀取操作是在主數據庫和從數據庫中進行的。從機也可用於數據訪問,以減少主數據庫的負荷

部署主從實例

新建Master實例

新建名爲mysql-master的實例,端口16000

docker run -d --name mysql-master --restart unless-stopped -p 16000:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40

image

新建Slave實例

新建名爲mysql-slave-01的實例,端口17001

docker run -d --name mysql-slave-01 --restart unless-stopped -p 17001:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40

image

新建名爲mysql-slave-02的實例,端口17002

docker run -d --name mysql-slave-02 --restart unless-stopped -p 17002:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxx mysql:5.7.40

image

爲Master和Slave創建庫表

我們可以使用一些SQL工具連接到Master和所有的Slave,然後通過下面語句創建好數據庫tesla和它名下的數據表order

CREATE DATABASE IF NOT EXISTS tesla;

USE tesla;

CREATE TABLE IF NOT EXISTS `order` (
  `id` int(11) NOT NULL,
  `name` varchar(254) NOT NULL,
  `bir` varchar(254) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

image

等下的主從同步都是基於這些信息來同步的,如果不一致的話,會出現錯誤。

配置Master實例

先將Master實例中配置文件拷貝出來

docker cp mysql-master:/etc/my.cnf F:\mysql-master\my.cnf

image

通過VSCode編輯它,在[client]之前位置,插入兩行配置

skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql

# 開啓Log_bin
log-bin=mysql.bin
# 指定全局唯一ID
server-id=11

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock

其中log-bin=mysql.bin指定了BinLog日誌的相對位置,最終會記錄在/var/lib/mysql/mysql.bin,然後server-id=11,給這個Master實例指定了唯一ID。

這裏還有一些可選的配置:

# 無需同步的數據庫名稱
binlog-ignore-db=mysql
# 設置使用的二進制日誌格式(mixed,statement,row)
binlog_format=mixed
# 設置二進制日誌過期清理時間,默認值爲0,,表示不自動清理
expire_logs_days=7
# 跳過主從複製中遇到的所有錯誤或者指定類型的錯誤,避免slave端的複製中斷
# 如1062錯誤是指一些主鍵重複,1032錯誤是指主從數據庫的數據不一致。
slave_skip_errors=1062

image

將修改後的配置文件拷貝回Master實例

docker cp F:\mysql-master\my.cnf mysql-master:/etc/my.cnf

然後重啓一次Master實例

docker restart mysql-master

image

進入Master實例

docker exec -it mysql-master /bin/bash

image

登錄mysql

mysql -u root -p

然後輸入密碼

image

登錄成功後,通過命令查看log-bin是否開啓成功

show variables like '%log_bin%';

image

創建用於主從複製的賬號

create user 'repl-from-master'@'%' identified by 'xxxxxxxxxx';

image

並且授予其複製權限

grant replication slave,replication client on *.* to 'repl-from-master'@'%';

image

查看實例狀態

show master status;

image

這裏的FilePosition都是我們Slave需要用到的信息,記錄下來。

另外,quit之後,還可以切換到log-bin數據目錄也應該可以看到日誌文件

cd /var/lib/mysql/
ls

image

配置Slave實例

先將Slave實例中配置文件拷貝出來

docker cp mysql-slave-01:/etc/my.cnf F:\mysql-slave-01\my.cnf

image

通過VSCode編輯它,在[client]之前位置,插入兩行配置

skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql

# 指定全局唯一ID
server-id=21

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock

其中server-id=21,給這個Slave實例指定了唯一ID。

這裏還有一些可選的配置:

# 無需同步的數據庫名稱
binlog-ignore-db=mysql
# 設置使用的二進制日誌格式(mixed,statement,row)
binlog_format=mixed
# 設置二進制日誌過期清理時間,默認值爲0,,表示不自動清理
expire_logs_days=7
# 跳過主從複製中遇到的所有錯誤或者指定類型的錯誤,避免slave端的複製中斷
# 如1062錯誤是指一些主鍵重複,1032錯誤是指主從數據庫的數據不一致。
slave_skip_errors=1062
# 將複製事件寫入自己的二進制日誌
log_slave_updates=1
# 設置數據庫數據爲只讀(具有super權限的用戶除外)
read_only=1

image

將修改後的配置文件拷貝回Slave實例

docker cp F:\mysql-slave-01\my.cnf mysql-slave-01:/etc/my.cnf

然後重啓一次Slave實例

docker restart mysql-slave-01

image

進入Slave實例

docker exec -it mysql-slave-01 /bin/bash

image

登錄mysql

mysql -u root -p

然後輸入密碼

image

登錄成功後,爲了防止之前有設置過Slave,我們先做一次停止

stop slave;

image

通過命令設置它Slave哪個Master,相關連接信息和位置是多少。

change master to master_host='192.168.0.109',master_port=16000, master_user='repl-from-master',master_password='xxxxxxxxxxxx',master_log_file='mysql-bin.000004',master_log_pos=154;

image

這些參數的含義分別是

  • master_host=主數據庫IP
  • master_port=主數據端口
  • master_user=在主數據庫創建的用於同步的用戶賬號
  • master_password=在主數據庫創建的用於同步的用戶密碼
  • master_log_file=指定從主數據庫複製數據的日誌文件,查看主數據狀態的File字段的值
  • master_log_pos=指定從主數據庫哪個位置開始複製數據,查看主數據狀態的Position字段的值
  • master_connect_retry=從數據庫連接主數據庫失敗時,重新嘗試連接的間隔時間,單位秒

這裏有個要特別注意的地方,master_host不能使用localhost或者127.0.0.1這樣的,如果是Docker Desktop for Windows可以使用本機的局域網Ip,通過ipconfig可以查閱。

image

重置一次同步

reset slave;

image

然後開始執行同步

start slave;

image

查看同步狀態

show slave status \G;

這裏使用了\G代表以鍵值對的方式輸出結果。

image

其中Slave_IO_RunningSlave_SQL_Running都爲Yes,纔算是正常。

處理異常情況

如果這時候Slave_IO_RunningNo,我們可以考慮先停止Slave

stop slave;

再回到Master裏面,在mysql模式下,執行

flush logs;

刷新下日誌。

再次查看位置

show master status;

image

File的名字會+1

回到Slave實例中更新位置

change master to master_log_file='mysql-bin.000002',master_log_pos=154;

然後先重置一次

reset slave;

然後啓動並查看Slave狀態

start slave;
show slave status \G;

image

驗證主從同步

我們先在Master的tesla庫的order表中新增一條數據。

image

接下來,我們去Slave的tesla庫的order表中看看

image

如果它在那裏,並且和Master保持一致,那麼就同步成功了。

常見錯誤

Error_code: 2003

這個錯誤表示,連接Master用的master_hostmaster_portmaster_usermaster_password四個信息裏面肯定錯了至少一個。

[ERROR] Slave I/O for channel '': error connecting to master 'repl-from-master@localhost:16000' - retry-time: 60  retries: 1, Error_code: 2003

Error_code: 1236

這個錯誤表示,沒有讀取到Master BinLog正確的日誌文件,如果確實文件都在,做一次Master的flush logs;動作,在來Slave修正下位置試試。

[ERROR] Slave I/O for channel '': Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file', Error_code: 1236

Error_code: 1051

這個錯誤表示,同步過來一個刪表動作,但是Slave中根本沒有這個表,估計也是Slave沒有同步創建好這張表。

[ERROR] Slave SQL for channel '': Error 'Unknown table 'tesla.order'' on query. Default database: 'tesla'. Query: 'DROP TABLE `order` /* generated by server */', Error_code: 1051

Error_code: 1146

這個錯誤表示,在Slave中都沒有找到這個名稱的表,可能是Master裏面新建了,但是在Slave中沒有對應的建,這裏補創建下就好了。

[ERROR] Slave SQL for channel '': Error executing row event: 'Table 'tesla.order' doesn't exist', Error_code: 1146

Error_code: 1032

這個錯誤表示,同步過來一個刪除動作,但是Slave中沒有這條記錄。

[ERROR] Slave SQL for channel '': Could not execute Delete_rows event on table tesla.order; Can't find record in 'order', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's master log mysql.000007, end_log_pos 1662, Error_code: 1032

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章