MySQL Replication 優化和技巧、常見故障解決方法

 

一些錯誤信息的處理,主從服務器上的命令,及狀態信息。
在從服務器上使用show slave status\G

Slave_IO_Running,爲No,
則說明IO_THREAD沒有啓動,請執行start slave io_thread

Slave_SQL_Running爲No
則複製出錯,查看Last_error字段排除錯誤後執行start slave sql_thread

查看Slave_IO_State字段空 //複製沒有啓動
Connecting to master//沒有連接上master
Waiting for master to send event//已經連上

主服務器上的相關命令:
show master status
show slave hosts
show logs
show binlog events
purge logs to 'log_name'
purge logs before 'date'
reset master(老版本flush master)
set sql_log_bin=

 

從服務器上的相關命令:
slave start
slave stop
SLAVE STOP IO_THREAD //此線程把master段的日誌寫到本地
SLAVE start IO_THREAD
SLAVE STOP SQL_THREAD //此線程把寫到本地的日誌應用於數據庫
SLAVE start SQL_THREAD
reset slave
SET GLOBAL SQL_SLAVE_SKIP_COUNTER
load data from master
show slave status(SUPER,REPLICATION CLIENT)
CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=,MASTER_USER=, MASTER_PASSWORD= //動態改變master信息
PURGE MASTER [before 'date'] 刪除master端已同步過的日誌


6.3.1 Master 同步線程狀態

以下列出了master的 Binlog Dump 線程 State 字段中最常見的幾種狀態。如果在master上沒有 Binlog Dump 線程,那麼同步就沒有在運行。

也就是說,沒有slave連接上來。


Sending binlog event to slave

事件是由二進制日誌構成,一個事件通常由更新語句加上其他信息。線程讀取到一個事件並正發送到slave上。


Finished reading one binlog; switching to next binlog

讀取完了一個二進制日誌,正切換到下一個。


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

已經讀取完全部未完成更新日誌,並且全部都發送到slave了。它處於空閒狀態,正等待在master上執行新的更新操作以在二進制日誌中產生新

的事件,然後讀取它們。


Waiting to finalize termination

當前線程停止了,這個時間很短。

 

6.3.2 Slave的I/O線程狀態

以下列出了slave的I/O線程 State 字段中最常見的幾種狀態。從MySQL 4.1.1開始,這個狀態在執行 SHOW SLAVE STATUS 語句結果的

Slave_IO_State 字段也會出現。這意味着可以只執行 SHOW SLAVE STATUS 語句就能瞭解到更多的信息。


Connecting to master

該線程證嘗試連接到master上。


Checking master version

確定連接到master後出現的一個短暫的狀態。


Registering slave on master

確定連接到master後出現的一個短暫的狀態。


Requesting binlog dump

確定連接到master後出現的一個短暫的狀態。該線程向master發送一個請求,告訴它要請求的二進制文件以及開始位置。


Waiting to reconnect after a failed binlog dump request

如果二進制日誌轉儲(binary log dump)請求失敗了(由於連接斷開),該線程在休眠時進入這個狀態,並定期重連。重連的時間間隔由 --

master-connect-retry 選項來指定。


Reconnecting after a failed binlog dump request

該線程正嘗試重連到master。


Waiting for master to send event

已經連接到master,正等待它發送二進制日誌。如果master閒置時,這個狀態可能會持續較長時間,如果它等待超過 slave_read_timeout 秒

,就會發生超時。這時,它就會考慮斷開連接,然後嘗試重連。


Queueing master event to the relay log

已經讀取到一個事件,正把它拷貝到中繼日誌中以備SQL線程處理。


Waiting to reconnect after a failed master event read

讀日誌時發生錯誤(由於連接斷開)。該線程在重連之前休眠 master-connect-retry 秒。
Reconnecting after a failed master event read


正嘗試重連到master。當連接確定後,狀態就變成 Waiting for master to send event。


Waiting for the slave SQL thread to free enough relay log space

relay_log_space_limit 的值非零,中繼日誌的大小總和超過這個值了。I/O線程等待SQL線程先處理中繼日誌然後刪除它們以釋放足夠的空間


Waiting for slave mutex on exit

當前線程停止了,這個時間很短。

 

6.3.3 Slave的SQL線程狀態

以下列出了slave的SQL線程 State 字段中最常見的幾種狀態:


