1. 程式人生 > 其它 >mysql-5.7主從複製

mysql-5.7主從複製

一、MySQL主從複製

將主資料庫中的DDL和DML操作通過二進位制日誌傳輸到從資料庫上,然後將這些日誌重新執行(重做)一遍;從而使得從資料庫的資料與主資料庫保持一致。

二、MySQL 主從複製的基本介紹

MySQL支援單向、非同步複製,複製過程中一個伺服器充當主伺服器,而一個或多個其它伺服器充當從伺服器。

MySQL複製是基於主伺服器在二進位制日誌中跟蹤所有對資料庫的更改。因此,要進行復制,必須在主伺服器上啟用二進位制日誌。每個從伺服器從主伺服器接收主伺服器已經記錄到日誌的資料。

當一個從伺服器連線主伺服器時,它通知主伺服器從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,並在本機上執行相同的更新。然後封鎖並等待主伺服器通知新的更新。從伺服器執行備份不會干擾主伺服器,在備份過程中主伺服器可以繼續處理更新。

三、什麼是主從複製

簡單來說,是使用兩個或兩個以上相同的資料庫,將一個數據庫當做主資料庫,而另一個數據庫當做從資料庫。在主資料庫中進行相應操作時,從資料庫記錄下所有主資料庫的操作,使其二者一模一樣。

MySQL資料庫主從複製主要分為三步:

1.master將改變記錄到二進位制日誌(binlog)中(這些記錄叫做二進位制日誌事件,binlog events)。

2.slave的io執行緒將master的binary log events拷貝到它的中繼日誌(relay log)。

3.slave的sql執行緒解析中繼日誌中的事件並在從庫執行,保持與主庫一致。

Binlog:主資料庫的二進位制日誌。

Relay log:從伺服器的中繼日誌。

注意:複製過程有一個很重要的限制——複製在slave上是序列化的,也就是說master上的並行更新操作不能在slave上並行操作。

四、同步過程

# 從庫準備

1.從庫change master to 時,ip port user password binlog position寫入到master.info進行記錄。

2.從庫 start slave 時,會啟動IO執行緒和SQL執行緒。


# 同步流程
1. 從庫的IO執行緒,讀取master.info資訊,獲取主庫資訊並連線主庫。

2. 主庫接收從庫的連結請求後,會生成一個準備binlog dump的執行緒,來響應從庫。

3. 主庫一旦有新的日誌生成,會發送“訊號”給主庫的binlog dump執行緒,然後binlog dump執行緒會讀取binlog日誌的更新。

4. 通過binlog dump執行緒將資料傳送給從庫的IO執行緒。

5. IO執行緒將收到的日誌儲存到了TCP/IP 快取。

6. 寫入TCP/IP快取後,立即返回ACK訊息給主庫 ,此時主庫工作完成。

7. IO執行緒更新master.info檔案、binlog 檔名和postion定位。

8. IO執行緒將快取中的資料,儲存到relay-log日誌檔案,此時io執行緒工作完成。

9. 從庫SQL執行緒讀取relay-log.info檔案,獲取到上次執行到的relay-log的位置,作為起點。

10. 從庫SQL執行緒基於從步驟9中獲取到的起點,去中繼日誌relay-log.000001獲取後續操作,在從庫回放relay-log中繼日誌之中內從主庫複製過來的資料。

11. SQL執行緒回放完成之後,會更新relay-log.info檔案,把當前操作的位置記入,作為下一次操作的起點。

12. relay-log會有自動清理的功能。


#注:在tcp協議中通訊之前都要經過三次握手,請求方發出一個syn訊號請求連線,對方收到並接受的時候就會發出ack訊息,ack就是迴應的意思。


五、主從複製的方式

MySQL的主從複製有兩種複製方式,分別是非同步複製半同步複製

1.非同步複製

我們之前介紹的就是非同步複製,即客戶端執行緒提交一個寫操作,寫入主庫的binlog日誌後就立即返回,並不需要等待從庫完成同步操作,而主庫的dump執行緒會監測binlog日誌的變數然後主動將更新推送給從庫。

MySQL 主從複製預設是非同步的模式。

