1、简单介绍该错误发生的背景:

1) 数据库版本:MySQL5.7.19

2) 对一个大表修改字段类型DDL(将主键id int变为bigint),为了不影响主库业务,先在从库上执行DDL操作,然后通过主从切换完成最终的大表DDL;在从库执行完DDL后,这时发现复制中断了,报错信息:

Last_SQL_Errno: 1677
Last_SQL_Error: Column 0 of table 'darren.conversions' cannot be converted from type 'int' to type 'bigint(20)'

3)错误重现:

     在主库上,建表如下:

CREATE TABLE `conversions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB

 在从库上,修改字段类型,将id int 变成bigint:

alter table conversions modify id bigint not null;

最后在主库上向该表插入数据,这时从库就报1677错误了。

2、解决方案

参考MySQL文档中的方法,在从库上设置slave_type_conversions ="ALL_NON_LOSSY",重启复制即可解决

MySQL>  set global slave_type_conversions ='ALL_NON_LOSSY';
MySQL> stop slave;start slave;

3、关于该错误的详细介绍

【不同数据类型的主从复制】:正常情况下,主库和从库每个表的各个列数据类型都是一致的,但是MySQL并不强制这样。有些特殊情况下,是存在主从列数据类型不一致,比如上面的大表DDL操作,先在从库上修改,然后切换主从,最后再修改老主库的结构,当然,可能存在其他多种情况,不一一列举。

【属性升级和降级(attribute promotion and demotion)】:主从复制下,MySQL只支持同类小数据类型和较大类型之间的属性提升和降级,比如将主库上int在从库上转为bigint,视为属性升级,相反将bigint转为int就是属性降级。属性升降级可用于基于语句和基于行的复制格式,并且不依赖于存储引擎。但是,日志格式的选择对允许的类型转换有影响,这里主要讨论row格式。

【有损和无损转换(Lossy and non-lossy conversions)】:主从数据库同一表同一列数据类型不一致,会产生数据类型转换。为了符合和适应目标列类型,截断(或其他修改)源值,称为有损转换;不需要截断或类似的修改以适应目标列中的源列值的转换是一个非有损的转换。这两种转换模式主要由slave_type_conversions系统变量控制,该变量的值如下:

Mode 影响描述
ALL_LOSSY(有损转换) 该模式下,列类型转换允许丢失一些信息。如果只设置该模式,只允许同类的大数据类型转换为小数据类型,其他模式的转换都会发生1677错误。生产环境不建议设置该值,很容易导致主从不一致。
ALL_NON_LOSSY(无损转换) 该模式下,不会导致数据丢失和截断,因为该值只允许同类的小数据类型转换为大数据类型,其他模式的转换都会发生1677错误。生产环境建议设置该值
ALL_LOSSY,ALL_NON_LOSSY(两种情况并存) 上面两种模式都支持,生产环境不建议设置该值
[empty] (空值) 不设置任何值,表示不允许任何模式的类型转换,如果发现类型转换,都会产生1677错误,导致复制中断

4、测试

4-1、slave_type_conversions='ALL_LOSSY'

主库id是int类型,slave修改为bigint,当主库插入数据后,从库直接报错1677;当从库修改为tinyint,由于是ALL_LOSSY模式,从库数据被截断,这时主从数据是不一致的。

----------------------------------------当从库修改为bigint----------------------------------------------------------------------------
mysql> show global variables like 'slave_type_conversions';
+------------------------+-----------+
| Variable_name | Value |
+------------------------+-----------+
| slave_type_conversions | ALL_LOSSY |
+------------------------+-----------+
row in set (0.00 sec) mysql> show slave status\G
*************************** . row ***************************
Last_Errno: 1677 #直接报错了
Last_Error: Column of table 'darren.conversions' cannot be converted from type 'int' to type 'bigint(20)'

----------------------------------------当从库修改为tinyint----------------------------------------------------------------------------
master插入11111:
mysql> insert into conversions(id,name) values(,'a');
Query OK, row affected (0.00 sec) mysql>
mysql> select * from conversions;
+-------+------+
| id | name |
+-------+------+
| | a |
| | a |
+-------+------+ slave的值127:
mysql> select * from darren.conversions;
+-----+------+
| id | name |
+-----+------+
| | a |
| | a | #11111被截断为127
+-----+------+

     4-2、slave_type_conversions='ALL_NON_LOSSY'

slave> show global variables like 'slave_type_conversions';
+------------------------+---------------+
| Variable_name | Value |
+------------------------+---------------+
| slave_type_conversions | ALL_NON_LOSSY |
+------------------------+---------------+ slave> show create table conversions;
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| conversions | CREATE TABLE `conversions` (
`id` tinyint() NOT NULL AUTO_INCREMENT,
`name` char() NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8 |
+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ------------------------------------主库插入值-----------------------------
master> insert into conversions(id,name) values(,'a');
Query OK, row affected (0.01 sec) master> select * from conversions;
+-------+------+
| id | name |
+-------+------+
| | a |
| | a |
| | a |
+-------+------+ 从库报错了,因为ALL_NON_LOSSY 只支持小数据类型转为大数据类型
mysql> show slave status\G
*************************** . row ***************************
Last_Errno:
Last_Error: Column of table 'darren.conversions' cannot be converted from type 'int' to type 'tinyint(4)'

     4-3、slave_type_conversions=''

设置为空值,从库不支持任何的类型转换,直接报错。

 5、支持哪些类型转换?

5.1) 支持整型 TINYINTSMALLINTMEDIUMINTINT, and BIGINT之间任意两者转换

5.2) 支持浮点数 DECIMALFLOATDOUBLE, and NUMERIC之间任意两者转换

5.3) 支持 CHARVARCHAR, and TEXT之间任意两者转换

5.4) 支持BINARYVARBINARY, and BLOB之间任意两者转换

5.5) 支持bit之间转换

其他不在上述的都不支持转换。

【总结】设置空值是最严格的模式,不允许列类型不一致,如果发生不一致,从库复制就中断报错了,能够最大程度上维护主从数据一致性。

如果日常运维,如大表DDL需要在从库上进行的,可以先设置slave_type_conversions='ALL_NON_LOSSY',能够保证从库不会产生1677错误,但是对于整型字段,一定要注意主从unsigned或者signed问题,如果主库signed,从库上是unsigned,主从数据有可能不一致;当主库上unsigned,从库signed的,一定要保证从库字段足够大能存下主库字段值,否则也会导致数据不一致。

参考文档:https://dev.mysql.com/doc/refman/5.7/en/replication-features-differing-tables.html

【FAQ系列】关于SQL_Errno:1677导致主从复制中断的思考和实践的更多相关文章

  1. 【FAQ系列】Relay log 导致复制启动失败

    今天在使用冷备份文件重做从库时遇到一个报错,值得研究一下. 版本:MySQL5.6.27 一.报错现象 dba:(none)> start slave; ERROR (HY000): Slave ...

  2. FAQ系列 | 如何保证主从复制数据一致性(转)

    导读 MySQL主从复制环境中,如何才能保证主从数据的一致性呢? 关于主从复制 现在常用的MySQL高可用方案,十有八九是基于 MySQL的主从复制(replication)来设计的,包括常规的一主一 ...

  3. 如果是在有master上开启了该参数,记得在slave端也要开启这个参数(salve需要stop后再重新start),否则在master上创建函数会导致replaction中断。

    如果是在有master上开启了该参数,记得在slave端也要开启这个参数(salve需要stop后再重新start),否则在master上创建函数会导致replaction中断.

  4. OOM导致的备库raylog损坏导致主从复制异常

    问题发现告警数据库出现复制中断,延迟超过100秒 问题排查复制信息检查,通过’show slave status\G’命令可以查看复制线程详细的工作状态,对于判断复制中断的原因有一些指导性意义.当时的 ...

  5. cad.net 复制图元的时候按下多次esc导致复制中断的bug,令REGEN,REGENALL更新图元无效.

    浩辰没有这个bug !!!!!!! 如上述动图所示,cad在复制一个多图元的操作时候,多次按下esc键中断复制操作, **注意例子要有足够多的图元(大概一万个图元),才能很好展示这个bug,而且这个b ...

  6. Mysql系列(三)—— Mysql主从复制配置

    一.前言 主从复制是Mysql知识体系中非常重的要一个模块.学习主从复制和后续的读写分离是完善只是知识体系的重要环节.且主从复制读写分离的思想并不仅仅局限于Mysql,在很多存储系统中都有该方案,如: ...

  7. Docker Data Center系列(一)- 快速搭建云原生架构的实践环境

    本系列文章演示如何快速搭建一个简单的云原生架构的实践环境. 基于这个基础架构,可以持续部署微服务架构的应用栈,演练敏捷开发过程,提升DevOps实践能力. 1 整体规划 1.1 拓扑架构 1.2 基础 ...

  8. MySQL主从复制中断,报“Error on master: message (format)='Cannot delete or update a parent row: a foreign key constraint fails' error code=1217” 错误

    前几天,发现从库挂了,具体报错信息如下: 分析思路 1. 因为我采用的是选择性复制,只针对以下几个库进行复制: card,upay,deal,monitor,collect.所以,不太可能出现对于sa ...

  9. 操作系统开发系列—13.b.进程之丰富中断处理程序

    首先打开时钟中断: out_byte(INT_M_CTLMASK, 0xFE); // Master 8259, OCW1. out_byte(INT_S_CTLMASK, 0xFF); // Sla ...

随机推荐

  1. PAT-L3-球队“食物链”-dfs-状压-set

    题目分析: 1. 一场双循环赛制的篮球赛,注意双循环,双循环! 2. 共有n只球队,两两之间有胜有负有平局: 3. 输入: 举例: 第一行:W:代表球队1打赢过这只队伍 L:代表球队2没打赢过这只队伍 ...

  2. Session 的原理及最佳实践

    Http协议是基于请求和响应的一种无状态的协议,而通过session可以使得Http应用变得有状态,即可以"记住"客户端的信息.今天就来说说这个session和cookie. Se ...

  3. CAS 之 Https And Database Authentication(三)

    CAS 之 Https And Database Authentication(三) 标签(空格分隔): CAS sso-examples-guides源码 Intro(介绍) 由上节可知Apereo ...

  4. WPF学习笔记2

    XML语言中添加注释为<!---->,这是和C#不同的,但是和HTML十分相似. XAML是一种基于XML的标记语言,每一个XML元素代表.NET控件的一个对象,XML元素的属性可以是.N ...

  5. 安装texlive2017(latex的编译软件)

    准备工作是先卸载老版本的texlive,这个只要找到原来安装时的安装目录,然后直接把整个文件夹删掉即可.然后找到最近的Ctan的镜像,下载到对应版本的texlive,例如Mac系统,最好用的就是tex ...

  6. dubbo服务简单搭建

    一.初识dubbo: 架构图: Provider: 暴露服务的服务提供方. Consumer: 调用远程服务的服务消费方. Registry: 服务注册与发现的注册中心. Monitor: 统计服务的 ...

  7. Alpha冲刺Day3

    Alpha冲刺Day3 一:站立式会议 今日安排: 我们把项目大体分为四个模块:数据管理员.企业人员.第三方机构.政府人员.数据管理员这一模块,数据管理员又可细分为两个模块:基础数据管理和风险信息管理 ...

  8. C程序第一次作业

    1-1 计算两数的和与差 1 设计思路 (1)主要描述题目算法 第一步:利用指针psum接收sum的地址,指针pdiff接收diff的地址,因此 * psum为sum, * pdiff为diff. 第 ...

  9. Linux挂载

    1 文件系统中相关目录 dev:设备文件 media:挂载媒体设备,如光驱,U盘 mnt:让用户临时挂载别的文件系统 2 磁盘分区相关知识 1)磁盘包括IDE和SCSI两种接口: IDE接口:速度慢但 ...

  10. ExecutorService实际上是一个线程池的管理工具

    在Java5之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动.调度.管理线程的一大堆API了.在Java5以后,通过Executor来启动线程比用 Thread的start()更好.在新特征 ...