Reading event from the relay log

從中繼日誌裏讀到一個事件以備執行。


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

已經處理完中繼日誌中的全部事件了,正等待I/O線程寫入更新的日誌。


Waiting for slave mutex on exit

當前線程停止了,這個時間很短。

 

 

 

 

故障

問題:主從複製不止何故停止了,我該怎麼辦?

答案:複製錯誤多半是因爲日誌錯誤引起的,所以首先要搞清楚是主日誌錯誤還是中繼日誌錯誤,從錯誤信息裏一般就能判斷,如果不能可以使用類似下面的mysqlbinlog命令:

shell> mysqlbinlog <MASTER_BINLOG_FILE> > /dev/null

shell> mysqlbinlog <SLAVE_BINLOG_FILE> > /dev/null

如果沒有錯誤,則不會有任何輸出,反之如果有錯誤,則會顯示出來。

如果是主日誌錯誤,則需要在從服務器使用SET GLOBAL sql_slave_skip_counter,如下:

mysql> SET GLOBAL sql_slave_skip_counter = 1;

mysql> START SLAVE;

注:如果有多個錯誤,可能需要執行多次(提醒:主從服務器數據可能因此不一致)。

如果是中繼日誌錯誤,只要在從服務器使用SHOW SLAVE STATUS結果中的日誌信息重新CHANGE MASTER TO即可,系統會拋棄當前的中繼日誌,重新下載:

mysql> CHANGE MASTER TO

MASTER_LOG_FILE='<Relay_Master_Log_File>',

MASTER_LOG_POS=<Exec_Master_Log_Pos>;

mysql> START SLAVE;

至於爲什麼使用的是Relay_Master_Log_File & Exec_Master_Log_Pos,參見概述。

問題:主服務器宕機了,如何把從服務器提升會主服務器?

答案:在一主多從的環境總,需選擇數據最新的從服務器做新的主服務器。如下圖所示:

提升從服務器爲主服務器

在一主(Server1)兩從(Server2,、Server3)的環境中,Server1宕機後,等到Server1和Server2把宕機前同步到的日誌都執行完,比較Master_Log_File和Read_Master_Log_Pos就可以判斷出誰快誰慢,因爲Server2從 Server1同步的數據(1582)比Server3從Server1同步的數據(1493)新,所以應該提升Server2爲新的主服務器,那麼 Server3在CHANGE MASTER TO到Server2的時候應該使用什麼樣的參數呢?1582-1493=89,而Server2的最後的二進制日誌位置是8167,所以答案是 8167-89=8078。

技巧

主從服務器中的表可以使用不同的表類型。比如主服務器可以使用InnoDB表類型,提供事務,行鎖等高級特性,從服務器可以使用MyISAM表類型,內存消耗少,易備份等優點。還有一個例子,一臺主服務器如果同時帶很多個從服務器的話,勢必會影響其性能,此時可以拿出一臺服務器作爲從服務器代理,使用BLACKHOLE表類型,只記錄日誌,不寫數據,由它帶多臺從服務器,從而提升性能。

主從服務器中的表可以使用不同的鍵類型。比如主服務器用InnoDB,鍵用VARCHAR的話節省空間,從服務器使用MyISAM,鍵用CHAR提高速度,因爲MyISAM有靜態表一說。

主從服務器中的表可以使用不同的索引。主服務器主要用來應付寫操作,所以除了主鍵和唯一索引等保證數據關係的索引一般都可以不加,從服務器一般用來應付讀操作,所以可以針對查詢特徵設置索引,再進一步,不同的從服務器可以針對不同的查詢設置不同的索引。

 

 

MySQL同步功能由3個線程(master上1個,slave上2個)來實現。執行 DE>START SLAVEDE> 語句後,slave就創建一個I/O線程。I/O線程連接到master上,並請求master發送二進制日誌中的語句。master創建一個線程來把日誌的內容發送到slave上。這個線程在master上執行 DE>SHOW PROCESSLISTDE> 語句後的結果中的 DE>Binlog DumpDE> 線程便是。slave上的I/O線程讀取master的 DE>Binlog DumpDE> 線程發送的語句,並且把它們拷貝到其數據目錄下的中繼日誌(relay logs)中。第三個是SQL線程,salve用它來讀取中繼日誌,然後執行它們來更新數據。

