用於複製的來源與目標資料表不必完全相同。來源上的資料表可以比副本的資料表副本有更多或更少的欄。此外,在符合特定條件的情況下,來源與副本上對應的資料表欄可以使用不同的資料類型。
不支援以不同方式分割的資料表之間的複製。請參閱第 19.5.1.25 節,〈複製與分割〉。
在來源與目標資料表具有不同定義的所有情況下,資料庫和資料表名稱在來源與副本上必須相同。以下兩個章節將討論其他條件,並提供範例。
您可以將資料表從來源複製到副本,使資料表的來源與副本副本具有不同數量的欄,但須符合以下條件:
資料表兩個版本共有的欄必須在來源與副本上以相同順序定義。(即使兩個資料表具有相同數量的欄,情況也是如此。)
資料表兩個版本共有的欄必須在任何其他欄之前定義。
這表示在副本上執行
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,來源上該欄位的任何成功插入也應該在副本上成功,因為不可能有大到超出 BIGINT 欄位的合法 TINYINT 值。
基於列的複製:屬性提升和降級。 基於列的複製支援較小資料類型和較大類型之間的屬性提升和降級。也可以指定是否允許降級欄位值的有損(截斷)或無損轉換,如本節稍後所述。
有損和無損轉換。 如果目標類型無法表示要插入的值,則必須決定如何處理轉換。如果我們允許轉換,但截斷(或以其他方式修改)來源值以在目標欄位中實現「符合」,則我們會進行所謂的有損轉換。不需要截斷或類似修改,以使目標欄位中的來源欄位值符合的轉換是無損轉換。
類型轉換模式。 系統變數 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.25.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')
不允許在先前清單中未列出的類型之間進行轉換。