首頁 >資料庫 >mysql教程 >詳解高性能Mysql主從架構的複製原理及配置

詳解高性能Mysql主從架構的複製原理及配置

coldplay.xixi
coldplay.xixi轉載
2021-02-11 09:59:243628瀏覽

詳解高性能Mysql主從架構的複製原理及配置

#免費學習推薦:mysql影片教學

#1 複製概述


      Mysql內建置的複製功能是建立大型,高效能應用程式的基礎。將Mysql的資料分佈到多個系統上去,這種分佈的機制,是透過將Mysql的某一台主機的資料複製到其它主機(slaves)上,並重新執行一遍來實現的。複製過程中一個伺服器充當主伺服器,而一個或多個其它伺服器充當從伺服器。主伺服器將更新寫入二進位日誌文件,並維護文件的一個索引以追蹤日誌循環。這些日誌可以記錄傳送到從伺服器的更新。當一個從伺服器連接主伺服器時,它會通知主伺服器從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,然後封鎖並等待主伺服器通知新的更新。

請注意當你進行複製時,所有對複製中的表的更新必須在主伺服器上進行。否則,你必須要小心,以避免使用者對主伺服器上的表進行的更新與對從伺服器上的表所進行的更新之間的衝突。

1.1 mysql支援的複製類型:

  (1):基於語句的複製:  在主伺服器上執行的SQL語句,在從伺服器上執行相同的語句。 MySQL預設採用基於語句的複製,效率比較高。  
            一旦發現無法精確複製時,   會自動選擇以資料為基礎的複製。
  (2):基於行的複製:把改變的內容複製過去,而不是把命令在從伺服器上執行一遍. 從mysql5.0開始支援
  (3):混合類型的複製: 預設採用基於語句的複製,一旦發現基於語句的無法精確的複製時,就會採用基於行的複製。

 1.2 . 複製解決的問題