# 要實現主從複製,需要如下幾步:
1、在主庫上建立一個用於複製的賬號。
2、修改主庫配置檔案,開啟主庫的Binlog,並設定server-id和重啟。
3、匯出主庫中所有的資料,先導給從庫
4、修改從庫配置檔案並重啟
5、配置主從複製
6、開啟主從複製

# 1.主庫建立用於複製的賬號
mysql> grant replication slave on *.* to cp@'172.16.1.%' identified by '123';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

# 2.修改主庫配置檔案
[root@db01 ~]# vim /etc/my.cnf

port=3306
socket=/tmp/mysql.sock
character-set-server=utf8mb4
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld.pid

server-id=1
log-bin=mysql-bin
binlog_format=row
sync_binlog=1
expire_logs_days=10
max_binlog_size=100M
binlog_cache_size=4M
max_binlog_cache_size=512M
binlog-ignore-db=mysql
auto-increment-offset=1
auto-increment-increment=1
slave-skip-errors=all
binlog_rows_query_log_events=on

[mysql]
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

[root@db01 ~]# systemctl restart mysqld

# 3.匯出主庫中所有的資料
[root@db01 ~]# mysqldump -uroot -p123 -A -E -R --triggers --master-data=2 --single-transaction > /tmp/all.sql

# 4.將資料匯入從庫
[root@db01 ~]# scp /tmp/all.sql 172.16.1.52:/root/
all.sql                                               100%  731KB   2.8MB/s   00:00    

[root@db02 ~]# mysql -uroot -p123 < /root/all.sql

# 5.修改從庫配置檔案
[root@db02 ~]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3306
socket=/tmp/mysql.sock
character-set-server=utf8mb4
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld.pid

server-id=2
# 中繼日誌
relay-log=mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%

[mysql]
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

[root@db02 ~]# systemctl restart mysqld

# 6.配置主從複製
-- 配置主從複製,首先得在MySQL Master節點查出binlog日誌狀態,然後配置主從複製
-- 在MySQL master節點查出binlog日誌狀態
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 |      864 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

-- 從庫配置主從複製
#先測試是否能連線主庫
[root@db02 ~]# mysql -ucp -p123 -h172.16.1.51

[root@db02 ~]# mysql -uroot -p123
mysql> change master to
    -> master_host='172.16.1.51',     	   -- 主庫伺服器的IP
    -> master_user='cp',			 	  -- 主庫授權用於複製的使用者
    -> master_password='123',		 	   --  密碼
    -> master_port=3306,			 	   -- 主庫埠
    -> master_log_file='mysql-bin.000005',   -- 主庫日誌名
    -> master_log_pos=864;				    -- 主庫日誌偏移量,即從何處開始複製
Query OK, 0 rows affected, 2 warnings (0.11 sec)

#開啟主從複製
mysql> start slave;
Query OK, 0 rows affected (0.36 sec)

#檢視狀態
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.1.51
                  Master_User: cp
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 864
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

# Slave_IO_Running 和 Slave_SQL_Running 為Yes即成功
 
 
#測試
-- 主庫插入資料
mysql> select * from linux13;
+----+--------+------+------+------+
| id | name   | city | age  | addr |
+----+--------+------+------+------+
|  1 | 張三   | NULL |   18 | NULL |
|  2 | 李四   | NULL |   27 | NULL |
|  3 | 小米   | NULL |   18 | NULL |
|  4 | 熊大   | NULL |   19 | NULL |
|  5 | 熊二   | NULL |   20 | NULL |
+----+--------+------+------+------+
5 rows in set (0.00 sec)

mysql> insert into linux13(id,name,age)  values (6,'楊雪',21);
Query OK, 1 row affected (0.01 sec)

mysql> select * from linux13;
+----+--------+------+------+------+
| id | name   | city | age  | addr |
+----+--------+------+------+------+
|  1 | 張三   | NULL |   18 | NULL |
|  2 | 李四   | NULL |   27 | NULL |
|  3 | 小米   | NULL |   18 | NULL |
|  4 | 熊大   | NULL |   19 | NULL |
|  5 | 熊二   | NULL |   20 | NULL |
|  6 | 楊雪   | NULL |   21 | NULL |
+----+--------+------+------+------+
6 rows in set (0.00 sec)

