debezium
实现了一个mysql ddl
语法解析器,用来解析ddl
语句。debezium
在最近会对解析器进行优化,更换mysql
语法解析器。为什么debezium mysql connector
需要ddl parser
?
为什么需要DdlParser
debeizum mysql connector
有2
个reader
,分别用于snapshot
和增量订阅。它们内部都用到了ddl parser
,充分说明了解析器的重要性。
SnapshotReader
启动时会获取所有表的建表语句,使用DdlParser
解析所有的建表语句;BinlogReader
会对ddl
进行监听,发生ddl
时,会调用DdlParser
解析;
如果没有DdlParser
,我们无法获取dbz
监听的表的最新schema
,无法得到它们的字段类型。如果我们无法获取最新字段类型,那么dbz
通过以上2
个reader
获取到的数据无法转换成正确的record
格式,业务方也就无法正常处理数据。
上述的reader
场景都会调用MysqlSchema.applyDdl
方法,此方法内部会调用DdlParser.parse
方法。
mysql
对应的解析器是MysqlDdlParser
,其重写了parseNextStatement
方法
@Override
protected void parseNextStatement(Marker marker) {
if (tokens.matches(DdlTokenizer.COMMENT)) {
parseComment(marker);
} else if (tokens.matches("CREATE")) {
parseCreate(marker);
} else if (tokens.matches("ALTER")) {
parseAlter(marker);
} else if (tokens.matches("DROP")) {
parseDrop(marker);
} else if (tokens.matches("RENAME")) {
parseRename(marker);
} else if (tokens.matches("USE")) {
parseUse(marker);
} else if (tokens.matches("SET")) {
parseSet(marker);
} else if (tokens.matches("INSERT")) {
consumeStatement();
} else if (tokens.matches("DELETE")) {
consumeStatement();
} else {
parseUnknownStatement(marker);
}
}
此方法对于不同的语句,MysqlDdlParser
分别作了处理。当然不管怎么处理,最后的目的就是让debezium
维护的表结构和数据库的表结构一致(比如字段类型)。
为什么要表结构一致?
当debezium
获取到mysql
数据时,会创建和数据对应一条记录(record
),内容为此次行变更数据。
行数据由多个列组成,每一列都有自己字段类型,debezium
获取的记录和行类型需要进行类型转换。记录会根据debezium
维护的表结构字段类型,进行正确的类型转换。具体的类型转化器都在MySqlValueConverters
类中列出。
正确的字段类型就需要debezium
维护的表结构和mysql
表结构一致。这也就是为什么需要ddl
解析器,解析ddl
语法。