如上所述,每個master/slave上都有3個線程。每個master上有多個線程,它爲每個slave連接都創建一個線程,每個slave只有I/O和SQL線程。

show slave master 用於提供有關從屬服務器線程的關鍵參數的信息

mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.2.40
Master_User: photorepl
Master_Port: 4331
Connect_Retry: 60
Master_Log_File: mysql-bin.005502
Read_Master_Log_Pos: 64401238
Relay_Log_File: mysqld-relay-bin.015418
Relay_Log_Pos: 13456757
Relay_Master_Log_File: mysql-bin.005152
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table: photo.%
Replicate_Wild_Ignore_Table: mysql.%
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 13456620
Relay_Log_Space: 36764898503
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 249904
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

SHOW SLAVE STATUS會返回以下字段:

? Slave_IO_State

SHOW PROCESSLIST輸出的State字段的拷貝。SHOW PROCESSLIST用於從屬I/O線程。如果線程正在試圖連接到主服務器,正在等待來自主服務器的時間或正在連接到主服務器等,本語句會通知您

? Master_User

被用於連接主服務器的當前用戶。

? Master_Port

當前的主服務器接口。

? Connect_Retry

–master-connect-retry選項的當前值

? Master_Log_File

I/O線程當前正在讀取的主服務器二進制日誌文件的名稱。

? Read_Master_Log_Pos

在當前的主服務器二進制日誌中,I/O線程已經讀取的位置。

? Relay_Log_File

SQL線程當前正在讀取和執行的中繼日誌文件的名稱。

? Relay_Log_Pos

在當前的中繼日誌中,SQL線程已讀取和執行的位置。

? Relay_Master_Log_File

由SQL線程執行的包含多數近期事件的主服務器二進制日誌文件的名稱。

? Slave_IO_Running

I/O線程是否被啓動併成功地連接到主服務器上。

? Slave_SQL_Running

SQL線程是否被啓動。

? Replicate_Do_DB,Replicate_Ignore_DB

使用–replicate-do-db和–replicate-ignore-db選項指定的數據庫清單。

? Replicate_Do_Table,Replicate_Ignore_Table,Replicate_Wild_Do_Table,Replicate_Wild_Ignore_Table

使用–replicate-do-table,–replicate-ignore-table,–replicate-wild-do-table和–replicate-wild-ignore_table選項指定的表清單。

? Last_Errno,Last_Error

被多數最近被執行的查詢返回的錯誤數量和錯誤消息。錯誤數量爲0並且消息爲空字符串意味着“沒有錯誤”。如果Last_Error值不是空值,它也會在從屬服務器的錯誤日誌中作爲消息顯示。

舉例說明:

Last_Errno: 1051

Last_Error: error ‘Unknown table ‘z” on query ‘drop table z’

該消息指示,表z曾經存在於在主服務器中並已被取消了,但是它沒有在從屬服務器中存在過,因此對於從屬服務器,DROP TABLE失敗。(舉例說明,在設置複製時,如果您忘記了把此表拷貝到從屬服務器中,則這有可能發生。)

? Skip_Counter

最近被使用的用於SQL_SLAVE_SKIP_COUNTER的值。

? Exec_Master_Log_Pos

來自主服務器的二進制日誌的由SQL線程執行的上一個時間的位置(Relay_Master_Log_File)。在主服務器的二進制日誌中的(Relay_Master_Log_File, Exec_Master_Log_Pos)對應於在中繼日誌中的(Relay_Log_File,Relay_Log_Pos)。

? Relay_Log_Space

所有原有的中繼日誌結合起來的總大小。

? Until_Condition,Until_Log_File,Until_Log_Pos

在START SLAVE語句的UNTIL子句中指定的值。

Until_Condition具有以下值:

o 如果沒有指定UNTIL子句,則沒有值

o 如果從屬服務器正在讀取,直到達到主服務器的二進制日誌的給定位置爲止,則值爲Master

o 如果從屬服務器正在讀取,直到達到其中繼日誌的給定位置爲止,則值爲Relay

Until_Log_File和Until_Log_Pos用於指示日誌文件名和位置值。日誌文件名和位置值定義了SQL線程在哪個點中止執行。

? Master_SSL_Allowed,Master_SSL_CA_File,Master_SSL_CA_Path,Master_SSL_Cert,Master_SSL_Cipher,Master_SSL_Key