-- 從庫查詢資料
mysql> select * from linux13;
+----+--------+------+------+------+
| id | name   | city | age  | addr |
+----+--------+------+------+------+
|  1 | 張三   | NULL |   18 | NULL |
|  2 | 李四   | NULL |   27 | NULL |
|  3 | 小米   | NULL |   18 | NULL |
|  4 | 熊大   | NULL |   19 | NULL |
|  5 | 熊二   | NULL |   20 | NULL |
|  6 | 楊雪   | NULL |   21 | NULL |
+----+--------+------+------+------+
6 rows in set (0.00 sec)

2.半同步複製

介於非同步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於非同步複製,半同步複製提高了資料的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網路中使用。

半同步複製超時則會切換回非同步複製,正常後則切回半同步複製

在半同步複製時,如果主庫的一個事務提交成功了,在推送到從庫的過程當中,從庫宕機了或網路故障,導致從庫並沒有接收到這個事務的Binlog,此時主庫會等待一段時間(這個時間由rpl_semi_sync_master_timeout的毫秒數決定),如果這個時間過後還無法推送到從庫,那MySQL會自動從半同步複製切換為非同步複製,當從庫恢復正常連線到主庫後,主庫又會自動切換回半同步複製。

3.主庫配置

# 1.確認主從的MySQL伺服器是否支援動態增加外掛
mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)

# 2.分別在主從資料庫安裝對應外掛 
#二進位制安裝的MySQL的外掛一般放在 /usr/local/mysql/lib/plugin/ 該目錄下

-- 主庫安裝外掛
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.28 sec)


#在主庫開啟半同步複製
mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.09 sec)

mysql> set global rpl_semi_sync_master_timeout=1000;   -- 單位毫秒
Query OK, 0 rows affected (0.00 sec)

# 新增到配置檔案
[root@db01 ~]# vim /etc/my.cnf
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000


4.從庫配置

# 1.確認主從的MySQL伺服器是否支援動態增加外掛
mysql> select @@have_dynamic_loading;
+------------------------+
| @@have_dynamic_loading |
+------------------------+
| YES                    |
+------------------------+
1 row in set (0.00 sec)

# 2.從庫安裝外掛
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.20 sec)

# 3.從庫開啟半同步複製
mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.07 sec)

mysql> stop slave io_thread;
Query OK, 0 rows affected (0.09 sec)

mysql> start slave io_thread;
Query OK, 0 rows affected (0.06 sec)

# 4.新增到配置檔案之中
[root@mysql-2 ~]# vim /etc/my.cnf
rpl_semi_sync_slave_enabled =1

[root@db02 ~]# systemctl restart mysqld


# 5.在主庫上檢視半同步複製的狀態
-- 主庫檢視
mysql> show status like 'Rpl_semi_sync_master_status';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON    |
+-----------------------------+-------+
1 row in set (0.00 sec)
-- 從庫檢視
mysql> show status like 'Rpl_semi_sync_slave_status';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

#這兩個變數常用來監控主從是否執行在半同步複製模式下。

六、主從故障

# IO執行緒故障

#Slave_IO_Running: No 或者 Connecting

1.檢測網路
[root@db02 ~]# ping 172.16.1.51

2.檢測埠
[root@db02 ~]# telnet 172.16.1.51 3306

3.防火牆是否開啟

4.主從的使用者名稱或者密碼錯誤
#測試使用主從使用者的使用者名稱和密碼連線主庫
[root@db02 ~]# mysql -urep -p123 -h172.16.1.51

5.反向解析
[root@db01 ~]# mysql -uroot -p123 -h172.16.1.51
Warning: Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'db01' (using password: YES)
#解決
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
skip_name_resolve


# sql執行緒故障
#Slave_SQL_Running: No 或者 Connecting

1.主庫有的資料,從庫沒有
2.從庫有的資料,主庫沒有
3.主庫資料與從庫不一致

#1)解決辦法一:(不認)
1.停止主從複製
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

2.跳過一個錯誤
mysql> set GLOBAL sql_slave_skip_counter=1;
Query OK, 0 rows affected (0.00 sec)

3.開啟主從
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

#2)解決辦法二:
1.停止主從複製
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

2.清空主從複製的資訊
mysql> reset slave all;
Query OK, 0 rows affected (0.00 sec)

3.同步主庫所有資料

4.重新配置主從複製

七、多主多從

