top
Loading...
6.7.復制特性和已知問題
6.7. 復制特性和已知問題

一般原則,SQL級復制兼容性要求主服務器和從服務器均支持使用的特性。例如,在MySQL 5.0.0中開始使用TIMESTAMPADD()函數。如果在主服務器上使用該函數,不能復制到MySQL 5.0.0之前的從服務器。如果你計劃在5.1和以前版本的MySQL之間進行復制,你應查閱對應以前版本系列的MySQL參考手冊,查詢該系列復制特征相關信息。

下面列出了關于支持什么和不支持什么的詳細信息。關于復制的其它InnoDB具體信息參見15.2.6.5節,“InnoDB和MySQL復制”。

關于保存的程序和觸發器的復制問題在20.4節,“存儲子程序和觸發程序的二進制日志功能”中討論。

·         AUTO_INCREMENTLAST_INSERT_ID()TIMESTAMP值正確實現復制。

·         USER()UUID()LOAD_FILE()函數毫無改變地被,這樣不能可靠地在從服務器上工作。

·         下面的限制只適合基于語句的復制,而不是基于行的復制。處理用戶級鎖定的函數GET_LOCK()RELEASE_LOCK()IS_FREE_LOCK()IS_USED_LOCK()復制時從服務器不知道在主服務器上同時進行的相關文本;因此如果從服務器上的內容不同,這些函數不用來插入到主服務器的表中(例如不執行INSERT INTO mytable VALUES(GET_LOCK(...)))

·         MySQL 5.1FOREIGN_KEY_CHECKSSQL_MODEUNIQUE_CHECKSSQL_AUTO_IS_NULL變量均復制。但TABLE_TYPE,即STORAGE_ENGINE變量 不復制,有利于在不同的存儲引擎之間進行復制。

·         即使主服務器和從服務器有不同的全局字符集變量,以及即使有不同的全局時區變量仍可以復制。

·         下面適合使用不同字符集的MySQL服務器之間的復制:

1.    必須在主服務器和從服務器上總是使用相同的全局字符集和校對規則(--default-character-set--default-collation)。否則,會在從服務器上遇到復制鍵值錯誤,因為在主服務器的字符集中被認為是唯一的鍵值在從服務器的字符集中可能不是唯一的。

2.    如果主服務器早于MySQL 4.1.3,則會話中的字符集不應與其全局值不同(換句話說,不要使用SET NAMESSET CHARACTER SET等等),因為從服務器不知道該字符集的更改。如果主服務器和從服務器均為4.1.3或更新版,可以隨便將會話的字符集變量設置為本地值(例如NAMESCHARACTER SETCOLLATION_CLIENTCOLLATION_SERVER),因為這些設定值被寫入二進制日志,因此從服務器知道。然而,禁止更改會話中這些變量的全局值;如前面所述,主服務器和從服務器必須具有唯一的全局字符集值。

3.    如果在主服務器上的數據庫的字符集與全局collation_server值不同,則應設計CREATE TABLE語句,以便它們不隱含依賴數據庫的默認字符集(Bug #2326);一個好的解決辦法是在CREATE TABLE中明顯說明字符集和校對規則。

·         應在主服務器和從服務器上設置相同的系統時區。否則一些語句,例如使用NOW()FROM_UNIXTIME()函數的語句,將不會正確復制。可以使用腳本mysqld_safe--timezone=timezone_name選項或通過設置TZ環境變量設置MySQL服務器運行的系統的時區。主服務器和從服務器還應有相同的默認連接時區設置;即主服務器和從服務器應有相同的--default-time-zone參數值。

·         CONVERT_TZ(...,...,@global.time_zone)不能正確復制。只有主服務器和從服務器均為5.0.4或更新版才能正確復制CONVERT_TZ(...,...,@session.time_zone)

·         會話變量只有在更新表的語句中使用時才能正確復制;例如:SET MAX_JOIN_SIZE=1000INSERT INTO mytable VALUES(@MAX_JOIN_SIZE)不能將相同的數據插入到主服務器上和從服務器上。不適用于通用的SET TIME_ZONE=...INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone))

