暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

17.4.1.9 Replication with Differing Table Definitions on Master and Slave

原创 由迪 2020-04-02
1046

复制的源表和目标表不必相同。主服务器上的表可以具有比从服务器的表更多或更少的列。此外,在某些条件下,主服务器和从服务器上的相应表列可以使用不同的数据类型。

注意
不支持在分区彼此不同的表之间进行复制。请参见 第17.4.1.23节“复制和分区”。

在源表和目标表没有相同定义的所有情况下,主数据库和从数据库上的数据库和表名称必须相同。在以下两个部分中,将通过示例讨论其他条件。

17.4.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在从属服务器 上允许使用前一个,因为在这两个版本的表中相同的列 c1,c2和 ,在任何不同的列之前,都在表的两个版本中分组在一起。 c3t

但是,以下ALTER TABLE语句不能在从属服务器上执行而不会导致复制中断:

ALTER TABLE t ADD COLUMN cnew2 INT AFTER c2;
在ALTER TABLE刚刚显示的语句的从属服务器上执行之后,复制失败 ,因为新列cnew2 位于两个版本的通用列之间 t。

该表版本中的 每个具有更多列的“ 额外 ”列都必须具有默认值。

列的默认值由许多因素决定,包括其类型,是否用DEFAULT选项定义 ,是否声明为NULL以及创建时有效的服务器SQL模式。有关更多信息,请参见第11.5节“数据类型默认值”)。

另外,当表的从属副本比主副本具有更多列时,表公用的每一列在两个表中必须使用相同的数据类型。

例子。 以下示例说明了一些有效和无效的表定义:

关于母版的更多专栏。 下表定义有效并且可以正确复制:

master> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
slave> CREATE TABLE t1 (c1 INT, c2 INT);
下表定义将引发错误,因为该表的两个版本共同的列定义在从属服务器上的顺序与主服务器上的顺序不同:

master> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
slave> CREATE TABLE t1 (c2 INT, c1 INT);
下列表定义也会引发错误,因为主表上多余的列的定义出现在该表的两个版本共同的列的定义之前:

master> CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);
slave> CREATE TABLE t1 (c1 INT, c2 INT);
从属上有更多列。 下表定义有效并且可以正确复制:

master> CREATE TABLE t1 (c1 INT, c2 INT);
slave> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
以下定义引起错误,因为在主表和从表上,表的两个版本的公共列未按相同的顺序定义:

master> CREATE TABLE t1 (c1 INT, c2 INT);
slave> CREATE TABLE t1 (c2 INT, c1 INT, c3 INT);
下列表定义也会引发错误,因为从表的版本中的额外列的定义出现在表的两个版本所共有的列的定义之前:

master> CREATE TABLE t1 (c1 INT, c2 INT);
slave> CREATE TABLE t1 (c3 INT, c1 INT, c2 INT);
以下表定义失败,因为表的从属版本比主版本具有更多列,并且表的两个版本对公共列使用不同的数据类型 c2:

master> CREATE TABLE t1 (c1 INT, c2 BIGINT);
slave> CREATE TABLE t1 (c1 INT, c2 INT, c3 INT);
17.4.1.9.2复制具有不同数据类型的列
理想情况下,同一表的主副本和从属副本上的对应列应具有相同的数据类型。但是,从MySQL 5.1.21开始,只要满足某些条件,就并不总是严格执行此要求。

在所有其他条件相同的情况下,始终可以从给定数据类型的列复制到相同类型和相同大小或宽度(如果适用或更大)的另一列。例如,您可以从一CHAR(10)列复制到另一列 CHAR(10),或从一 CHAR(10)列复制 到一 CHAR(25)列而没有任何问题。在某些情况下,还可以从一种数据类型的列(在主数据库上)复制到另一种数据类型的列(在从属数据库上)。当列的主版本的数据类型在从属上提升为相同大小或更大的类型时,这称为 属性提升。

属性升级可与基于语句的复制和基于行的复制一起使用,并且不依赖于主服务器或从服务器使用的存储引擎。但是,日志记录格式的选择确实会影响允许的类型转换。详细信息将在本节后面讨论。

