主备不一致:Table definition on master and slave does not match

昨天一同事在线上做变更,为了保证主库的稳定性,先在备库把binlog关闭,然后在进行DDL变更,在通过切换HA,把备库切换为主库,在老的主库上做DDL变更

看上去这样做法没有太大的问题,但是当备库变更一做完,HA切换到备库,开始老主库变更的时候,备库就出现复制出现错误:

Last_Error: Table definition on master and slave does not match: Column 10 type mismatch – received type 3, dbname.table_name has type 8

Skip_Counter: 0

Exec_Master_Log_Pos: 1046252634

Relay_Log_Space: 2910773181

Until_Condition: None

Until_Log_File:

Until_Log_Pos: 0

Master_SSL_Allowed: No

Master_SSL_CA_File:

Master_SSL_CA_Path:

Master_SSL_Cert:

Master_SSL_Cipher:

Master_SSL_Key:

Seconds_Behind_Master: NULL

Master_SSL_Verify_Server_Cert: No

Last_IO_Errno: 0

Last_IO_Error:

Last_SQL_Errno: 1535

Last_SQL_Error: Table definition on master and slave does not match: Column 10 type mismatch – received type 3, dbname.table_name has type 8

1 row in set (0.00 sec)

<1>从这个错误上来看,是主备的表结构不一致导致的,但是之前的复制都是好好的,为什么做完变更后就会出现这个问题,应该是在DDL变更后导致的问题;

master:

mysql -uroot dbname -e “show create table table_name”>master.sql

slave:

mysql -uroot dbname -e “show create table table_name”>slave.sql

diff -u master.sql slave.sql没有找到两个表结构有什么大问题;

<2>查看出问题的数据字段:

root@127.0.0.1 : dbname 17:46:35> desc table_name;

+—————-+———————+——+—–+——————-+—————————–+

| Field | Type | Null | Key | Default | Extra |

+—————-+———————+——+—–+——————-+—————————–+

| url | varchar(333) | NO | UNI | NULL | |

| Description | varchar(255) | YES | | NULL | |

| HttpStatus | int(11) | YES | | NULL | |

| AddTime | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |

| ServerBanner | varchar(255) | YES | | NULL | |

| TaskTag | varchar(255) | NO | MUL | NULL | |

| TaskTag2 | varchar(255) | YES | | NULL | |

| DomainName | varchar(255) | NO | MUL | NULL | |

| R_DomainName | varchar(255) | YES | MUL | NULL | |

| ScanTaskID | int(11) | YES | | NULL | |

| SubTaskID | bigint(20) unsigned | NO | PRI | NULL | auto_increment |

| urlhash | varchar(32) | YES | UNI | | |

| duplicateHash | varchar(32) | YES | | | |

| enable | tinyint(1) | YES | | 0 | |

| webappid | int(11) | YES | | NULL | |

| crc_DomainName | int(10) unsigned | YES | MUL | NULL | |

| wapscore | int(11) | YES | | 0 | |

| ip | varchar(45) | YES | | NULL | |

+—————-+———————+——+—–+——————-+—————————–+

slave:

root@127.0.0.1 : information_schema 14:59:40> select * from columns where table_schema=”dbname” and table_name=”table_name” and ORDINAL_POSITION= 10\G;

*************************** 1. row ***************************

TABLE_CATALOG: NULL

TABLE_SCHEMA: dbname

TABLE_NAME: table_name

COLUMN_NAME: ScanTaskID

ORDINAL_POSITION: 10

COLUMN_DEFAULT: NULL

IS_NULLABLE: YES

DATA_TYPE: int

CHARACTER_MAXIMUM_LENGTH: NULL

CHARACTER_OCTET_LENGTH: NULL

NUMERIC_PRECISION: 10

NUMERIC_SCALE: 0

CHARACTER_SET_NAME: NULL

COLLATION_NAME: NULL

COLUMN_TYPE: int(11)

COLUMN_KEY:

EXTRA:

PRIVILEGES: select,insert,update,references

COLUMN_COMMENT:

1 row in set (0.00 sec)

master:

root@127.0.0.1 : information_schema 14:59:19> select * from information_schema.columns where table_schema=”dbname” and table_name=”table_name” and ORDINAL_POSITION= 10\G;

*************************** 1. row ***************************

TABLE_CATALOG: NULL

TABLE_SCHEMA: dbname

TABLE_NAME: table_name

COLUMN_NAME: ScanTaskID

ORDINAL_POSITION: 10

COLUMN_DEFAULT: NULL

IS_NULLABLE: YES

DATA_TYPE: int

CHARACTER_MAXIMUM_LENGTH: NULL

CHARACTER_OCTET_LENGTH: NULL

NUMERIC_PRECISION: 10

NUMERIC_SCALE: 0

CHARACTER_SET_NAME: NULL

COLLATION_NAME: NULL

COLUMN_TYPE: int(11)

COLUMN_KEY:

EXTRA:

PRIVILEGES: select,insert,update,references

COLUMN_COMMENT:

1 row in set (0.00 sec)

查看数据字段,主备库还是一致的,这个时候好像到了穷途;

<3>查看同事昨天的DDL变更脚本,涉及到加字段,调整字段的长度,看上去很平常,

我们是先在备库做的变更,然后在到主库的变更,期间的binlog是关闭的,这时候,印风同学想到如果在备库变更的时候,主库的业务是没有停止的,

如果主库变更的数据同步到备库,备库的变更做完,主备已经不一致了,这样的话,就会造成复制失败了,看了看脚本中有字段长度调长的,这下就迎刃而解了;