##         MySQL複製技術有下列一些特點:

         (1)# 負載平衡(load balancing)
         (3)    備份(Backups) 
         (4)    高可用性和容錯行High availability and failover 

  1.3 複製如何工作 

        整體上來說,複製有3個步驟:   

       (1)    master將改變記錄至二進位日誌(binary log)(這些記錄中稱為二進位日誌事件,且將改變記錄到二進位日誌#0 (2)    slave將master的binary log events拷貝到它的中繼日誌(relay log);

        (3)    slave重做中繼改變反映它自己的資料。

下圖描述了複製的過程:

                        

          流程的第一部份是master記錄二進位日誌。在每個交易更新資料完成之前,master在二日誌記錄這些變更。 MySQL將交易串列的寫入二進位日誌,即使交易中的語句都是交叉執行的。在事件寫入二進位日誌完成後,master通知儲存引擎提交交易。
       下一步就是slave將master的binary log拷貝到它自己的中繼日誌。首先,slave開始一個工作執行緒-I/O執行緒。 I/O線程在master上打開一個普通的連接,然後開始binlog dump process。 Binlog dump process從master的二進位日誌中讀取事件,如果已經跟上master,它會睡眠並等待master產生新的事件。 I/O執行緒將這些事件寫入中繼日誌。
       SQL slave thread(SQL從執行緒)處理流程的最後一步。 SQL線程從中繼日誌讀取事件,並重播其中的事件而更新slave的數據,使其與master中的數據一致。只要該執行緒與I/O執行緒保持一致,中繼日誌通常會位於OS的快取中,所以中繼日誌的開銷很小。
        另外,在master中也有一個工作線程:和其它MySQL的連接一樣,slave在master中打開一個連接也會讓master開始一個線程。複製過程有一個很重要的限制-複製在slave上是串列化的,也就是說master上的平行更新操作不能在slave上並行操作。

 2 .主從複製設定


有兩台MySQL資料庫伺服器Master和slave,Master為主伺服器,slave為從伺服器,初始狀態時,Master和slave中的資料資訊相同,當Master中的資料改變時,slave也跟著發生相應的變化,使得master和slave的資料資訊同步,達到備份的目的。

重點:
負責在主、從伺服器傳輸各種修改動作的媒介是主伺服器的二進位變更日誌,這個日誌記載著需要傳送給從伺服器的各種修改動作。因此,主伺服器必須啟動二進位日誌功能。從伺服器必須具備足以讓它連接主伺服器並請求主伺服器把二進位變更日誌傳輸給它的權限。
        
環境:
Master與slave的MySQL資料庫版本同為5.0.18
IP位址:10.100.0.100

#2.1、建立複製帳號

1、在Master的資料庫中建立一個備份帳戶:每個slave使用標準的MySQL使用者名稱和密碼連線master。進行複製操作的使用者會授予REPLICATION SLAVE權限。使用者名稱的密碼都會儲存在文字檔案master.info中

指令如下:

mysql > GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* TO backup@’10.100.0.200’ IDENTIFIED BY ‘1234’;

 

建立一個帳戶backup,並且只能允許從10.100.0.200這個位址上來登陸,密碼是1234。

(如果因為mysql版本新舊密碼演算法不同,可以設定:set password for 'backup'@'10.100.0.200'=old_password('1234'))

#2.2、拷貝資料

(假如是你完全新安裝mysql主從伺服器,這個步驟就不需要。因為新安裝的master和slave有相同的資料)

關閉Master伺服器,將Master中的資料拷貝到B伺服器中,使得Master和slave中的資料同步,並且確保在全部設定操作結束前,禁止在Master和slave伺服器中進行寫入操作,使得兩個資料庫中的資料一定要相同!

2.3、設定master

 

#接下來對master進行配置,包括開啟二進位日誌,指定唯一的servr ID。例如,在設定檔加入下列值:

server-id=1log-bin=mysql-binserver-id:为主服务器A的ID值log-bin:二进制变更日值

重啟master,執行SHOW MASTER STATUS,輸出如下:

詳解高性能Mysql主從架構的複製原理及配置

## 



# #2.4、設定slave

###Slave的設定與master類似,你同樣需要重新啟動slave的MySQL。如下:###
log_bin           = mysql-binserver_id         = 2relay_log         = mysql-relay-binlog_slave_updates = 1read_only         = 1
###server_id:是必須的,而且唯一。 ######log_bin:slave沒有必要開啟二進位日誌bin_log,但在某些情況下,必須設定,例如,如果slave為其它slave的master,必須設定bin_log。在這裡,我們開啟了二進位日誌,而且顯示的命名(預設名稱為hostname,但是,如果hostname改變則會出現問題)。 ### relay_log:設定中繼日誌,log_slave_updates表示slave將複製事件寫進自己的二進位日誌(後面會看到它的用處)。 ### 有些人開啟了slave的二進位日誌,卻沒有設定log_slave_updates,然後查看slave的資料是否改變,這是錯誤的設定。 ######read_only:盡量使用read_only,它防止改變資料(除了特殊的執行緒)。但是,read_only並且很實用,特別是那些需要在slave上建立表格的應用程式。 ###### #########2.5、啟動slave#######

接下来就是让slave连接master,并开始重做master二进制日志中的事件。你不应该用配置文件进行该操作,而应该使用CHANGE MASTER TO语句,该语句可以完全取代对配置文件的修改,而且它可以为slave指定不同的master,而不需要停止服务器。如下:

mysql> CHANGE MASTER TO MASTER_HOST='server1',    -> MASTER_USER='repl',    -> MASTER_PASSWORD='p4ssword',    -> MASTER_LOG_FILE='mysql-bin.000001',    -> MASTER_LOG_POS=0;

MASTER_LOG_POS的值为0,因为它是日志的开始位置。

你可以用SHOW SLAVE STATUS语句查看slave的设置是否正确:

mysql> SHOW SLAVE STATUS\G*************************** 1. row ***************************             Slave_IO_State:                Master_Host: server1                Master_User: repl                Master_Port: 3306              Connect_Retry: 60            Master_Log_File: mysql-bin.000001        Read_Master_Log_Pos: 4             Relay_Log_File: mysql-relay-bin.000001              Relay_Log_Pos: 4      Relay_Master_Log_File: mysql-bin.000001           Slave_IO_Running: No          Slave_SQL_Running: No                             ...omitted...      Seconds_Behind_Master: NULLSlave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No

表明slave还没有开始复制过程。日志的位置为4而不是0,这是因为0只是日志文件的开始位置,并不是日志位置。实际上,MySQL知道的第一个事件的位置是4。

为了开始复制,你可以运行:

mysql> START SLAVE;运行SHOW SLAVE STATUS查看输出结果:mysql> SHOW SLAVE STATUS\G*************************** 1. row ***************************             Slave_IO_State: Waiting for master to send event                Master_Host: server1                Master_User: repl                Master_Port: 3306              Connect_Retry: 60            Master_Log_File: mysql-bin.000001        Read_Master_Log_Pos: 164             Relay_Log_File: mysql-relay-bin.000001              Relay_Log_Pos: 164      Relay_Master_Log_File: mysql-bin.000001           Slave_IO_Running: Yes          Slave_SQL_Running: Yes                             ...omitted...      Seconds_Behind_Master: 0

在这里主要是看:

                   Slave_IO_Running=Yes                   Slave_SQL_Running=Yes

 

slave的I/O和SQL线程都已经开始运行,而且Seconds_Behind_Master不再是NULL。日志的位置增加了,意味着一些事件被获取并执行了。如果你在master上进行修改,你可以在slave上看到各种日志文件的位置的变化,同样,你也可以看到数据库中数据的变化。

你可查看master和slave上线程的状态。在master上,你可以看到slave的I/O线程创建的连接:

在master上输入show processlist\G;

mysql> show processlist \G

*************************** 1. row ***************************

     Id: 1

   User: root

   Host: localhost:2096

     db: test

Command: Query

   Time: 0

 State: NULL

   Info: show processlist

*************************** 2. row ***************************

     Id: 2

   User: repl

   Host: localhost:2144

     db: NULL

Command: Binlog Dump

   Time: 1838

 State: Has sent all binlog to slave; waiting for binlog to be updated

   Info: NULL

2 rows in set (0.00 sec)

 

行2为处理slave的I/O线程的连接。

在slave服务器上运行该语句:

mysql> show processlist \G

*************************** 1. row ***************************

     Id: 1

   User: system user

   Host:

     db: NULL

Command: Connect

   Time: 2291

 State: Waiting for master to send event

   Info: NULL

*************************** 2. row ***************************

     Id: 2

   User: system user

   Host:

     db: NULL

Command: Connect

   Time: 1852

 State: Has read all relay log; waiting for the slave I/O thread to update it

   Info: NULL

*************************** 3. row ***************************

     Id: 5

   User: root

   Host: localhost:2152

     db: test

Command: Query

   Time: 0

 State: NULL

   Info: show processlist

3 rows in set (0.00 sec)


行1为I/O线程状态,行2为SQL线程状态。

2.5、添加新slave服务器

假如master已经运行很久了,想对新安装的slave进行数据同步,甚至它没有master的数据。
此时,有几种方法可以使slave从另一个服务开始,例如,从master拷贝数据,从另一个slave克隆,从最近的备份开始一个slave。Slave与master同步时,需要三样东西:
(1)master的某个时刻的数据快照;
(2)master当前的日志文件、以及生成快照时的字节偏移。这两个值可以叫做日志文件坐标(log file coordinate),因为它们确定了一个二进制日志的位置,你可以用SHOW MASTER STATUS命令找到日志文件的坐标;
(3)master的二进制日志文件。

可以通过以下几中方法来克隆一个slave:
(1)    冷拷贝(cold copy)
停止master,将master的文件拷贝到slave;然后重启master。缺点很明显。
(2)    热拷贝(warm copy)
如果你仅使用MyISAM表,你可以使用mysqlhotcopy拷贝,即使服务器正在运行。
(3)    使用mysqldump
使用mysqldump来得到一个数据快照可分为以下几步:
锁表:如果你还没有锁表,你应该对表加锁,防止其它连接修改数据库,否则,你得到的数据可以是不一致的。如下:
mysql> FLUSH TABLES WITH READ LOCK;
在另一个连接用mysqldump创建一个你想进行复制的数据库的转储:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
对表释放锁。
mysql> UNLOCK TABLES;

 

3、深入了解复制


已经讨论了关于复制的一些基本东西,下面深入讨论一下复制。

3.1、基于语句的复制(Statement-Based Replication)

     MySQL 5.0及之前的版本仅支持基于语句的复制(也叫做逻辑复制,logical replication),这在数据库并不常见。master记录下改变数据的查询,然后,slave从中继日志中读取事件,并执行它,这些SQL语句与master执行的语句一样。
这种方式的优点就是实现简单。此外,基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
 
      但是,基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,例如,master与slave可能有不同的时间。所以,MySQL的二进制日志的格式不仅仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。即使如此,还是有一些语句,比如,CURRENT USER函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。
     另外一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。

3.2、基于记录的复制(Row-Based Replication)

      MySQL增加基于记录的复制,在二进制日志中记录下实际数据的改变,这与其它一些DBMS的实现方式类似。这种方式有优点,也有缺点。优点就是可以对任何语句都能正确工作,一些语句的效率更高。主要的缺点就是二进制日志可能会很大,而且不直观,所以,你不能使用mysqlbinlog来查看二进制日志。
对于一些语句,基于记录的复制能够更有效的工作,如:

mysql> INSERT INTO summary_table(col1, col2, sum_col3)    -> SELECT col1, col2, sum(col3)    -> FROM enormous_table    -> GROUP BY col1, col2;

     假设,只有三种唯一的col1和col2的组合,但是,该查询会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。
    另一方面,下面的语句,基于语句的复制更有效:
 mysql> UPDATE enormous_table SET col1 = 0;
此时使用基于记录的复制代价会非常高。由于两种方式不能对所有情况都能很好的处理,所以,MySQL 5.1支持在基于语句的复制和基于记录的复制之前动态交换。你可以通过设置session变量binlog_format来进行控制。

3.3、复制相关的文件

除了二进制日志和中继日志文件外,还有其它一些与复制相关的文件。如下:

(1)mysql-bin.index

伺服器一旦開啟二進位日誌,會產生一個與二日誌檔案同名,但是以.index結尾的檔案。它用於追蹤磁碟上存在哪些二進位日誌檔案。 MySQL用它來定位二進位日誌檔。它的內容如下(我的機器上):
詳解高性能Mysql主從架構的複製原理及配置

 (2)mysql-relay-bin.index

該檔案的功能與mysql-bin.index類似,但是它是針對中繼日誌,而不是二進位日誌。內容如下:
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018

(3)master.info

#儲存master的相關資訊。不要刪除它,否則,slave重啟後不能連接master。內容如下(我的機器上):

詳解高性能Mysql主從架構的複製原理及配置

 

# I/O執行緒更新master.info文件,內容如下(我的機器上):

.\mysql-02-relay-bin.000019

254

mysql-01-bin.000010

286

0

52813

#


 (4)relay-log.info 

包含slave中目前二進位日誌和中繼日誌的資訊。

3.4、發送複製事件到其它slave

當設定log_slave_updates時,你可以讓slave扮演其它slave的master。此時,slave把SQL執行緒執行的事件寫進行自己的二進位日誌(binary log),然後,它的slave可以取得這些事件並執行它。如下:
詳解高性能Mysql主從架構的複製原理及配置

3.5、複製過濾(Replication Filters)

複製過濾可以讓你只複製伺服器中的一部分數據,有兩種複製過濾:在master上過濾二進位日誌中的事件;在slave上過濾中繼日誌中的事件。如下:

 

詳解高性能Mysql主從架構的複製原理及配置

 

#4、複製的常用拓樸結構


複製的體系結構有以下一些基本原則:
(1)    每個slave只能有一個master;
(2)    每個slave只能有一個唯一的伺服器ID;
(3)    每個master可以擁有很多slave;
(4)    如果你設定log_slave_updates,slave可以是其它slave的master,從而擴散master的更新。

MySQL不支援多主機伺服器複製(Multimaster Replication)-也就是一個slave可以有多個master。但是,透過一些簡單的組合,我們卻可以建立靈活而強大的複製體系結構。

 

4.1、單一master和多重slave

        則由一個master和一個slave組成複製系統是最簡單的情況。 Slave之間並非互相通信,只能與master溝通。

        在實際應用情境中,MySQL複製90%以上都是一個Master複製到一個或多個Slave的架構模式,主要用於讀取壓力比較大的應用的資料庫端廉價擴充解決方案。因為只要Master和Slave的壓力不是太大(尤其是Slave端壓力)的話,非同步複製的延遲一般都很少很少。尤其是自從Slave端的複製方式改成兩個執行緒處理之後,更是減少了Slave端的延時問題。而帶來的效益是,對於資料即時性要求不是特別Critical的應用,只需要透過廉價的pcserver來擴展Slave的數量,將讀取壓力分散到多台Slave的機器上面,即可透過分散單一資料庫伺服器的讀壓力來解決資料庫端的讀取效能瓶頸,畢竟在大多數資料庫應用系統中的讀壓力還是比寫壓力大很多。這在很大程度上解決了目前許多中小型網站的資料庫壓力瓶頸問題,甚至有些大型網站也在使用類似方案解決資料庫瓶頸。

如下:
詳解高性能Mysql主從架構的複製原理及配置
 如果寫入操作較少,而讀取操作很時,可以採取這種結構。你可以將讀取操作分佈到其它的slave,從而減少master的壓力。但是,當slave增加到一定數量時,slave對master的負載以及網路頻寬都會變成一個嚴重的問題。
這種結構雖然簡單,但是,它卻非常靈活,足以滿足大多數應用需求。一些建議:
(1)    不同的slave扮演不同的功能(例如使用不同的索引,或不同的儲存引擎);
(2)    用一個slave作為備用master,只複製;
(3)    用遠端的slave,用於災難復原;

大家應該都比較清楚,從一個Master節點可以複製出多個Slave節點,可能有人會想,那一個Slave節點是否可以從多個Master節點上面進行複製呢?至少在目前來看,MySQL是做不到的,以後是否會支援就不清楚了。

MySQL不支援一個Slave節點從多個Master節點來進行複製的架構,主要是為了避免衝突的問題,防止多個資料來源之間的資料出現衝突,而造成最後資料的不一致性。不過聽說已經有人開發了相關的patch,讓MySQL支援一個Slave節點從多個Master結點當作資料來源來複製,這也正是MySQL開源的本質所帶來的好處。

 

 

4.2、主動模式的Master-Master(Master-Master in Active-Active Mode)

Master-Master複製的兩台伺服器,既是master,也是另一台伺服器的slave。這樣,任何一方所做的變更,都會透過複製應用到另外一方的資料庫。

 

可能有些读者朋友会有一个担心,这样搭建复制环境之后,难道不会造成两台MySQL之间的循环复制么?实际上MySQL自己早就想到了这一点,所以在MySQL的BinaryLog中记录了当前MySQL的server-id,而且这个参数也是我们搭建MySQLReplication的时候必须明确指定,而且Master和Slave的server-id参数值比需要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值之后,MySQL就很容易判断某个变更是从哪一个MySQLServer最初产生的,所以就很容易避免出现循环复制的情况。而且,如果我们不打开记录Slave的BinaryLog的选项(--log-slave-update)的时候,MySQL根本就不会记录复制过程中的变更到BinaryLog中,就更不用担心可能会出现循环复制的情形了。

 

如图:
詳解高性能Mysql主從架構的複製原理及配置

 

主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都需要自己的可写的数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,如果两个服务器分别同时执行如下语句:
在第一个服务器上执行:

mysql> UPDATE tbl SET col=col + 1;

在第二个服务器上执行:

mysql> UPDATE tbl SET col=col * 2;

那么结果是多少呢?一台服务器是4,另一个服务器是3,但是,这并不会产生错误。
实际上,MySQL并不支持其它一些DBMS支持的多主服务器复制(Multimaster Replication),这是MySQL的复制功能很大的一个限制(多主服务器的难点在于解决更新冲突),但是,如果你实在有这种需求,你可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台。但是,可以通过其它一些方式来模拟这种多主服务器的复制。

 

4.3、主动-被动模式的Master-Master(Master-Master in Active-Passive Mode)

这是master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中一个服务只能进行只读操作。如图:
詳解高性能Mysql主從架構的複製原理及配置

 

 

4.4 级联复制架构 Master –Slaves - Slaves

        在有些应用场景中,可能读写压力差别比较大,读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑注读的压力。这时候,Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端因为复制就会消耗较多的资源,很容易造成复制的延时。

        遇到这种情况如何解决呢?这时候我们就可以利用MySQL可以在Slave端记录复制所产生变更的BinaryLog信息的功能,也就是打开—log-slave-update选项。然后,通过二级(或者是更多级别)复制来减少Master端因为复制所带来的压力。也就是说,我们首先通过少数几台MySQL从Master来进行复制,这几台机器我们姑且称之为第一级Slave集群,然后其他的Slave再从第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,我称之为第二级Slave集群。如果有需要,我们可以继续往下增加更多层次的复制。这样,我们很容易就控制了每一台MySQL上面所附属Slave的数量。这种架构我称之为Master-Slaves-Slaves架构

            这种多层级联复制的架构,很容易就解决了Master端因为附属Slave太多而成为瓶颈的风险。下图展示了多层级联复制的Replication架构。

詳解高性能Mysql主從架構的複製原理及配置

当然,如果条件允许,我更倾向于建议大家通过拆分成多个Replication集群来解决

上述瓶颈问题。毕竟Slave并没有减少写的量,所有Slave实际上仍然还是应用了所有的数据变更操作,没有减少任何写IO。相反,Slave越多,整个集群的写IO总量也就会越多,我们没有非常明显的感觉,仅仅只是因为分散到了多台机器上面,所以不是很容易表现出来。

此外,增加复制的级联层次,同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险。

而如果我们通过分拆集群的方式来解决的话,可能就会要好很多了,当然,分拆集群也需要更复杂的技术和更复杂的应用系统架构。

 

 4.5、带从服务器的Master-Master结构(Master-Master with Slaves)

这种结构的优点就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,而且还可以将读密集型的请求放到slave上。

詳解高性能Mysql主從架構的複製原理及配置

级联复制在一定程度上面确实解决了Master因为所附属的Slave过多而成为瓶颈的问题,但是他并不能解决人工维护和出现异常需要切换后可能存在重新搭建Replication的问题。这样就很自然的引申出了DualMaster与级联复制结合的Replication架构,我称之为Master-Master-Slaves架构

和Master-Slaves-Slaves架构相比,区别仅仅只是将第一级Slave集群换成了一台单独的Master,作为备用Master,然后再从这个备用的Master进行复制到一个Slave集群。

这种DualMaster与级联复制结合的架构,最大的好处就是既可以避免主Master的写入操作不会受到Slave集群的复制所带来的影响,同时主Master需要切换的时候也基本上不会出现重搭Replication的情况。但是,这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,因为如果后面的Slave集群比较大的话,备用Master可能会因为过多的SlaveIO线程请求而成为瓶颈。当然,该备用Master不提供任何的读服务的时候,瓶颈出现的可能性并不是特别高,如果出现瓶颈,也可以在备用Master后面再次进行级联复制,架设多层Slave集群。当然,级联复制的级别越多,Slave集群可能出现的数据延时也会更为明显,所以考虑使用多层级联复制之前,也需要评估数据延时对应用系统的影响。

 

5、复制的常见问题


错误一:change master导致的:
     Last_IO_Error: error connecting to master 'repl1@IP:3306' - retry-time: 60  retries

错误二:在没有解锁的情况下停止slave进程:

 mysql> stop slave;

ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction

 

错误三:在没有停止slave进程的情况下change master

mysql> change master to master_host=‘IP', master_user='USER', master_password='PASSWD', master_log_file='mysql-bin.000001',master_log_pos=106;

ERROR 1198 (HY000): This operation cannot be performed with a running slave; run STOP SLAVE first

 

错误四:A B的server-id相同:
Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; 
these ids must be different for replication to work (or the --replicate-same-server-id option must be used on
slave but this does not always make sense; please check the manual before using it). 
查看server-id
mysql> show variables like 'server_id'; 
手动修改server-id
mysql> set global server_id=2; #此处的数值和my.cnf里设置的一样就行 
mysql> slave start;

错误五:change master之后,查看slave的状态,发现slave_IO_running 仍为NO
需要注意的是,上述几个错误做完操作之后要重启mysql进程,slave_IO_running 变为Yes

 

错误六:MySQL主从同步异常Client requested master to start replication from position > file size

字面理解:从库的读取binlog的位置大于主库当前binglog的值

这一般是主库重启导致的问题,主库从参数sync_binlog默认为1000,即主库的数据是先缓存到1000条后统一fsync到磁盘的binlog文件中。

 当主库重启的时候,从库直接读取主库接着之前的位点重新拉binlog,但是主库由于没有fsync最后的binlog,所以会返回1236 的错误。
正常建议配置sync_binlog=1 也就是每个事务都立即写入到binlog文件中。

1、在从库检查slave状态:

偏移量为4063315

詳解高性能Mysql主從架構的複製原理及配置

2、在主库检查mysql-bin.001574的偏移量位置

     mysqlbinlog mysql-bin.001574 >  ./mysql-bin.001574.bak

     tail -10 ./mysql-bin.001574.bak

mysql-bin.001574文件最后几行 发现最后偏移量是4059237,从库偏移量的4063315远大主库的偏移量4059237,也就是参数sync_binlog=1000导致的。

詳解高性能Mysql主從架構的複製原理及配置

3、重新设置salve

mysql> stop slave;mysql> change master to master_log_file='mysql-bin.001574' ,master_log_pos=4059237;mysql> start slave;

错误8:数据同步异常情况

 

第一种:在master上删除一条记录,而slave上找不到。

Last_Error: Could not execute Delete_rows event on table market_edu.tl_player_task; Can't find record in 'tl_player_task', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.002094, end_log_pos 286434186

解决方法:由于master要删除一条记录,而slave上找不到故报错,这种情况主上都将其删除了,那么从机可以直接跳过。

可用命令:stop slave;   set global sql_slave_skip_counter=1;    start slave;

第二种:主键重复。在slave已经有该记录,又在master上插入了同一条记录。

Last_SQL_Error: Could not execute Write_rows event on table hcy.t1; 
Duplicate entry '2' for key 'PRIMARY', 
Error_code: 1062; 
handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000006, end_log_pos 924

解决方法:在slave删除重复的主键

第三种:在master上更新一条记录,而slave上找不到,丢失了数据。

Last_SQL_Error: Could not execute Update_rows event on table hcy.t1;
Can't find record in 't1', 
Error_code: 1032; 
handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000010, end_log_pos 263

解决方法:把丢失的数据在slave上填补,然后跳过报错即可。

insert into t1 values (2,'BTV');

stop slave ;set global sql_slave_skip_counter=1;start slave;

相关免费学习推荐:mysql数据库(视频)

以上是詳解高性能Mysql主從架構的複製原理及配置的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除