第五章:MySQL主從複製


目錄

1. 主從MySQL主從複製介紹... 1

2. MySQL主從複製的企業應用場景... 3

3. 實現MySQL主從讀寫分離的方案... 5

4. MySQL主從複製原理... 7

5. 主從複製實戰... 8

5.1 MySQL主從配置... 8

5.2 MySQL數據庫級聯配置... 12

5.3 MySQL主從複製配置步驟小結... 15

5.4 主從配置表示成功後的關鍵參數說明... 15

5.5 MySQL主從複製配置問題彙總... 16

6. MySQL主從複製更多應用技巧... 17

 

1. 主從MySQL主從複製介紹

    MySQL的主從複製方案,其實就和文件及文件系統級別同步是類似的,都是數據的傳輸,只不過MySQL無需藉助第三方工具,而是自帶的同步複製功能,另外一點,MySQL的主從複製並不是磁盤上文件直接同步,而是邏輯的binlog日誌同步到本地在應用執行的過程。

MySQL數據庫支持單向、雙向、鏈式級聯等不同場景的複製,在複製過程中,一臺服務器充當主服務器(Master),而一個或多個其它的服務器充當從服務器(Slave)。

複製可以單向:M==>S;可以雙向:M<==>S;當然也可以多M環裝同步等。

如果設置了鏈式級聯複製,那麼,從(slave)服務器本身除了充當從服務器外,也會同時充當其下面從服務器的主服務器,鏈式級聯複製類似A==>B==>C==>D的複製形式。

下面是MySQL各種同步結構的邏輯圖:

1. 單向主從複製邏輯圖,此架構只能在Master端進行數據寫入


wKioL1gCa5WzKAaOAABOO29WO-o427.png

wKiom1gCa5fQAcz-AACa_-VsGQo214.png

 

2. 雙向主主同步邏輯圖,此架構可以在Master1端或Master2端進行數據寫入

 

wKioL1gCa82CZxVgAABTRhGxxVo225.png

3. 線性級聯單向雙主同步邏輯圖,此架構只能在Master端進行數據寫入

wKiom1gCa-zzhWFNAACEc5DYFQs041.png

4. 環裝級聯單向多主同步邏輯圖,任意一個點都可以寫入數據

wKiom1gCbAvSUfo3AACZhE1C30c830.png

5. 環裝級聯單向多主多從同步邏輯圖,次架構只能在任意一個master端進行數據寫入

wKioL1gCbHDRv2kJAADNf5uUDjE241.png

6. MySQL官方同步架構圖

wKioL1gCbIngVdnWAAHSqyc8JMU040.png

    在當前的生產環境中,MySQL主從複製都是異步的複製方式,既不是嚴格實時的數據同步。


2. MySQL主從複製的企業應用場景

MySQL主從複製集羣功能使得MySQL數據庫支持大規模高併發讀寫稱爲可能,同時有效的保護了物理服務器宕機場景的數據備份。


應用場景1:從服務器作爲主服務器的實時數據備份

主從服務器架構的設置可以大大加強MySQL數據庫架構的健壯性,例如:當主服務器出現問題時,我們可以人工或設置自動切換到從服務器繼續提供服務,此時從服務器的數據與宕機時的數據庫幾乎是一致的。

這類似NFS存儲數據通過inotify+rsync同步到備份的NFS服務器,只不過MySQL的複製方案是其自帶的工具。

利用MySQL的複製功能進行數據備份時,在硬件故障、軟件故障的場景下,該數據備份是有效的,但對於人爲執行drop、delete等語句刪除數據的情況,從庫的備份功能就沒用了,因爲從服務器也會執行刪除的語句。


應用場景2:主從服務器實現讀寫分離,從服務器實現負載均衡

主從服務器架構可通過(PHP、java等)或代理軟件(mysql-proxy、Amoeba)實現對用戶(客戶端)的請求讀寫分離,揖讓從服務器金聰處理用戶的select查詢請求,降低用戶查詢響應時間,以及同時讀寫在主服務器上帶來的訪問壓力,對於更新的數據(例如:update、insert、delete語句),則仍然交給主服務器處理,確保主服務器和從服務器保持實時同步。

wKiom1gCbK6AtStLAAHAZu1sXjk056.png