在企業中,資料庫高可用一直是企業的重中之重,中小企業很多都是使用mysql主從方案,一主多從,讀寫分離等,但是單主存在單點故障,從庫切換成主庫需要作改動。因此,如果是雙主或者多主,就會增加mysql入口,增加高可用。不過多主需要考慮自增長ID問題,這個需要特別設定配置檔案,比如雙主,可以使用奇偶,總之,主之間設定自增長ID相互不衝突就能完美解決自增長ID衝突問題。

1.MySQL雙主(主主)架構方案思路

兩臺mysql都可讀寫,互為主備,預設只使用一臺(masterA)負責資料的寫入,另一臺(masterB)備用。

  1. masterA是masterB的主庫,masterB又是masterA的主庫,它們互為主從。
  2. 兩臺主庫之間做高可用,可以採用keepalived等方案(使用VIP對外提供服務)。
  3. 所有提供服務的從伺服器與masterB進行主從同步(雙主多從)。
  4. 建議採用高可用策略的時候,masterA或masterB均不因宕機恢復後而搶佔VIP(非搶佔模式)。

這樣做可以在一定程度上保證主庫的高可用,在一臺主庫down掉之後,可以在極短的時間內切換到另一臺主庫上(儘可能減少主庫宕機對業務造成的影響),減少了主從同步給線上主庫帶來的壓力;但是也有幾個不足的地方:

  1. masterB可能會一直處於空閒狀態。
  2. 主庫後面提供服務的從庫要等masterB先同步完了資料後才能去masterB上去同步資料,這樣可能會造成一定程度的同步延時。

2.修改主節點的配置檔案