·         可以將從服務器上的非事務表復為主服務器上的事務表。例如,可以將主服務器上的InnoDB表復制為從服務器上的MyISAM表。然而,復制過程中,如果從服務器在BEGIN/COMMIT塊過程中停止則會產生問題,因為從服務器在BEGIN塊開始時會重啟。該問題出現在TODO中,不久將會得到修復。

·         MySQL 5.1中可以正確復制引用用戶變量(@var_name形式的變量)的更新語句;但在4.1以前的版本中卻不可能。請注意從MySQL 5.1開始對用戶變量名的大小寫不再敏感;當在5.1和舊版本之間設置復制時應考慮該問題。

·         從服務器可以使用SSL連接到主服務器。

·         有一個全局系統變量slave_transaction_retries:如果因為某個InnoDB死鎖或超過 InnoDBinnodb_lock_wait_timeoutNDB簇的TransactionDeadlockDetectionTimeoutTransactionInactiveTimeoutREPLICATION SLAVESQL線程未能執行某個事務,在給出錯誤停止前自動重試slave_transaction_retries次。 默認值是10。從MySQL 5.0.4開始,可以從SHOW STATUS的輸出中看到重試總次數;參見5.3.4節,“服務器狀態變量”。

·         如果在主服務器上的CREATE TABLE語句中使用了DATA DIRECTORYINDEX DIRECTORY子句,子句也可以在從服務器上使用。如果在從服務器主機文件系統中不存在一致的目錄或雖然存在但不能被從服務器訪問,則會帶來問題。MySQL 5.1支持一個稱為NO_DIR_IN_CREATEsql_mode選項。如果從服務器運行時將SQL模式設置為包括該選項,復制CREATE TABLE語句時將忽略這些子句。結果是在表的數據庫目錄中創建了MyISAM數據和索引文件。

·         下面的限制只適合基于語句的復制,而不是基于行的復制:如果在查詢中數據修改不確定,主服務器和從服務器上的數據可以不同;也就是由查詢優化器確定。(這是常用的但不是很好的習慣,即使不是在復制中也不好)關于該問題的詳細解釋,參見A.8.1節,“MySQL中的打開事宜”。

·         READ LOCKFLUSH LOGSFLUSH MASTERFLUSH SLAVEFLUSH TABLES不記入日志,因為如果復制到從服務器會造成問題。關于語法示例,參見13.5.5.2節,“FLUSH語法”。FLUSH TABLESANALYZE TABLEOPTIMIZE TABLEREPAIR TABLE語句被寫入二進制日志并會復制到從服務器。一般情況不會造成問題,因為這些語句不修改表的數據。但是在某些情況下會帶來問題。如果你復制mysql數據庫中的授權表并且不使用GRANT直接更新那些表,必須在從服務器上執行FLUSH PRIVILEGES使新的權限生效。并且,如果使用FLUSH TABLES重新命名MERGE表的MyISAM表,必須手動在從服務器上執行FLUSH TABLES。如果不指定NO_WRITE_TO_BINLOG或其別名LOCAL,則這些語句被寫入二進制日志。

·         MySQL只支持一個主服務器和多個從服務器。我們計劃將來添加一個投票算法,當前的主服務器出現問題時自動切換。我們還計劃引入代理過程通過向不同的從服務器發送SELECT查詢以幫助進行負載均衡。

·         當服務器關閉、重啟時,其MEMORY表將變為空。主服務器按下述方法復制該結果:啟動后第1次主服務器使用每個MEMORY表,它通知從服務器需要向表寫入DELETE FROM語句來清空二進制日志的表。詳細信息參見15.4節,“MEMORY (HEAP)存儲引擎”。

·         除了關閉從服務器(而不僅僅是從服務器線程) 臨時表都被復制,并且還沒有在從服務器上執行的更新所使用的臨時表也已經復制。如果關閉從服務器,從服務器重啟后更新需要的那些臨時表不可再用。為了避免該問題,臨時表打開時不要關閉從服務器。而應遵照下面的程序:

1.    執行STOP SLAVE語句。

2.    使用SHOW STATUS檢查slave_open_temp_tables變量的值。

3.    如果值為0,使用mysqladmin shutdown命令關閉從服務器。

4.    如果值不為0,用START SLAVE重啟從服務器線程。

5.    后面再重復該程序看下次的運氣是否好一些。

我們計劃在不久的將來修復該問題。

·         可以很安全地連接用--logs-slave-updates選項指定的循環主服務器/從服務器關系中的服務器。但請注意許多語句在這種設置中不能正確工作,除非你的客戶代碼關注了潛在的在不同的服務器不同順序的更新中可能發生的這類問題。

這說明你可以象這樣創建設置:

A -> B -> C -> A

服務器ID被編碼在二進制日志事件中,因此服務器A知道何時自己首次創建它讀取的事件并且不執行事件(除非用--replicate-same-server-id選項啟動了服務器A,只在很少情況下有意義)。這樣,沒有無限循環。只有對表執行沒有沖突的更新時該類循環設置才能工作。換句話說,如果在AC中插入數據,絕對不應在A中插入鍵值可能與插入到C中的行相沖突的一行。如果更新的順序很重要,還不應更新兩個服務器上相同的行。

·         如果從服務器上的某個語句產生錯誤,則從服務器上的SQL線程終止,并且從服務器向錯誤日志寫入一條消息。此時應手動連接從服務器,修復該問題(例如,一個不存在的表),然后運行START SLAVE

·         可以很安全地關閉主服務器并在以后重啟。如果某個從服務器丟失與主服務器的連接,從服務器嘗試立即重新連接。如果失敗,從服務器定期重試。(默認設置是每60秒重試一次。可以通過--master-connect-retry選項更改)從服務器也能夠處理網絡連接中斷。但是,只有從服務器超過slave_net_timeout秒沒有從主服務器收到數據才通知網絡中斷。如果中斷時間短,可以降低slave_net_timeout。參見5.3.3節,“服務器系統變量”。

·         關閉從服務器(凈關閉)也很安全,因為它可以跟蹤它離開的地點。不純凈的關閉操作會產生問題,特別是系統關閉前硬盤緩存未刷新到硬盤上時。如果有不間斷電源,可以大大提高系統容錯能力。不純凈的關閉主服務器會造成主服務器上的表和二進制日志內容之間的不一致性;在主服務器上使用InnoDB表和--innodb-safe-binlog選項可以避免該問題。參見5.11.3節,“二進制日志”。(注釋:MySQL 5.1中不需要--innodb-safe-binlog,由于引入了XA事務支持已經作廢了)

·         由于MyISAM表的非事務屬性,可以有一個語句只是更新一個表并返回錯誤代碼。例如,多行插入時有一個行超過鍵值約束,或者如果長的更新語句更新部分行后被殺掉了。如果發生在主服務器上,除非錯誤代碼合法并且語句執行產生相同的錯誤代碼,從服務器線程將退出并等待數據庫管理員決定如何做。如果該錯誤代碼驗證行為不理想,可以用--slave-skip-errors選項掩蓋(忽視)部分或全部錯誤。

·         如果從BEGIN/COMMIT系列的非事務表更新事務表,如果提交事務前更新非事務表,對二進制日志的更新可能會不同步。這是因為事務提交后才被寫入二進制日志。

·         事務混合更新事務表和非事務表時,二進制日志中語句的順序是正確的,即使在ROLLBACK時,所有需要的語句也會寫入二進制日志。但是如果在第1個連接的事務完成前,第2個連接更新非事務表,語句記入日志時會出現順序錯誤,因為第2個連接的更新執行完后立即寫入日志,而不管第1個連接執行的事務的狀態如何。

作者:mysql.com
來源:http://dev.mysql.com/doc/refman/5.1/zh/replication.html
北斗有巢氏 有巢氏北斗