應用場景3:把多個從服務器根據業務重要性進行拆分訪問

可以把幾個不同的從服務器,根號月公司的業務進行拆分,例如:在爲外部用戶提供查詢服務的從服務器,在內部DBA用來數據備份的從服務器,還有爲公司內部人員提供訪問的後臺、腳本、日誌分析及供開發人員查詢使用的從服務器,這樣拆分除了減輕主服務器的壓力外,還可以是數據庫對外不用戶瀏覽,內部用戶業務處理及DBA人員的備份等互不影響。


3. 實現MySQL主從讀寫分離的方案

(1)通過程序實現讀寫分離(性能和效率最佳,推薦)

PHP和java程序都可以通過設置多個連接文件輕鬆地實現對數據庫的讀寫分離,即當語句關鍵字爲select時,就去連接讀庫的連接文件,若爲update、insert、delete時,則連接寫庫的文件。

通過程序實現讀寫分離的缺點就是需要開發人員對程序進行改造,使其對下層不透明,但這種方式更容易開發和實現,適合互聯網業務場景。

wKioL1gCbPvQZCBwAAGLBauFgdY619.png


2)通過開源的軟件實現讀寫分離

MySQL-Proxy、Amoeba等代理軟件也可以是實現讀寫分離功能,這些軟件的穩定性和功能一般,不建議生產使用,絕大多數公司常用的還是在應用端發程序實現讀寫分離。


(3)大型門戶獨立開發DAL層綜合軟件

       百度、阿里等大型門戶都有開發牛人,會花大力氣開發適合自己業務的讀寫分離,負載均衡,監控報警,自動擴容,自動收縮等一系列功能的DAL層軟件。

wKiom1gCbSjS4en6AADxcXffk8w086.png

4. MySQL主從複製原理

wKiom1gCbUKi28xIAAGWlDPyydQ979.png

簡單描述MySQL Replication的複製原理過程

1. 在Slave服務器上執行start slave命令開啓主從複製開關,開始進行主從複製。

2. 此時,slave服務器的I/O線程會通過在Master上已經授權的複製用戶權限請求選擇Master服務器,並   請求從指定binlog日誌文件的指定位置(日誌文件名和位置就是在哦誒之主從瀆職服務時執行change   master命令指定的)之後,之後開始發送binlog日誌內容。

3. Master服務器接收來自slave服務器的IO線程的請求後,其上負責複製的I/O線程會根據slave服務器   的io線程請求的信息分批讀取指定binlog日誌文件指定位置之後的binlog日誌信息,然後返回給     slave端的I/O線程,返回的信息中除了binlog日誌內容外,還有在master服務器端記錄的新的binlog   文件名稱,以及在新的binlog中的下一個指定的跟新位置。

4. 當slave服務器的io線程獲取帶master服務器上io線程發送的日誌內容,日誌文件及位置點後,會將   binlog日誌內容寫到slave端自身的relay loy(即中繼日誌)的最末端,並將新的binlog日誌文件名   和位置點記錄到master-info文件中,以便下一次讀取master端新的binlog日誌是能夠告訴master服   務端從新的binlog日誌指定文件及位置開始請求新的binlog日誌內容。

5.slave服務器端的SQL線程會實時監測本地relay log中的io線程新增加的日誌內容。然後及時的把  relay.log文件中的內容解析成SQL語句,並且自身slave服務器上按解析sql語句的位置順序執行應用  這些SQL語句,並在relay-log.info中記錄當前應用中繼日誌文件名及位置點。


MySQL主從複製原理的重點小結:

  • 主從複製是異步的邏輯的SQL語句級的複製

  • 複製時,主庫有一個線程,從庫有兩個線程,即I/O和SQL線程

  • 實現主從複製的前提條件時主庫開啓記錄binlog功能

  • 作爲複製的所有MySQL節點的sever id都不能相同

binlog文件只記錄對數據有更改的SQL語句(來自主數據庫內容的變更),不記錄任何查詢(如:select、show)語句。

5. 主從複製實戰

實現主從複製條件

  • 開啓binlog功能。

  • 主庫建立同步賬號。

  • 從庫配置master.info(change master..)。

startslave複製開關。

5.1 主從配置

如圖:

wKioL1gCbauyfzwuAAAji-RNtuU819.png

wKiom1gCbargeMENAAArWx4jObE157.png

 

配置主從複製

測試環境:使用一臺服務器,多實例,一個實例做主,另外的實例做從(多臺服務器也一樣)


1)主庫操作


1. 先確認主庫binlog功能是否開啓和各個實例server-id實例的不同

[root@db01 3308]# egrep "log-bin|server-id" /data/{3306,3307}/my.cnf
/data/3306/my.cnf:log-bin= /data/3306/mysql-bin
/data/3306/my.cnf:server-id= 1
/data/3307/my.cnf:#log-bin= /data/3307/mysql-bin
/data/3307/my.cnf:server-id= 3


2. 主庫授權同步的用戶

[root@db01 /]# mysql -uroot -poldboy123 -S /data/3306/mysql.sock  #<== 登錄數據庫
mysql> grant replication slave on *.* torep@'172.16.1.%' identified by 'oldboy123';
Query OK, 0 rowsaffected (0.00 sec)                 #<== 創建rep用戶並授權
mysql> flush privileges;                            #<== 刷新數據庫
Query OK, 0 rowsaffected (0.00 sec)
 
mysql> select user,host from mysql.user;            #<== 創建用戶後查看確認
mysql> show grants for rep@'172.16.1.%';            #<== 查看rep用戶權限


3. 備份前對主數據庫鎖表(只讀)

mysql> flush table with read lock;
Query OK, 0 rowsaffected (0.00 sec)


測試:單開一個窗口,創建一個數據庫(這時會發現創建不了,因爲表鎖了)

mysql> create database oldgirl;


4. 查看全備與增量之間的臨界點

mysql> show master status;
+-----------------+------------+---------------+------------------+
| File            | Position   | Binlog_Do_DB  | Binlog_Ignore_DB |
+-----------------+------------+---------------+------------------+
| mysql-bin.000016|     4065   |               |                  |
+-----------------+------------+---------------+------------------+
1 row in set (0.00sec)


5. 開始備份

創建備份目錄

[root@db01 ~]# mkdir -p /server/backup/

全備

[root@db01~]# mysqldump -uroot -poldboy123 -S/data/3306/mysql.sock -B -A --events|gzip >/server/backup/rep_bak_$(date+%F).sql.gz
[root@db01 ~]# ll -htr /server/backup/|tail -1
-rw-r--r-- 1 root root 149K Aug 31 23:57rep_bak_2016-08-31.sql.gz

6. 因爲數據已經備份完,所以可以開放用戶寫入功能,此時會發現測試窗口的數據會寫入

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


(2)從庫操作

1. 確保所有用戶server-id不同(主庫已經確認過)

[root@db01 3308]# egrep "log-bin|server-id" /data/{3306,3307}/my.cnf
/data/3306/my.cnf:log-bin= /data/3306/mysql-bin
/data/3306/my.cnf:server-id= 1
/data/3307/my.cnf:#log-bin= /data/3307/mysql-bin
/data/3307/my.cnf:server-id= 3


2. 把主庫的全備導入到從庫

[root@db01 ~]# gzip -d/server/backup/rep_bak_2016-08-31.sql.gz
[root@db01 ~]# ll /server/backup/rep_bak_2016-08-31.sql
-rw-r--r-- 1 root root 552788 Aug 31 23:57//server/backup/rep_bak_2016-08-31.sql
[root@db01 ~]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock </server/backup/rep_bak_2016-08-31.sql


3. 找位置點,開始配置masterinfo