问了一下B2B的plinux,他们只有加字段的时候,才放到备库上去做,其他的还是在主库上直接做的;

<4>刚才看到从 information_schema.columns 中查询有问题的列的时候,直接代入ORDINAL_POSITION= 10得到的是ScanTaskID

字段,但出问题的字段是第11为字段(即我们调整长度的字段),所以binlog中是从0开始计算字段的位置的;

<5>5.5中报错显得更加人性了:

Column 0 of table ‘test.t3’ cannot be converted from type ‘int’ to type ‘bigint(20)’;

<6>.那如何避免这样的问题喃,由于我们的库采用的是row模式,只要把slave的复制改为statement就可以了,将主库的binlog_format由row改为statement,这样达到备库的binlog就不会出现错误;

时间: 2024-08-18 09:56:21

主备不一致:Table definition on master and slave does not match的相关文章

数据库内核月报 - 2015 / 05-MySQL · 捉虫动态 · 临时表操作导致主备不一致

bug描述 在binlog_format=row模式下,事务中create或drop临时表后,后面再执行DML(影响多行的DML)如果失败,那么失败的DML会回滚,但DML仍然记录了binlog.这个 binlog 应用到备库后会导致主备不一致. 此bug已提给官方bug#76940. 以下是重现的测例: 主库执行 create table t1(c1 int primary key) engine=innodb; insert into t1 values(1),(2),(3),(4),(5)

MySQL · 捉虫动态 · ALTER IGNORE TABLE导致主备不一致

背景 我们知道当一张表的某个字段存在重复值时,这个字段没办法直接加UNIQUE KEY,但是MySQL提供了一个 ALTER IGNORE TABLE的方式,可以忽略修改表结构过程中出现的错误,但是要忽略UNIQUE重复值,就需要打开old_alter_table,也就是拷贝表的方式来ALTER TABLE. 例如这样: CREATE TABLE t1(c1 int) ENGINE = InnoDB; INSERT INTO t1 VALUES (1), (1); SET old_alter_t

MySQL内核月报 2014.09-MariaDB·主备复制·CREATE OR REPLACE

MariaDB 10.0.8 版本增加了一个CREATE OR REPLACE TABLE语法,这个语法的目的是让Replication更加可靠,为什么这个语句能让复制更可靠呢? 例如用户使用CREATE ... SELECT语句,而这个语句回滚了又重新执行,备库有可能先收到一个CREATE语句,但是没收到INSERT的Events,主库重做一遍之后,备库收到CREATE语句时就会失败,而CREATE OR REPLACE则可以避免这个问题,存在的表会被替换掉. 最基本的使用例子: 这个语句其实

利用pt-table-sync 解决主备数据不一致的问题

https://www.percona.com/doc/percona-toolkit/2.2/pt-table-sync.html 提醒 在使用之前备份将要操作的数据表 使用 --replicate or --sync-to-master方法,是在主库做修改,而不是直接修改备库 同步语法 -- Sync db.tbl on host1 to host2: pt-table-sync --execute h=host1,D=db,t=tbl h=host2 -- Sync all tables

主备-keepalived 备机启动自动从backup切换成master

问题描述 keepalived 备机启动自动从backup切换成master 按照网上的教程搭建,两台服务器,主机ip:10.1.21.211,备机ip:10.1.21.212,虚ip:10.1.21.213.搭完后备用机一**启动keepalived就自动从BACKUP切换到MASTER(另一机并未关keepalived服务)**,正常主机没有down之前备机应该是backup状态才对啊,用ip a查看时发现备用机的IP也包含虚拟IP. 主机配置: ! Configuration File f

mysql 数据库-mysql搭主备和proxy,备库change master to的问题

问题描述 mysql搭主备和proxy,备库change master to的问题 mysql搭主备和proxy,备库change master to master_host,这里的master_host是主库的IP还是proxy的IP,跪求Mysql高人指点.

MySQL复制(2) 主备库都为空的情况下创建主备复制

本文适用于新安装的主库和备库,假定主备库为空,如果你是从已存在的主库复制,请转到<[MySQL] 复制(3)- 创建主备复制(从另一个服务器开始复制)> 主库的配置 主库需要打开二进制日志,并制定一个唯一的server id,my.cnf文件中增加或修改如下内容: server_id=60 log-bin = /data/mysql/log/mysql-bin 备库的配置 备库my.cnf的配置如下: server_id=61 read_only=1 log_bin = /data/mysql

简单的主备切换方案

主备切换是很多高可用性系统都必须解决的问题,方法有很多,象基于ZooKeeper的主备切换就是一个很好的选择. 在这里提供一种更简单但不完美的主备切换方法: 1) 假设A和B是集群中的主控(Master)节点 2) 1~7是工作节点(如HDFS中的DataNode) 3) 在每个工作节点上,都同时配置了A和B的IP,而且是对等的,无主备之分 所谓主:是指提供服务的主控,而备是指不提供服务的主控,当主故障时,由备接管其它服务,但因网络原因,可能主和备都未故障,这个是解决主备切换的关键问题所在. 选

mysql 主备复制下的可靠性漫谈(三)

引言:    前面两期主要针对各种故障条件下,对数据可靠性带来的挑战及普通应对策略.本文主要针对在主备非强同步复制模式下,能否保证数据可靠性来讨论. 复制模式概述:    异步模式:主库收到commit 请求后,依次执行:写redo log prepare,写入binlog,写redo log commit,返回客户端成功.         半同步模式:主库收到commit 后,依次执行 redo log prepare,写binlog/发往备库(两个步骤并行),等待备库回复收到ack,redo