文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  來源與副本上具有不同資料表定義的複製

19.5.1.9 來源與副本上具有不同資料表定義的複製

用於複製的來源和目標資料表不必完全相同。來源上的資料表可以比副本的資料表副本具有更多或更少的欄。此外,在滿足某些條件的情況下,來源和副本上的對應資料表欄可以使用不同的資料類型。

注意

不支援在彼此分割方式不同的資料表之間進行複製。請參閱第 19.5.1.24 節,「複製與分割」

在來源和目標資料表定義不完全相同的所有情況下,資料庫和資料表名稱在來源和副本上必須相同。以下兩節將討論其他條件,並提供範例。

19.5.1.9.1 來源或副本上具有更多欄的複製

您可以將資料表從來源複製到副本,使資料表的來源和副本副本具有不同數量的欄,但必須符合以下條件

  • 兩個版本的資料表通用的欄必須在來源和副本上以相同的順序定義。(即使兩個資料表具有相同數量的欄,情況也是如此。)

  • 兩個版本的資料表通用的欄必須在任何其他欄之前定義。

    這表示在複本上執行 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 兩個版本中共同的欄位 c1c2c3,在任何不同的欄位之前,在兩個版本的表格中都保持分組在一起。

    然而,以下 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);
19.5.1.9.2 具有不同資料類型的欄位複寫

來源和複本上相同表格的對應欄位,理想情況下應該具有相同的資料類型。然而,只要滿足某些條件,這並非總是嚴格執行。

通常可以將給定資料類型的欄位複寫到另一個相同類型且相同大小或寬度(如果適用)或更大的欄位。例如,您可以將 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,則嘗試導致資料遺失的轉換(例如 INTTINYINT,或 CHAR(25)VARCHAR(20))會導致複本停止並產生錯誤。

ALL_LOSSY,ALL_NON_LOSSY

當設定此模式時,允許所有支援的類型轉換,無論它們是否為有損轉換。

ALL_SIGNED

將提升的整數類型視為帶正負號的值(預設行為)。

ALL_UNSIGNED

將提升的整數類型視為不帶正負號的值。

ALL_SIGNED,ALL_UNSIGNED

如果可能,將提升的整數類型視為帶正負號,否則視為不帶正負號。

[空白]

當未設定 replica_type_conversions 時,不允許任何屬性提升或降級;這表示來源和目標表格中的所有欄位都必須屬於相同類型。

此模式為預設模式。

當提升整數類型時,其正負號不會保留。預設情況下,複本將所有此類值視為帶正負號。您可以使用 ALL_SIGNEDALL_UNSIGNED 或兩者來控制此行為。ALL_SIGNED 告訴複本將所有提升的整數類型視為帶正負號;ALL_UNSIGNED 指示它將這些類型視為不帶正負號。指定兩者會導致複本在可能的情況下將值視為帶正負號,否則將其視為不帶正負號;它們列出的順序並不重要。如果未使用 ALL_LOSSYALL_NONLOSSY 中的至少一個,則 ALL_SIGNEDALL_UNSIGNED 都不會產生任何影響。

變更類型轉換模式需要使用新的 replica_type_conversions 設定重新啟動複本。

支援的轉換。 以下清單顯示了不同但相似的資料類型之間支援的轉換:

  • 在任何整數類型 TINYINTSMALLINTMEDIUMINTINTBIGINT 之間。

    這包括這些類型的帶正負號和不帶正負號版本之間的轉換。

    有損轉換是透過將來源值截斷為目標欄位允許的最大值(或最小值)來進行的。為了確保從不帶正負號類型轉換為帶正負號類型時的無損轉換,目標欄位必須足夠大,才能容納來源欄位中的值範圍。例如,您可以將 TINYINT UNSIGNED 無損降級為 SMALLINT,但不能降級為 TINYINT

  • 在任何小數類型 DECIMALFLOATDOUBLENUMERIC 之間。

    FLOAT 轉換為 DOUBLE 是無損轉換;從 DOUBLE 轉換為 FLOAT 則只能以有損方式處理。 從 DECIMAL(M,D) 轉換為 DECIMAL(M',D'),其中 D' >= D(M'-D') >= (M-D) 為無損轉換;若任何情況 M' < MD' < D 或兩者皆是,則只能進行有損轉換。

    對於任何小數類型,如果要儲存的值無法放入目標類型,則該值會根據伺服器文件中其他地方定義的捨入規則捨入。有關小數類型如何進行捨入的資訊,請參閱第 14.24.4 節,「捨入行為」

  • 在任何字串類型 CHARVARCHARTEXT 之間,包括不同寬度之間的轉換。

    CHARVARCHARTEXT 轉換為相同或較大尺寸的 CHARVARCHARTEXT 資料行永遠不會是無損的。有損轉換的處理方式是在副本上僅插入字串的前 N 個字元,其中 N 是目標資料行的寬度。

    重要事項

    不支援使用不同字元集的資料行之間的複寫。

  • 在任何二進位資料類型 BINARYVARBINARYBLOB 之間,包括不同寬度之間的轉換。

    BINARYVARBINARYBLOB 轉換為相同或較大尺寸的 BINARYVARBINARYBLOB 資料行永遠不會是無損的。有損轉換的處理方式是在副本上僅插入字串的前 N 個位元組,其中 N 是目標資料行的寬度。

  • 在任何 2 個任意大小的 BIT 資料行之間。

    當將值從 BIT(M) 資料行插入到 BIT(M') 資料行時,其中 M' > MBIT(M') 資料行的最高有效位元會被清除(設定為零),而 BIT(M) 值的 M 位元會設定為 BIT(M') 資料行的最低有效位元。

    當將值從來源 BIT(M) 資料行插入到目標 BIT(M') 資料行時,其中 M' < M,會為 BIT(M') 資料行指定最大可能值;換句話說,會為目標資料行指定一個全設定值。

不允許進行前述清單中未包含的類型之間的轉換。