[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock
CHANGE MASTER TO                                           
MASTER_HOST='172.16.1.51',           #<== 主庫IP
MASTER_PORT=3306,                    #<== 主庫端口(如果配置一主多從可不寫,默認)
MASTER_USER='rep',                   #<== 這裏是主庫上建立的用於複製的用戶rep
MASTER_PASSWORD='oldboy123',         #<== rep用戶密碼
MASTER_LOG_FILE='mysql-bin.000016',  #<== 這裏是showmaster status; 時看到的臨界點binlog文件,注意,這裏不能多空格
MASTER_LOG_POS=107;                  #<== 這是showmaster status; 查看二進制文件偏移量,注意,不能多空格

[root@db01 ~]# ll /data/3307/     
-rw-rw---- 1 mysql mysql   51 Sep 1 03:40 relay-log.info

參數如下:

CHANGE MASTER TO
MASTER_HOST='172.16.1.51',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='oldboy123',
MASTER_LOG_FILE='mysql-bin.000016',
MASTER_LOG_POS=107;


4. 開啓同步開關

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


5. 查看同步狀態,看到以下黃色部分是以下狀態就算成功

mysql> show slave status\G
*************************** 1. row***************************
-----------------------省略部分內容------------         
       Relay_Master_Log_File: mysql-bin.000017
             Slave_IO_Running: Yes                #<== 看這IO線程yes和SQLyes就成功了
            Slave_SQL_Running: Yes
             Replicate_Do_DB:
-------------------------------------省略-----------
        Seconds_Behind_Master: 0                  #<== 主到從複製的延遲
1 row in set (0.00 sec)

或者使用命令查看:

mysql -S /data/3307/mysql.sock -e"show slave status\G"|egrep -i "_running|Behind "
 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes
Seconds_Behind_Master: 0


(3)簡單測試是否成功

1. 在主庫創建數據庫,查看從庫是否同步

[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3306/mysql.sock
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| mysql                 |
| performance_schema    |
+-----------------------+
8 rows in set (0.00 sec)

mysql> create database testdatabase;
Query OK, 1 row affected (0.00 sec)
 
mysql> show databases;             
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| mysql                 |
| performance_schema    |
| testdatabase          |
+-----------------------+
9 rows in set (0.00 sec)

登錄從庫查看

[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock
mysql> show databases;
+-------------------------------+
| Database              |
+-------------------------------+
| information_schema   |
| mysql                |
| performance_schema  |
| testdatabase         |
+-------------------------------+
9 rows in set (0.00 sec)


------------------成功!!!-------------------


5.2 MySQL數據庫級聯配置

wKiom1gC7_7RMPWPAABVByvUL4k640.png

說明:在配置了MySQL一主一從或MySQL一主多從的情況下,在該基礎上的從庫下面在配置一臺從庫,構成線性級聯單向雙主同步。


環境:在以上5.1的配置上繼續配置級聯


以下在以上配置的3307從庫上操作


1. 開啓從庫3309記錄binlog日誌功能,配置如下:

[root@db01 3307]# vim /data/3307/my.cnf
[mysqld]
log-slave-updates                      #<==在從庫上配置binloa文件時,此行也是必須加的
log-bin = /data/3309/mysql-bin

重啓生效

[root@db01 3307]# /data/3307/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL..


2. 全備3307從庫實例,導入到3309

[root@db01 3307]# mysqldump -uroot -poldboy123 -S/data/3307/mysql.sock -B -A --master-data=1 --events>/server/backup/3307.sql
[root@db01 3307]# mysql -uroot-poldboy123 -S /data/3309/mysql.sock </server/backup/3307.sql


以下步驟在3309上面操作


3. 在3309上面配置master info文件

[root@db01 3309]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock 
mysql> CHANGE MASTER TO
    ->MASTER_HOST='172.16.1.51',                     
    ->MASTER_PORT=3307,                                     
    ->MASTER_USER='rep',                             
    ->MASTER_PASSWORD='oldboy123';              
Query OK, 0 rows affected (0.01 sec)
說明:這裏沒有進行查看並指定binlog文件的位置點是因爲備份時已經使用參數-x(鎖表),和--master-data=1
(標記binlog文件數據位置)兩個參數,--master-data=1會自動會自動生成位置點。

參數如下:

CHANGEMASTER TO
MASTER_HOST='172.16.1.51',
MASTER_PORT=3307,
MASTER_USER='rep',
MASTER_PASSWORD='oldboy123';


4. 在3309上面開啓slave開關

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

5. 查看狀態

mysql> show slave status\G 
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
       Seconds_Behind_Master: 0
說明:以上輸出部分內容省略,只要以上三行是該狀態就表示正確(此三行是配置成功標誌最關鍵的參數)

# 還可以在命令行外執行命令查看,如下:

[root@db01 3309]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock  -e "showslave status\G"|egrep -i "_running|Seconds"
            Slave_IO_Running: Yes
           Slave_SQL_Running: Yes
       Seconds_Behind_Master: 0


測試:

在主庫3306裏面寫入數據,這時在3307庫裏面和3309庫裏面就會同時有啦,如下:

# 3306查看並創建數據庫

[root@db01 3308]# mysql -uroot -poldboy123 -S/data/3306/mysql.sock
mysql> show databases;    
+---------------------+
| Database            |
+---------------------+
| information_schema  |
| mysql               |
| oldboy              |
| performance_schema  |
+---------------------+
4 rows in set (0.00 sec)
mysql> create database zyl;                         #<== 創建名爲zyl的庫
mysql> show databases;                              #<==在3306上面查看
+-------------------------------+
| Database            |
+-------------------------------+
| information_schema   |      
| mysql                    |
| oldboy              |
| performance_schema  |
| zyl                |
+-------------------------------+
5 rows in set (0.00 sec)[
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3307/mysql.sock
mysql> show databases;                               #<==在3307上面查看
+-------------------------------+
| Database            |
+-------------------------------+
| information_schema   |      
| mysql                     |
| oldboy              |
| performance_schema  |
| zyl                |
+-------------------------------+
5 rows in set (0.00 sec)
[root@db01 3307]# mysql -uroot -poldboy123 -S/data/3309/mysql.sock
mysql> show databases;                              #<==在3309上面查看
+---------------------+
| Database            |
+---------------------+
| information_schema  |      
| mysql               |
| oldboy              |
| performance_schema  |
| zyl                 |
+---------------------+
5 rows in set (0.00 sec)


報錯原因:  1. 防火牆原因;

        2. 複製賬號和密碼不對。


5.3 MySQL主從複製配置步驟小結

 1. 一主一從環境爲一臺服務器(多實例),3306爲主,3307爲從,3309爲級聯。

2. 配置my.cnf文件,主庫配置bin-logserver-id出本書,從庫配置sever-id,該值個庫不能一樣,一般不開啓從庫的binlog功能,但是在5.2因爲在3307從庫下還有配置級聯從庫,所以需要開啓。配置這些參數要重啓才能生效。

3. 登錄主庫,增加從庫連接主庫同步的賬戶,例如:rep、並授權replication slave複製同步的權限。

4. 登錄主庫,整庫鎖表flus tablewith read lock(窗口關閉後即失效,超時參數設定的時間到了,鎖表也會失效),然後show master status查看binlog的位置狀態。

5 . 離開窗口,在linux命令行備份導出原有的數據庫數據,並拷貝到從庫所在的服務器目錄,如果數據量龐大,並且允許停機,可以停機打包,而不用mysqldump

6. 導出主庫數據後,執行unlocktables解鎖主庫。

7. 把主庫導出的數據恢復到從庫。

8. 根據主庫的show masterstatus查看到的binlog的位置狀態,在從庫執行change master to...語句。

9. 從庫開啓複製開關,即執行Lstartslave;。

5.4 主從配置表示成功後的關鍵參數說明

主從複製是否配置成功,最關鍵的是下面的3項狀態參數

 

Slave_IO_Running:Yes

這個是I/O線程狀態,I/O線程複製從主庫到從庫讀取binlog日誌,並寫入從庫的中繼日誌,狀態爲yes表示I/O線程工作正常。


Slave_SQL_Running:Yes

這個是SQL線程狀態,SQL線程負責讀取中繼日誌(relay-log)中的數據並裝換爲SQL語句應用到數據庫中,狀態爲YES表示I/O線程工作正常。


Seconds_Behind_Master:0

這個是複製過程中從庫比主庫延遲的描述,這個參數很重要,但企業更準確地判斷主從延遲的方法爲:在主庫寫時間戳,然後從庫讀取時間戳,和當前數據庫時間進行比較,從而認定是否延遲。

5.5 MySQL主從複製配置問題彙總

1. 主庫show master status沒返回狀態結果,如下

mysql> show master status;
0 row in set (0.00 sec)


原因:binlog功能開關沒開或沒生效導致。正確開啓方式如下:

[root@db01 3307]# grep "log-bin"/data/3306/my.cnf
log-bin = /data/3306/mysql-bin               #<== 在配置文件中將此行註釋打開
[root@db01 3307]# mysql -uroot -poldboy123 -S /data/3306/mysql.sock-e "show variables like 'log_bin';"             #<== 修改後查看結果
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+


2. 出現錯誤信息:“Last_IO_Error:GOTdatal errow 1236 drom master when when reading data from binary log; ‘ Couldnot find first log file name in binary log index file’ ”

原因:以上故障原因是執行CHANGE MASTER 命令時,某一個參數的值多個空格導致,如下:

CHANGE MASTER TO
MASTER_HOST='172.16.1.51',
MASTER_PORT=3307,
MASTER_USER='rep',
MASTER_PASSWORD='oldboy123';
說明;以上參數均不能有空格

3. MySQL服務無法啓動

[root@db01 /]# /data/3306/mysql start
MySQL is running...                                  #<==正在運行

[root@db01 /]# ps -ef|grep mysql                     #<== 並無mysql進程
root     30345  26941  0 22:16 pts/4    00:00:00 grep mysql

原因:其原因是啓動腳本里對mysql.sock是否存在做了判斷,如果存在mysql.sock,就認爲服務運行,這是個bug,解決如下:

[root@db01 /]# rm -f /data/3306/mysql.sock
# 說明:刪除後重新啓動查看即可


4. 當從起或關閉MySQL服務從起或關閉不了,報錯如下:

[root@db01 3307]# /data/3307/mysql restart
Restarting MySQL...
Stoping MySQL...
/application/mysql/bin/mysqladmin: connect toserver at 'localhost' failed
error: 'Access denied for user 'root'@'localhost'(using password: YES)'
MySQL is running...

原因:是啓動文件/data/3306/mysql裏面沒有修改數據庫密碼,當我們設置完密碼後,在mysql啓動文件mysql中也是有密碼的,如果不改,就無法停止服務。

[root@db01 /]# vim /data/3306/mysql
mysql_pwd="oldboy123"


6. MySQL主從複製更多應用技巧


1.工作中MySQL從庫停止複製故障案例

模擬重現故障的能力是運維人員最重要的能力。下面就來次模擬操作。先在從庫創建一個庫,然後去主庫創建同名的庫來模擬數據衝突,命令如下:

show slave status;報錯:且 show slavestatus\G:
Slave_IO_Running:Yes
Slave_SQL_Running:NO
Seconds_Behind_Master:NULL
Last_Error:Error 'Can't create database 'xiaoliu';database exists' onquery. Default database:'xiaoliu'. Query:'create database xiaoliu'

對於該衝突,解決方法1如下:

top slave;                               #<== 臨時停止同步開關
set global sql_slave_skip_counter =1;    #<== 將同步指針向下移動一個,如果多次不同步,可以重複操作
start slave;                             #<== 沖洗你開啓
show slave status\G:                     #<== 再次進行查看確認

如果修改後還會報錯,那可以適當的將set global sql_slave_skip_counter值增大即可。

 

提示:setglobal sql_slave_skip_counter=n;#n取值>0,忽略執行N個更新。

 

解決方法2:根據可以忽略的錯誤號事先在配置文件中配置,跳過指定的不影響業務數據的錯誤,例如:

root@MySQL ~]# grep slave-skip /data/3306/my.cnf
slave-skip-errors = 1032,1062,1007


提示:類似由於入庫重複導致的失敗可以忽略,其他情況是不是可以忽略需要根據不同公司的具體業務來評估。可以查看博客的代碼含義


其他可能引起復制故障的原因:


  • MySQL自身的原因及人爲重複插入數據。

  • 不同的數據庫版本會引起不同步,低版本到高版本可以,但是高版本不能往低版本同步。

  • ·MySQL的運行錯誤或程序bug。

  • ·binlog記錄模式,例如:row level模式就比默認的語句模式要好。


2. 讓MySQL從庫記錄binlog日誌的方法

從庫需要記錄binlog的應用場景:當前的從庫還要作爲其他從庫的主庫,例如級聯複製或雙主互爲主從場景的情況下。下面介紹從庫記錄binlog日誌的方法。

在從庫的my.cnf中加入如下參數,然後重啓服務生效即可。

log-slave-updates                       #<== 必須要有這個參數
log-bin = /data/3307/mysql-bin          #<==開啓從庫binlog功能
expire_logs_days = 7  #<==相當於find/data/3307/ -type f -name " mysql-bin.000*" -mtime +7 |xargs rm -f


3. MySQL主從複製集羣架構的數據備份策略

有主從複製了,還需要做定時全量加增量備份麼?答案是肯定的!

因爲,如果主庫有語句級誤操作(例如:drop database oldboy;),從庫也會執行drop databaseoldboy;,這樣MySQL主從庫就都刪除了該數據。

把從庫作爲數據庫備份服務器時,備份策略如下:

高併發業務場景備份時,可以選擇在一臺從庫上備份(Slave5),把從庫作爲數據庫備份服務器時需要在從庫開啓binlog功能,其邏輯如圖所示。

wKiom1gC9I7TD_HoAAGLBauFgdY158.png


步驟如下:

1.選擇一個不對外提供服務的從庫,這樣可以確保和主庫更新最接近,專門用於做數據備份。

2.開啓從庫的binlog功能。

  備份時可以選擇只停止SQL線程,停止應用SQL語句到數據庫,I/O線程保留工作狀態,執行命令爲stop slave sql_thread;,備份方式可以採取mysqldump邏輯備份或直接物理備份,例如:使用cp、tar(針對/data/目錄)工具或xtrabackup(第三方的物理備份軟件)進行備份,則邏輯備份和物理備份的選擇,一般是根據總的備份數據量的多少進行選擇的,數據量低於30G,建議選擇mysqldump邏輯備份方法,安全穩定,最後把全備和binlog數據發送到備份服務器上留存。


4. MySQL主從複製延遲問題的原因及解決方案


問題一:主庫的從庫太多,導致複製延遲。

從庫數量以3~5個爲宜,要複製的從節點數量過多,會導致複製延遲。


問題二:從庫硬件比主庫差,導致複製延遲。

查看Master和Slave的系統配置,可能會因爲機器配置不當,包括磁盤I/O、CPU、內存等各方面因素造成複製的延遲。這一般發生在高併發大數據量寫入場景U、內存等各方面因素造成複製的延遲。這一般發生在高併發大數據量寫入場景中。


問題三:慢SQL語句過多

假如一條SQL語句執行時間是20秒,那麼從執行完畢到從庫上能查到數據至少需要20秒,這樣就延遲20秒了。

一般要把SQL語句的優化作爲常規工作,不斷地進行監控和優化,如果單個SQL的寫入時間長,可以修改後分多次寫入。通過查看慢查詢日誌或show fullprocesslist命令,找出執行時間長的查詢語句或大的事務。


問題四:主從複製的設計問題。

例如,主從複製單線程,如果主庫寫併發太大,來不及傳送到從庫,就會導致延遲。

更高版本的MySQL可以支持多線程複製,門戶網站則會自己開發多線程同步功能。


問題五:主從庫之間的網絡延遲。

主從庫的網卡、網線、連接的交換機等網絡設備都可能成爲複製的瓶頸,導致複製延遲,另外,跨公網主從複製很容易導致主從複製延遲。

問題六:主庫讀寫壓力大,導致複製延遲。

主庫硬件要搞好一點,架構的前端要加buffer及緩存層。


5. 通過read-only參數讓從庫只讀訪問

read-only參數選項可以讓從服務器只允許來自從服務器線程或具有SUPER權限的數據庫用戶進行更新,確保從服務器不接受來自用戶端的非法用戶更新。

read-only參數允許數據庫更新的條件爲:

  • 具有SUPER權限的用戶可以更新,不受read-only參數影響,例如:管理員root。

  • 來自從服務器線程可以更新,不受read-only參數影響,例如:前文的rep用戶。

 

在生產環境中,可以在從庫Slave中使用read-only參數,確保從庫數據不被非法更新。

read-only參數的配置方法如下。

方法一:直接帶--read-only參數啓動或重啓數據庫,使用

killall mysqld

mysqladmin -uroot -poldboy123 -S/data/3307/mysql.sock shutdown
mysqld_safe --defaults-file=/data/3307/my.cnf--read-only &

方法二:在my.cnf裏[mysqld]模塊下加read-only參數重啓數據庫,配置如下:

[mysqld]
read-only


6.Web用戶專業設置方案:MySQL主從複製讀寫分離集羣


專業的運維人員提供給開發人員讀寫分離的賬戶設置方法如下:

1)訪問主庫和從庫時使用一套用戶密碼,例如,用戶爲web,密碼爲oldboy123。

2)即使訪問IP不同,端口也儘量相同(3306)。例如:寫庫VIP爲10.0.0.7,讀庫VIP爲10.0.0.8。


除了IP沒辦法修改之外,要儘量爲開發人員提供方便,如果數據庫前端有DAL層(DBProxy),還可以只給開發人員一套用戶、密碼、IP、端口,這樣就更專業了,剩下的都由運維人員搞定。


下面是授權Web連接用戶訪問的方案:MySQL主從複製讀寫分離集羣。


方法1:主庫和從庫使用不同的用戶,授予不同的權限。


主庫上對web_w用戶授權如下:

用戶:web_w   密碼:oldboy123   端口:3306   主庫VIP10.0.0.7

權限:SELECTINSERTUPDATEDELETE

命令:
GRANT SELECT,INSERT,UPDATE,DELETE ON `web`.* TO 'web_w'@'10.0.0.%' identified by 'oldboy123';

從庫上對web_r用戶授權如下:

用戶:web_r   密碼:oldboy123    端口:3306  從庫VIP10.0.0.8

權限:SELECT

命令:
GRANT SELECT ON `web`.* TO 'web_r'@'10.0.0.%' identified by'oldboy123'

 

提示:此法顯得不夠專業,但是可以滿足開發需求。

 

方法2:主庫和從庫使用相同的用戶,但授予不同的權限。


主庫上對web用戶授權如下

用戶:web   密碼:oldboy123   端口:3306    主庫VIP10.0.0.7 

權限:SELECTINSERTUPDATEDELETE

命令:
GRANT SELECT,INSERT,UPDATE,DELETE ON `web`.* TO 'web'@'10.0.0.%'identified by 'oldboy123'
;

從庫上對web用戶授權如下:

用戶:web  密碼:oldboy123    端口:3306    主庫VIP10.0.0.8

權限:SELECT

提示:由於主庫和從庫是同步複製的,所以從庫上的web用戶會自動和主庫保持一致,即無法實現只讀select的授權

要實現方法2中的授權方案,有如下兩個方法。

一是在主庫上創建用戶和權限後,從庫上revoke收回對應更新權限(insert、update、delete)。

命令爲:
REVOKE INSERT,UPDATE,DELETE ONweb.* FROM 'web'@'10.0.0.%';

二是忽略授權庫MySQL同步,主庫的配置參數如下:

binlog-ignore-db = mysql
replicate-ignore-db = mysql

提示:上面參數等號兩邊必須有空格。

 

方法3:在從庫上設置read-only參數,讓從庫只讀。

主庫從庫:主庫和從庫使用相同的用戶,授予相同的權限(非ALL權限)。

用戶:web   密碼:oldboy123   端口:3306  主庫VIP10.0.0.7,從庫VIP10.0.0.8

權限:SELECTINSERTUPDATEDELETE

命令:
GRANT SELECT,INSERT,UPDATE,DELETE ON web.* TO 'web_w'@'10.0.0.%' identified by 'oldboy123';

由於從庫設置了read-only,非super權限是無法寫入的,因此,通過read-only參數就可以很好地控制用戶,使其不能非法將數據寫入從庫


老男孩生產工作場景的設置方案如下:


1)忽略授權庫MySQL同步,主庫配置參數如下:

binlog-ignore-db = mysql
replicate-ignore-db = mysql

提示:上面參數等號兩邊必須有空格。

2)主庫和從庫使用相同的用戶,但授予不同的權限。

主庫上對web用戶授權如下:

用戶:web  密碼:oldboy123  端口:3306   主庫VIP10.0.0.7 


權限:SELECTINSERTUPDATEDELETE

命令:
GRANT SELECT,INSERT,UPDATE,DELETE ON web.* TO 'web'@'10.0.0.%' identified by 'oldboy123';

從庫上對web用戶授權如下:

用戶:web  密碼:oldboy123  端口:3306  主庫VIP10.0.0.8

權限:SELECT


3)從庫設置read-only,增加雙保險。

 

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