重要
无论您使用基于语句的复制还是基于行的复制,如果希望使用属性提升,表的从属副本都不能包含比主副本多的列。

基于语句的复制。 使用基于语句的复制时,遵循的一条简单经验法则是:“ 如果在主服务器上运行的语句也将在从服务器上成功执行,那么它也应成功复制 ”。换句话说,如果该语句使用的值与从属服务器上给定列的类型兼容,则可以复制该语句。例如,您也可以将适合TINYINT列的任何值插入到 BIGINT列中。因此,即使您TINYINT 将从属表的副本中的列类型更改为 BIGINT,成功插入主节点上该列的任何内容也应在从属节点上成功,因为不可能有TINYINT足够大的合法 值来超过一BIGINT列。

在MySQL 5.6.10之前,使用基于语句的复制时, AUTO_INCREMENT要求主服务器和从服务器上的列都相同。否则,更新可能会应用于从属服务器上的错误表。(缺陷号12669186)

基于行的复制:属性提升和降级。 MySQL 5.6中基于行的复制支持较小数据类型和较大类型之间的属性提升和降级。也可以指定是否允许降级的列值进行有损(截断)或无损转换,如本节后面所述。

有损和无损转换。 如果目标类型不能代表要插入的值,则必须决定如何处理转换。如果我们允许转换但截断(或以其他方式修改)源值以在目标列中实现 “ 拟合 ”,那么我们进行所谓的有损转换。不需要截断或类似修改即可将源列值适合目标列的转换是 无损转换。

类型转换模式(slave_type_conversions变量)。 slave_type_conversions 全局服务器变量 的设置控制从服务器上使用的类型转换模式。该变量采用下表中的一组值,该表显示了每种模式对从站的类型转换行为的影响:
image.png

提升整数类型时,不会保留其有符号性。默认情况下,从站将所有此类值视为带符号。从MySQL 5.6.13开始,你可以控制使用这一行为ALL_SIGNED, ALL_UNSIGNED或两者兼而有之。(Bug#15831300) ALL_SIGNED告诉从站将所有提升的整数类型都视为带符号; ALL_UNSIGNED指示其将这些视为未签名。同时指定两者会使从属设备将值视为有符号,否则将其视为无符号。列出的顺序并不重要。如果其中至少之一或未 使用,也 ALL_SIGNED不会 ALL_UNSIGNED产生任何影响。 ALL_LOSSYALL_NONLOSSY

更改类型转换模式需要使用新slave_type_conversions 设置重新启动从站。

支持的转换。 下表显示了不同但相似的数据类型之间受支持的转换:

之间的任意整数类型的 TINYINT, SMALLINT, MEDIUMINT, INT,和 BIGINT。

这包括这些类型的带符号和无符号版本之间的转换。

通过将源值截断为目标列允许的最大值(或最小值)来进行有损转换。为了确保从无符号类型转换为带符号类型时的无损转换,目标列必须足够大以容纳源列中的值范围。例如,您可以TINYINT UNSIGNED无损地降级为 SMALLINT,但不能降级为 TINYINT。

之间的任何小数类型 DECIMAL, FLOAT, DOUBLE,和 NUMERIC。

FLOATto DOUBLE是无损转换;DOUBLE到 FLOAT只能有损地处理。从 到 where 和的 转换 是无损的;对于其中任何情况下 , 或两者,仅有损转换可。 DECIMAL(M,D)DECIMAL(M’,D’)D’ >= D(M’-D’) >= (M-DM’ < MD’ < D

对于任何十进制类型,如果要存储的值不能适合目标类型,则该值将根据文档中其他位置为服务器定义的舍入规则进行舍入。有关如何对十进制类型执行此操作的信息,请参见 第12.21.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个尺寸的任意2 列之间。

将 列中 的值插入 列中时,,列的最高有效位 被清除(设置为零),并且该值的 位 被设置为该 列的最低有效位 。 BIT(M)BIT(M’)M’ > MBIT(M’)MBIT(M)BIT(M’)

当将值从源 列插入目标 列时,其中 分配了该列的最大可能值 ;换句话说, “ all-set ”值分配给目标列。 BIT(M)BIT(M’)M’ < MBIT(M’)

不允许在上一个列表以外的类型之间进行转换。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论