這些字段顯示了被從屬服務器使用的參數。這些參數用於連接主服務器。

Master_SSL_Allowed具有以下值:

o 如果允許對主服務器進行SSL連接,則值爲Yes

o 如果不允許對主服務器進行SSL連接,則值爲No

o 如果允許SSL連接,但是從屬服務器沒有讓SSL支持被啓用,則值爲Ignored。

與SSL有關的字段的值對應於–master-ca,–master-capath,–master-cert,–master-cipher和–master-key選項

########################################################################

 

Replication延時的類型

    1、固定性的延時

    ——Slave的數據持續性的落後於Master並且一直無法與Master的數據保持一致。

    ——Slave的數據經常在白天落後於Master,而在晚上可以趕上並與Master的記錄保持一致。

    這種類型的延時通常是由於Slave服務器的負載已經到達了上限或在白天訪問量大的時候到達上限造成的。

    2、非固定性的延時

    ——Slave的數據只是短暫的落後於Master,可在短時間內恢復,這類型的延時通常與批量任務和報表有關,效率差的查詢也會導致這類延時

    Mysql Replication的限制

      Mysql的Replication是單線程的,意味着只能有效的使用一個CPU內核和一個磁盤,一條複雜的查詢或者事務都導致進程被阻塞,不過現在針對5.1版本的多線程Replication補丁,http://forge.mysql.com/wiki/ReplicationFeatures/ParallelSlave,還是pre版,有很多限制,感興趣的可以去看看。

    Replication的容量

    1、理解什麼是Replication的容量

      可以將Replication暫停一個小時,重新啓動Replication後,觀察Slave的數據多久可以與Master一致。從Replication重新啓動到和Master數據一致所花費的時間與Replication暫停的時間的比值就是Replication的容量。

    2、建議保持Replication的容量在3倍以上,即延遲一個小時的數據,Slave只需要20分鐘就能與Master的數據一致。

    Replication的優化

    1、5.0的mysql中避免類似以下的更新語句

    INSERT … SELECT

    UPDATE .... WHERE

      複雜的查詢會導致Replication線程阻塞。如果是insert或update與select結合的語句,可以講select單獨執行並保存在臨時表中,然後再執行insert或者update。

      如果使用的是5.1的mysql,新功能中的行級Replication(RBR)可以解決這個問題。RBR可以將在Master上通過複雜查詢後更新的結果直接傳給Slave,Slave可以直接將結果更新到數據庫中。

    2、避免大的事務

    太大的事務會造成Replication長時間阻塞,數據會嚴重滯後於Master。

    Slave服務器的硬件選擇

    更快的CPU內核,對於單線程的Replication多核CPU是沒有任何優勢的。更高速的硬盤,包括更高的轉速和更好的高速緩存命中率,如果有錢的話上SSD吧。

    主從結構的擴展性問題

    1、如何降低寫操作的頻率

      Master的寫操作會擴散到所有的Slave上,所以高頻率的寫操作會降低Slave的讀操作效率。

    至少保持一臺Slave做全庫同步,其他的Slave可以只做部分表的同步。當然,這需要web應用程序的配合來分配哪些查詢讀哪些Slave。將一些更新操作放到memcached中,例如session和計數器。Slave使用myisam引擎,將一些寫入量很大的更新操作直接在slave上執行,而不通過Replication。

    2、如何更有效的利用Slave的硬件資源[ 變形蟲]

    使用分區

    有選擇的對錶進行同步

    在Slave上對數據進行歸檔。

    Session的持久化

    爲不同的應用服務器分配不同的Slave進行讀操作。

    或者根據查詢類型的不同來分配不同的Slave。

    3、如何使你的程序最大化的利用Slave

      將對數據更新不敏感的查詢放到Slave上,而需要實時數據的查詢則放到Master。通過session的持久化,讓做了修改的用戶首先看到修改的內容,其他的用戶可以等待Slave更新後再查看新內容。

      對於某些數據,可以用memcached來存放數據的版本號,讀Slave的程序可以先對比Slave的數據和memcached數據的版本,如果不一致則去讀master。用戶和博客類的信息可以用這種方法。在查詢前可以通過SHOW SLAVE STATUS檢測Slave的狀態,然後根據返回的結果進行服務器的選擇。

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