用于复制的源表和目标表不必相同。源上的表可以比副本的表拥有更多或更少的列。此外,源和副本上对应的表列可以使用不同的数据类型,这取决于某些条件。
不支持在不同分区的表之间进行复制。看到17.5.1.24节,“复制和分区”.
在所有源表和目标表没有相同定义的情况下,源表和副本上的数据库和表名必须相同。在接下来的两节中,我们将通过示例讨论其他条件。
你可以将一个表从源复制到副本,这样表的源副本和副本副本有不同的列数,但要满足以下条件:
表的两个版本的公共列必须在源和副本上以相同的顺序定义。(即使两个表的列数相同也是如此。)
表的两个版本的公共列必须在任何其他列之前定义。
这意味着执行
ALTER TABLE
如果在两个表共有的列范围内插入一个新列,则会导致复制失败,示例如下:假设有一张表
t
,存在于源和副本上,由以下定义创建表
声明:创建表t (c1 INT, c2 INT, c3 INT);
假设
ALTER TABLE
语句在副本上执行:在表中添加cnew1列
前面的
ALTER TABLE
被允许在副本上,因为列c1
,c2
,c3
对于两个版本的表都是通用的t
在两个版本的表中,在任何不同的列之前保持分组。然而,以下情况
ALTER TABLE
语句不能在不导致复制中断的情况下在副本上执行:为表添加cnew2列
对象的副本上执行复制后,复制失败
ALTER TABLE
语句,因为新列cnew2
的两个版本的公共列之间t
.每一个”额外的”具有更多列的表版本中的列必须具有默认值。
列的默认值由许多因素决定,包括它的类型、是否使用
默认的
选项,是否声明为零
,以及创建时有效的服务器SQL模式;有关更多信息,请参见第11.6节,“数据类型默认值”).
此外,当表的副本的列比源副本的列多时,表的每个公共列必须在两个表中使用相同的数据类型。
的例子。下面的例子说明了一些有效和无效的表定义:
关于源代码的更多列。以下表定义有效且复制正确:
创建表t1 (c1 INT, c2 INT, c3 INT);CREATE TABLE t1 (c1 INT, c2 INT);
下面的表定义将引发错误,因为两个版本的表的公共列的定义在副本上的顺序与在源上的顺序不同:
创建表t1 (c1 INT, c2 INT, c3 INT);CREATE TABLE t1 (c2 INT, c1 INT);
下面的表定义也会引发错误,因为源上额外列的定义出现在两个版本表的公共列的定义之前:
创建表t1 (c3 INT, c1 INT, c2 INT);CREATE TABLE t1 (c1 INT, c2 INT);
关于副本的更多列。以下表定义有效且复制正确:
创建表t1 (c1 INT, c2 INT);创建表t1 (c1 INT, c2 INT, c3 INT);
以下定义将引发错误,因为表的两个版本的公共列在源和副本上定义的顺序不同:
创建表t1 (c1 INT, c2 INT);CREATE TABLE t1 (c2 INT, c1 INT, c3 INT);
下面的表定义也会引发错误,因为在副本版本的表中,额外列的定义出现在两个版本的表的公共列的定义之前:
创建表t1 (c1 INT, c2 INT);CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);
下面的表定义会失败,因为与源版本相比,表的副本版本有额外的列,并且表的两个版本对公共列使用不同的数据类型c2
:
创建表t1 (c1 INT, c2 BIGINT);创建表t1 (c1 INT, c2 INT, c3 INT);
理想情况下,同一表的源副本和副本副本上的对应列应该具有相同的数据类型。然而,只要满足某些条件,这并不总是严格执行的。
通常可以将给定数据类型的列复制到具有相同类型、相同大小或宽度(如果适用)或更大的另一列。例如,您可以从CHAR (10)
列到另一列CHAR (10)
,或从CHAR (10)
列到CHAR (25)
列没有任何问题。在某些情况下,还可以从具有一种数据类型的列(在源上)复制到具有不同数据类型的列(在副本上);当源版本的列的数据类型提升为副本上相同大小或更大的类型时,这称为属性提升.
属性提升既可以与基于语句的复制一起使用,也可以与基于行的复制一起使用,并且不依赖于源或副本使用的存储引擎。然而,日志格式的选择确实对允许的类型转换有影响;细节将在本节后面讨论。
无论使用基于语句的复制还是基于行的复制,如果希望使用属性提升,表的副本副本不能包含比源副本更多的列。
Statement-based复制。当使用基于语句的复制时,一个简单的经验法则是:”如果在源上运行的语句也会在副本上成功执行,那么它也应该成功复制”.换句话说,如果语句使用的值与副本上给定列的类型兼容,则语句可以被复制。类型中的任意值都可以插入非常小的整数
列成长整型数字
专栏也是;即使你改变了a的类型非常小的整数
列中的表的副本长整型数字
,在源上成功插入到该列的任何插入在副本上也应该成功,因为不可能有合法的非常小的整数
值,该值大到足以超过长整型数字
列。
基于行的复制:属性提升和降级。基于行的复制支持在较小的数据类型和较大的数据类型之间提升和降级属性。还可以指定是否允许对降级列值进行有损(截断)或非有损转换,本节稍后将对此进行解释。
有损转换和非有损转换。如果目标类型不能表示插入的值,则必须决定如何处理转换。如果允许转换,但截断(或以其他方式修改)源值以实现”适合”在目标列中,我们创建已知的a有损的转换.不需要截断或类似修改以使源列值适合目标列的转换是无损耗转换。
类型转换模式。系统变量的全局值replica_type_conversions
(从MySQL 8.0.26)或slave_type_conversions
(在MySQL 8.0.26之前)控制副本上使用的类型转换模式。该变量从以下列表中获取一组值,该列表描述了每种模式对副本类型转换行为的影响:
- ALL_LOSSY
-
在这种模式下,允许进行意味着信息丢失的类型转换。
这并不意味着允许非有损转换,仅仅是只允许需要有损转换或根本不需要转换的情况;例如,启用只有此模式允许
INT
要转换为的列非常小的整数
(有损转换),但不是非常小的整数
列到INT
列(无损耗)。在这种情况下,尝试后一种转换将导致复制停止,并在副本上出现错误。 - ALL_NON_LOSSY
-
这种模式允许不需要截断或对源值进行其他特殊处理的转换;也就是说,它允许目标类型比源类型范围更广的转换。
设置此模式与是否允许有损转换无关;这是由
ALL_LOSSY
模式。如果只有ALL_NON_LOSSY
是确定的,但不是ALL_LOSSY
,然后尝试将导致数据丢失的转换(例如INT
来非常小的整数
,或CHAR (25)
来VARCHAR (20)
)导致副本停止并报错。 - ALL_LOSSY, ALL_NON_LOSSY
-
当设置此模式时,允许所有受支持的类型转换,无论它们是否是有损转换。
- ALL_SIGNED
-
将提升的整数类型视为有符号值(默认行为)。
- ALL_UNSIGNED
-
将提升的整数类型视为无符号值。
- ALL_SIGNED, ALL_UNSIGNED
-
如果可能,将提升的整数类型处理为有符号,否则为无符号。
- [空]
-
当
replica_type_conversions
或slave_type_conversions
未设置,不允许属性提升或降级;这意味着源表和目标表中的所有列必须具有相同的类型。该模式为默认模式。
提升整数类型时,不会保留其符号性。默认情况下,副本将所有这些值视为有符号值。您可以使用ALL_SIGNED
,ALL_UNSIGNED
,或者两者都有。ALL_SIGNED
告诉副本将所有提升的整数类型视为有符号的;ALL_UNSIGNED
指示它将这些参数视为unsigned。如果可能的话,指定两者会使副本将该值视为有符号值,否则将其视为无符号值;它们的排列顺序并不重要。既不ALL_SIGNED
也不ALL_UNSIGNED
有什么影响,如果至少一个ALL_LOSSY
或ALL_NONLOSSY
也不使用。
更改类型转换模式需要使用new重新启动副本replica_type_conversions
或slave_type_conversions
设置。
支持转换。支持的不同但相似的数据类型之间的转换如下表所示:
在任何整数类型之间
非常小的整数
,短整型
,MEDIUMINT
,INT
,长整型数字
.这包括这些类型的有符号版本和无符号版本之间的转换。
有损转换是通过将源值截断为目标列允许的最大值(或最小值)来实现的。为了确保从无符号类型到有符号类型的非有损转换,目标列必须足够大,以容纳源列中的值范围。例如,你可以降级
非常小的整数无符号
无损耗,短整型
,但不是非常小的整数
.浮动
来双
是一个非有损转换;双
来浮动
只能胡乱处理。从小数(
来米
,D
)小数(
在哪里米的
,D '
)
而且D '
> =D
(
)是非有损的;在任何情况下米的
-D '
) >= (米
-D
,米的
<米
,或者两者都有,只能进行有损转换。D '
<D
对于任何十进制类型,如果要存储的值不适合目标类型,则根据文档中为服务器定义的舍入规则向下舍入。10bet官方网站看到第12.25.4节“舍入行为”,以了解如何对十进制类型执行此操作。
在任何字符串类型之间
字符
,VARCHAR
,文本
,包括不同宽度之间的转换。转换
字符
,VARCHAR
,或文本
到一个字符
,VARCHAR
,或文本
相同大小或更大的列永远不会有损耗。有损转换通过只插入第一个来处理N
副本上字符串的字符,其中N
目标列的宽度。重要的不支持使用不同字符集的列之间的复制。
在任何二进制数据类型之间
二进制
,VARBINARY
,团
,包括不同宽度之间的转换。转换
二进制
,VARBINARY
,或团
到一个二进制
,VARBINARY
,或团
相同大小或更大的列永远不会有损耗。有损转换通过只插入第一个来处理N
副本上字符串的字节数,其中N
目标列的宽度。在任意2之间
位
任意2个大小的列。的值插入时
位(
列成米
)位(
列,米的
)
的最重要的位米的
>米
位(
列被清除(设置为零)米的
)米
一些位(
属性的最低有效位米
)位(
列。米的
)当从源插入值时
位(
列到目标中米
)位(
列,米的
)
的最大可能值米的
<米
位(
列被赋值;换句话说,an”都准备好了”值赋给目标列。米的
)
不允许在前面列表之外的类型之间进行转换。