{"record":{"id":"50bed5d0b5ab0ead","repo":"alibaba/canal","slug":"mysql8-0-unmatch-column-metadata-pls-submit-issu","errorCode":null,"errorMessage":"MySQL8.0 unmatch column metadata & pls submit issue , table : {}, db fieldMeta : {} , binlog fieldMeta : {} , on : {}:[]","messagePattern":"MySQL8\\.0 unmatch column metadata & pls submit issue , table : (.+?), db fieldMeta : (.+?) , binlog fieldMeta : (.+?) , on : (.+?):\\[\\]","errorType":"exception","errorClass":"CanalParseException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java","lineNumber":719,"sourceCode":"                    }\n                }\n                continue;\n            }\n\n            FieldMeta fieldMeta = null;\n            if (tableMeta != null && !tableError) {\n                // 处理file meta\n                fieldMeta = tableMeta.getFields().get(i);\n            }\n\n            if (fieldMeta != null && existOptionalMetaData && tableMetaCache.isOnTSDB()) {\n                // check column info\n                boolean check = StringUtils.equalsIgnoreCase(fieldMeta.getColumnName(), info.name);\n                check &= (fieldMeta.isUnsigned() == info.unsigned);\n                check &= (fieldMeta.isNullable() == info.nullable);\n\n                if (!check) {\n                    throw new CanalParseException(\"MySQL8.0 unmatch column metadata & pls submit issue , table : \"\n                                                  + tableMeta.getFullName() + \", db fieldMeta : \"\n                                                  + fieldMeta.toString() + \" , binlog fieldMeta : \" + info.toString()\n                                                  + \" , on : \" + event.getHeader().getLogFileName() + \":\"\n                                                  + (event.getHeader().getLogPos() - event.getHeader().getEventLen()));\n                }\n            }\n\n            Column.Builder columnBuilder = Column.newBuilder();\n            if (fieldMeta != null) {\n                columnBuilder.setName(fieldMeta.getColumnName());\n                columnBuilder.setIsKey(fieldMeta.isKey());\n                // 增加mysql type类型,issue 73\n                columnBuilder.setMysqlType(fieldMeta.getColumnType());\n            } else if (existOptionalMetaData) {\n                columnBuilder.setName(info.name);\n                columnBuilder.setIsKey(info.pk);\n                // mysql8.0里没有mysql type类型\n                // columnBuilder.setMysqlType(fieldMeta.getColumnType());","sourceCodeStart":701,"sourceCodeEnd":737,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/LogEventConvert.java#L701-L737","documentation":"Thrown from parseOneRow() during a strict column-metadata consistency check that only runs under two conditions: existOptionalMetaData is true (MySQL 8.0+ binlog includes extra column metadata) and tableMetaCache.isOnTSDB(). The check compares four attributes — column name, unsigned flag, nullable flag — between the DB's fieldMeta and the binlog's fieldMeta (info). If any mismatch is found, Canal aborts with this exception, indicating a serious TSDB/binlog metadata inconsistency.","triggerScenarios":"During parseOneRow(), for each column where fieldMeta != null && existOptionalMetaData && isOnTSDB(), Canal compares fieldMeta.getColumnName() vs info.name (case-insensitive), fieldMeta.isUnsigned() vs info.unsigned, and fieldMeta.isNullable() vs info.nullable. A single mismatch triggers the exception. The message includes table name, both metadata representations, and the binlog position.","commonSituations":"The TSDB snapshot is stale — a DDL changed column attributes (e.g. added NOT NULL, changed signed→unsigned) but TSDB didn't capture the change. MySQL 8.0's binlog includes richer column metadata that Canal's TSDB hasn't been synchronized with. A manual DDL was applied outside of Canal's binlog stream (e.g. on a different replicated server). TSDB history file was corrupted or manually edited.","solutions":["Delete the TSDB history file (canal.instance.tsdb.dir contents) and restart Canal to force a full TSDB rebuild from the current DB state.","Run canal.instance.tsdb.snapshot.expire to force-expire the stale TSDB entries.","Verify the DDL events are not filtered (canal.instance.filter.query.ddl should be false when TSDB is enabled).","If the mismatch is a known Canal bug for your MySQL 8.0.x version, upgrade Canal."],"exampleFix":"# before — stale TSDB persists mismatch\ncanal.instance.tsdb.enable=true\ncanal.instance.tsdb.dir=../conf/tsdb\n\n# fix — clear TSDB history and restart\n# rm -rf ../conf/tsdb/*\n# then restart canal; TSDB will rebuild from live DDL\n","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    parseRowsEventForTableMeta(event);\n} catch (CanalParseException e) {\n    if (e.getMessage().contains(\"MySQL8.0 unmatch column metadata\")) {\n        // TSDB snapshot is stale — clear and rebuild\n        logger.error(\"Column metadata mismatch on MySQL 8.0, clearing TSDB history\", e);\n        clearTsdbHistory(); // delete tsdb.dir contents\n        // Restart Canal to rebuild TSDB from current DDL\n    }\n}","preventionTips":["Keep TSDB history clean — periodically verify it matches the live database schema.","Ensure DDL events are NOT filtered (canal.instance.filter.query.ddl=false) when TSDB is enabled.","After major schema migrations, clear the TSDB directory and restart Canal."],"tags":["mysql","mysql8","tsdb","column-metadata","ddl","consistency-check"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}