[root@db01 ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3306
socket=/tmp/mysql.sock
character-set-server=utf8mb4
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld.pid

# 節點ID,確保唯一
server-id = 1        
 
#開啟mysql的binlog日誌功能
log-bin=binlog
#控制資料庫的binlog刷到磁碟上去 , 0 不控制,效能最好,1每次事物提交都會刷到日誌檔案中,效能最差,最安全
sync_binlog=1
#binlog日誌格式
binlog_format=row
#binlog過期清理時間
expire_logs_days=7
#binlog每個日誌檔案大小
max_binlog_size=100m
#binlog快取大小
binlog_cache_size=4m   
#最大binlog快取大小
max_binlog_cache_size=512m         
 
#不生成日誌檔案的資料庫,多個忽略資料庫可以用逗號拼接,或者 複製黏貼下述配置項,寫多行
binlog-ignore-db=mysql 
# 表中自增欄位每次的偏移量
auto-increment-offset=1
# 表中自增欄位每次的自增量
auto-increment-increment=2
#跳過從庫錯誤
slave-skip-errors=all

#將複製事件寫入binlog,一臺伺服器既做主庫又做從庫此選項必須要開啟
log-slave-updates=true
gtid-mode=on

enforce-gtid-consistency=true
master-info-repository=file
relay-log-info-repository=file
sync-master-info=1
slave-parallel-workers=0
sync_binlog=0
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
max_binlog_size=1024M

# 忽略同步的資料庫
replicate-ignore-db=mysql
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema
replicate-ignore-db=sys

max_connections=3000
max_connect_errors=30

#忽略應用程式想要設定的其他字符集
skip-character-set-client-handshake
#連線時執行的SQL                                
init-connect='SET NAMES utf8mb4'
#服務端預設字符集
character-set-server=utf8mb4
#請求的最大連線時間
wait_timeout=1800
#和上一引數同時修改才會生效
interactive_timeout=1800
#sql模式
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

max_allowed_packet=10M
bulk_insert_buffer_size=8M
query_cache_type=1
query_cache_size=128M
query_cache_limit=4M
key_buffer_size=256M
read_buffer_size=16K
# 禁用反向解析
skip-name-resolve
slow_query_log=1
long_query_time=6
slow_query_log_file=slow-query.log
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=16M

[mysql]
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

3.修改備節點的配置檔案

[root@db02 ~]# vim /etc/my.cnf 
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3306
socket=/tmp/mysql.sock
character-set-server=utf8
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld.pid

# 節點ID,確保唯一
server-id=2      
 
#開啟mysql的binlog日誌功能
log-bin=binlog
#控制資料庫的binlog刷到磁碟上去 , 0 不控制,效能最好,1每次事物提交都會刷到日誌檔案中,效能最差,最安全
sync_binlog=1
#binlog日誌格式
binlog_format=row
#binlog過期清理時間
expire_logs_days=7
#binlog每個日誌檔案大小
max_binlog_size=100m
#binlog快取大小
binlog_cache_size=4m   
#最大binlog快取大小
max_binlog_cache_size=512m  
 
#不生成日誌檔案的資料庫,多個忽略資料庫可以用逗號拼接,或者 複製黏貼下述配置項,寫多行
binlog-ignore-db=mysql 
 
# 表中自增欄位每次的偏移量
auto-increment-offset=2
# 表中自增欄位每次的自增量
auto-increment-increment=2  
#跳過從庫錯誤
slave-skip-errors=all

#將複製事件寫入binlog,一臺伺服器既做主庫又做從庫此選項必須要開啟
log-slave-updates=true
gtid-mode=on

enforce-gtid-consistency=true
master-info-repository=file
relay-log-info-repository=file
sync-master-info=1
slave-parallel-workers=0
sync_binlog=0
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
max_binlog_size=1024M

# 忽略同步的資料庫
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema
replicate-ignore-db=sys

max_connections=3000
max_connect_errors=30

#忽略應用程式想要設定的其他字符集
skip-character-set-client-handshake
#連線時執行的SQL
init-connect='SET NAMES utf8'
#服務端預設字符集
character-set-server=utf8
#請求的最大連線時間
wait_timeout=1800
#和上一引數同時修改才會生效
interactive_timeout=1800
#sql模式
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

max_allowed_packet=10M
bulk_insert_buffer_size=8M
query_cache_type=1
query_cache_size=128M
query_cache_limit=4M
key_buffer_size=256M
read_buffer_size=16K

# 禁用反向解析
skip-name-resolve

slow_query_log=1
long_query_time=6
slow_query_log_file=slow-query.log
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=16M

[mysql]
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

4.兩個master階段都必須重新初始化

#停止MySQL並刪除data目錄下的所有檔案
[root@db01 ~]# systemctl stop mysqld
[root@db01 ~]# rm -rf /usr/local/mysql/data/*
[root@db02 ~]# systemctl stop mysqld
[root@db02 ~]# rm -rf /usr/local/mysql/data/*


[root@db01 ~]# mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

[root@db02 ~]# mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

#   --initialize-insecure  不安全初始化,即沒有密碼。
#   --initialize           安全初始化,會自動生成臨時密碼。在log-error裡,查詢 temporary password

5.分別登入資料庫並建立複製賬號

# 使用臨時密碼登入
[root@db01 ~]# systemctl start mysqld
[root@db01 ~]# grep 'temporary password' /var/log/mysqld.log 
2021-10-19T08:01:08.782788Z 1 [Note] A temporary password is generated for root@localhost: O=i#f4Bfjy&t
[root@db01 ~]# mysql -uroot -p'O=i#f4Bfjy&t'

[root@db02 ~]# systemctl start mysqld
[root@db02 ~]# grep 'temporary password' /var/log/mysqld.log 
2021-10-19T08:01:27.407550Z 1 [Note] A temporary password is generated for root@localhost: 4i?k*cU,I2d=
[root@db02 ~]# mysql -uroot -p'4i?k*cU,I2d='


# 修改臨時密碼
mysql> alter user root@localhost identified by '123';
Query OK, 0 rows affected (0.00 sec)

# 重新登入資料庫
[root@db01 ~]# mysql -uroot -p123
[root@db02 ~]# mysql -uroot -p123

# 建立遠端連線賬號
mysql> grant all on *.* to root@'%' identified by '12345' with grant option;
Query OK, 0 rows affected, 1 warning (0.00 sec)

# 刪除其他密碼
mysql> delete from mysql.user where host='localhost';
Query OK, 2 rows affected (0.00 sec)

# 重新整理許可權
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

# 重新登入並建立遠端複製賬號
mysql> grant replication slave on *.* to cp@'%' identified by '12345';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

6.配置主從複製

# db01主機binlog資訊
mysql> show master status;
+---------------+----------+--------------+------------------+--------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+--------------------------------+
| binlog.000003 |     1184 |              | mysql            | b7cf4a55-30b2-11ec-bda8-000c29577624:1-12 |
+---------------+----------+--------------+------------------+--------------------------------+
1 row in set (0.01 sec)


# db02主機binlog資訊
mysql> show master status;
+---------------+----------+--------------+------------------+----------------------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+---------------+----------+--------------+------------------+----------------------------------+
| binlog.000002 |     1791 |              | mysql            | c2e9e04e-30b2-11ec-aa81-000c29e11414:1-10 |
+---------------+----------+--------------+------------------+----------------------------------+
1 row in set (0.00 sec)



# 在db01上執行
mysql> change master to 
    -> master_host='172.16.1.52',
    -> master_port=3306,
    -> master_user='cp',
    -> master_password='12345',
    -> master_log_file='binlog.000002',
    -> master_log_pos=1791;
Query OK, 0 rows affected, 2 warnings (0.10 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.1.52
                  Master_User: cp
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000002
          Read_Master_Log_Pos: 1791
               Relay_Log_File: db01-relay-bin.000002
                Relay_Log_Pos: 317
        Relay_Master_Log_File: binlog.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

# 在db02上執行
mysql> change master to
    -> master_host='172.16.1.51',
    -> master_port=3306,
    -> master_user='cp',
    -> master_password='12345',
    -> master_log_file='binlog.000003',
    -> master_log_pos=1184;
Query OK, 0 rows affected, 2 warnings (0.11 sec)
 
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.1.51
                  Master_User: cp
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000003
          Read_Master_Log_Pos: 1184
               Relay_Log_File: db02-relay-bin.000002
                Relay_Log_Pos: 317
        Relay_Master_Log_File: binlog.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
    

7.測試

# db01建立資料庫和表
mysql> create database linux13;
Query OK, 1 row affected (0.00 sec)

mysql> use linux13;
Database changed

mysql> create table student(id int);
Query OK, 0 rows affected (0.01 sec)

# db02插入資料
mysql> use linux13;
Database changed

mysql> insert into student values (1),(2);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

# db01查詢資料
mysql> select * from student;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

#雙方寫入的資料均能在對方查詢到,雙主架構資料庫成功

八、雙主高可用

高可用是使用keepalived實現VIP。從而實現一個IP無感知操作兩個主節點

# 兩個節點都安裝keepalived
[root@db01 ~]# yum install -y keepalived
[root@db02 ~]# yum install -y keepalived


# 修改keepalived的配置檔案
[root@db01 ~]# vim /etc/keepalived/keepalived.conf 
global_defs {
    router_id LVS_DEVEL
}
vrrp_script chk_kubernetes {
    script "/etc/keepalived/check_kubernetes.sh"
    interval 2
    weight -5
    fall 3
    rise 2
}
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    mcast_src_ip 10.0.0.51      # 所在節點的IP
    virtual_router_id 51
    priority 100
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass K8SHA_KA_AUTH
    }
    virtual_ipaddress {
        10.0.0.3
    }

    #呼叫計劃指令碼
    track_script {
        check_kubernetes
	}
}

