用於複製的來源和目標資料表不必完全相同。來源上的資料表可以比副本的資料表副本具有更多或更少的欄。此外,在滿足某些條件的情況下,來源和副本上的對應資料表欄可以使用不同的資料類型。
不支援在彼此分割方式不同的資料表之間進行複製。請參閱第 19.5.1.24 節,「複製與分割」。
在來源和目標資料表定義不完全相同的所有情況下,資料庫和資料表名稱在來源和副本上必須相同。以下兩節將討論其他條件,並提供範例。
您可以將資料表從來源複製到副本,使資料表的來源和副本副本具有不同數量的欄,但必須符合以下條件
兩個版本的資料表通用的欄必須在來源和副本上以相同的順序定義。(即使兩個資料表具有相同數量的欄,情況也是如此。)
兩個版本的資料表通用的欄必須在任何其他欄之前定義。
這表示在複本上執行
ALTER TABLE陳述式,將新欄位插入到兩表格共有的欄位範圍內,會導致複寫失敗,如下列範例所示:假設在來源和複本上都存在的表格
t是由以下CREATE TABLE陳述式所定義:CREATE TABLE t ( c1 INT, c2 INT, c3 INT );假設在複本上執行此處顯示的
ALTER TABLE陳述式:ALTER TABLE t ADD COLUMN cnew1 INT AFTER c3;先前的
ALTER TABLE陳述式在複本上是允許的,因為表格t兩個版本中共同的欄位c1、c2和c3,在任何不同的欄位之前,在兩個版本的表格中都保持分組在一起。然而,以下
ALTER TABLE陳述式在複本上執行時會導致複寫中斷:ALTER TABLE t ADD COLUMN cnew2 INT AFTER c2;在複本上執行剛才顯示的
ALTER TABLE陳述式後,複寫會失敗,因為新欄位cnew2出現在t兩個版本共有的欄位之間。表格中具有較多欄位的版本中,每個「額外」欄位都必須有一個預設值。
欄位的預設值取決於多個因素,包括其類型、是否使用
DEFAULT選項定義、是否宣告為NULL,以及建立時生效的伺服器 SQL 模式;如需更多資訊,請參閱 第 13.6 節,「資料類型預設值」)。
此外,當複本的表格副本比來源的表格副本具有更多欄位時,表格共有的每個欄位在兩個表格中都必須使用相同的資料類型。
範例。 以下範例說明一些有效和無效的表格定義:
來源上有更多欄位。 以下表格定義是有效的且可以正確複寫:
source> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
replica> CREATE TABLE t1 (c1 INT, c2 INT);以下表格定義會引發錯誤,因為表格兩個版本共有的欄位定義在複本上的順序與來源上的順序不同:
source> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
replica> CREATE TABLE t1 (c2 INT, c1 INT);以下表格定義也會引發錯誤,因為來源上的額外欄位定義出現在表格兩個版本共有的欄位定義之前:
source> CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);
replica> CREATE TABLE t1 (c1 INT, c2 INT);複本上有更多欄位。 以下表格定義是有效的且可以正確複寫:
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);以下定義會引發錯誤,因為表格兩個版本共有的欄位在來源和複本上未以相同的順序定義:
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica> CREATE TABLE t1 (c2 INT, c1 INT, c3 INT);以下表格定義也會引發錯誤,因為複本表格版本中的額外欄位定義出現在表格兩個版本共有的欄位定義之前:
source> CREATE TABLE t1 (c1 INT, c2 INT);
replica> CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);以下表格定義失敗,因為與來源版本相比,複本的表格版本有額外欄位,且表格的兩個版本對共同欄位 c2 使用不同的資料類型:
source> CREATE TABLE t1 (c1 INT, c2 BIGINT);
replica> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
來源和複本上相同表格的對應欄位,理想情況下應該具有相同的資料類型。然而,只要滿足某些條件,這並非總是嚴格執行。
通常可以將給定資料類型的欄位複寫到另一個相同類型且相同大小或寬度(如果適用)或更大的欄位。例如,您可以將 CHAR(10) 欄位複寫到另一個 CHAR(10),或將 CHAR(10) 欄位複寫到 CHAR(25) 欄位,而不會有任何問題。在某些情況下,也可以將具有一種資料類型(在來源上)的欄位複寫到具有不同資料類型(在複本上)的欄位;當來源版本的欄位資料類型提升到複本上相同或更大的類型時,這稱為屬性提升。
屬性提升可用於基於陳述式和基於列的複寫,且不依賴於來源或複本使用的儲存引擎。但是,記錄格式的選擇確實會影響允許的類型轉換;本節稍後會討論具體細節。
無論您使用基於陳述式還是基於列的複寫,如果您希望使用屬性提升,則複本的表格副本不能包含比來源副本更多的欄位。
基於陳述式的複寫。 當使用基於陳述式的複寫時,一個簡單的經驗法則是:「如果在來源上執行的陳述式也能在複本上成功執行,則應該也能成功複寫」。換句話說,如果陳述式使用的值與複本上給定欄位的類型相容,則可以複寫該陳述式。例如,您可以將任何適合 TINYINT 欄位的值插入到 BIGINT 欄位;因此,即使您將複本表格副本中的 TINYINT 欄位類型變更為 BIGINT,來源上任何對該欄位成功的插入也應該在複本上成功,因為不可能有合法的 TINYINT 值大到足以超出 BIGINT 欄位。
基於列的複寫:屬性提升和降級。 基於列的複寫支援在較小的資料類型和較大的類型之間進行屬性提升和降級。也可以指定是否允許降級欄位值的有損(截斷)或無損轉換,如本節稍後解釋。
有損和無損轉換。 如果目標類型無法表示要插入的值,則必須決定如何處理轉換。如果我們允許轉換,但截斷(或以其他方式修改)來源值以在目標欄位中實現「適合」,則我們進行所謂的有損轉換。不需要截斷或類似修改即可將來源欄位值放入目標欄位的轉換是無損轉換。
類型轉換模式。 系統變數 replica_type_conversions 的全域值控制複本上使用的類型轉換模式。此變數從以下清單中取得一組值,該清單描述了每個模式對複本類型轉換行為的影響:
- ALL_LOSSY
在此模式下,允許導致資訊遺失的類型轉換。
這並不表示允許無損轉換,僅表示僅允許需要有損轉換或根本不需要轉換的情況;例如,僅 啟用此模式允許將
INT欄位轉換為TINYINT(有損轉換),但不允許將TINYINT欄位轉換為INT欄位(無損轉換)。在此情況下嘗試後者轉換會導致複寫停止並在複本上產生錯誤。- ALL_NON_LOSSY
此模式允許不需要截斷或對來源值進行其他特殊處理的轉換;也就是說,它允許目標類型具有比來源類型更廣泛範圍的轉換。
設定此模式與是否允許有損轉換無關;這由
ALL_LOSSY模式控制。如果僅設定ALL_NON_LOSSY,但未設定ALL_LOSSY,則嘗試導致資料遺失的轉換(例如INT到TINYINT,或CHAR(25)到VARCHAR(20))會導致複本停止並產生錯誤。- ALL_LOSSY,ALL_NON_LOSSY
當設定此模式時,允許所有支援的類型轉換,無論它們是否為有損轉換。
- ALL_SIGNED
將提升的整數類型視為帶正負號的值(預設行為)。
- ALL_UNSIGNED
將提升的整數類型視為不帶正負號的值。
- ALL_SIGNED,ALL_UNSIGNED
如果可能,將提升的整數類型視為帶正負號,否則視為不帶正負號。
- [空白]
當未設定
replica_type_conversions時,不允許任何屬性提升或降級;這表示來源和目標表格中的所有欄位都必須屬於相同類型。此模式為預設模式。
當提升整數類型時,其正負號不會保留。預設情況下,複本將所有此類值視為帶正負號。您可以使用 ALL_SIGNED、ALL_UNSIGNED 或兩者來控制此行為。ALL_SIGNED 告訴複本將所有提升的整數類型視為帶正負號;ALL_UNSIGNED 指示它將這些類型視為不帶正負號。指定兩者會導致複本在可能的情況下將值視為帶正負號,否則將其視為不帶正負號;它們列出的順序並不重要。如果未使用 ALL_LOSSY 或 ALL_NONLOSSY 中的至少一個,則 ALL_SIGNED 和 ALL_UNSIGNED 都不會產生任何影響。
變更類型轉換模式需要使用新的 replica_type_conversions 設定重新啟動複本。
支援的轉換。 以下清單顯示了不同但相似的資料類型之間支援的轉換:
在任何整數類型
TINYINT、SMALLINT、MEDIUMINT、INT和BIGINT之間。這包括這些類型的帶正負號和不帶正負號版本之間的轉換。
有損轉換是透過將來源值截斷為目標欄位允許的最大值(或最小值)來進行的。為了確保從不帶正負號類型轉換為帶正負號類型時的無損轉換,目標欄位必須足夠大,才能容納來源欄位中的值範圍。例如,您可以將
TINYINT UNSIGNED無損降級為SMALLINT,但不能降級為TINYINT。在任何小數類型
DECIMAL、FLOAT、DOUBLE和NUMERIC之間。從
FLOAT轉換為DOUBLE是無損轉換;從DOUBLE轉換為FLOAT則只能以有損方式處理。 從DECIMAL(轉換為M,D)DECIMAL(,其中M',D')且D'>=D() 為無損轉換;若任何情況M'-D') >= (M-D、M'<M或兩者皆是,則只能進行有損轉換。D'<D對於任何小數類型,如果要儲存的值無法放入目標類型,則該值會根據伺服器文件中其他地方定義的捨入規則捨入。有關小數類型如何進行捨入的資訊,請參閱第 14.24.4 節,「捨入行為」。
在任何字串類型
CHAR、VARCHAR和TEXT之間,包括不同寬度之間的轉換。將
CHAR、VARCHAR或TEXT轉換為相同或較大尺寸的CHAR、VARCHAR或TEXT資料行永遠不會是無損的。有損轉換的處理方式是在副本上僅插入字串的前N個字元,其中N是目標資料行的寬度。重要事項不支援使用不同字元集的資料行之間的複寫。
在任何二進位資料類型
BINARY、VARBINARY和BLOB之間,包括不同寬度之間的轉換。將
BINARY、VARBINARY或BLOB轉換為相同或較大尺寸的BINARY、VARBINARY或BLOB資料行永遠不會是無損的。有損轉換的處理方式是在副本上僅插入字串的前N個位元組,其中N是目標資料行的寬度。在任何 2 個任意大小的
BIT資料行之間。當將值從
BIT(資料行插入到M)BIT(資料行時,其中M'),M'>MBIT(資料行的最高有效位元會被清除(設定為零),而M')BIT(值的M)M位元會設定為BIT(資料行的最低有效位元。M')當將值從來源
BIT(資料行插入到目標M)BIT(資料行時,其中M'),會為M'<MBIT(資料行指定最大可能值;換句話說,會為目標資料行指定一個「全設定」值。M')
不允許進行前述清單中未包含的類型之間的轉換。