[root@db02 ~]# vim /etc/keepalived/keepalived.conf 
global_defs {
    router_id LVS_DEVEL
}
vrrp_script chk_kubernetes {
    script "/etc/keepalived/check_kubernetes.sh"
    interval 2
    weight -5
    fall 3
    rise 2
}
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    mcast_src_ip 10.0.0.52     # 所在節點的IP
    virtual_router_id 51
    priority 90
    advert_int 2
    authentication {
        auth_type PASS
        auth_pass K8SHA_KA_AUTH
    }
    virtual_ipaddress {
        10.0.0.3
    }

    #呼叫計劃指令碼
    track_script {
        check_kubernetes
    }    
}

[root@db01 ~]# vim /etc/keepalived/check_kubernetes.sh
#!/bin/bash
/usr/local/mysql/bin/mysql -uroot -p12345 -e 'status;' &> /dev/null

if [ $? -ne 0 ];then
        systemctl start mysqld

        sleep 2

        /usr/local/mysql/bin/mysql -uroot -p12345 -e 'status;' &> /dev/null

        if [ $? -ne 0 ];then
                systemctl stop keepalived
        fi
fi

[root@db01 ~]# chmod +x /etc/keepalived/check_kubernetes.sh

[root@db01 ~]# scp /etc/keepalived/check_kubernetes.sh 172.16.1.52:/etc/keepalived/