本文主要分析的部分是instance启动时,parser的一个启动和工作过程。主要关注的是AbstractEventParser的start()方法中的parseThread。
一、序列图
二、源码分析
parseThread中包含的内容比较清晰,代码不是很长,我们逐步分析下。
2.1 构造数据库连接
erosaConnection = buildErosaConnection();
这里构造的,应该是一个mysql的链接,包括的内容都是从配置文件中过来的一些信息,包括mysql的地址,账号密码等。
2.2 启动心跳线程
startHeartBeat(erosaConnection);
这里的心跳,感觉是个假的心跳,并没有用到connection相关的内容。启动一个定时任务,默认3s发送一个心跳的binlog给sink阶段,表名parser还在工作。在sink阶段,会把心跳的binlog直接过滤,不会走到store过程。
2.3 dump之前准备工作
这一步的代码也不复杂。
preDump(erosaConnection);
我们看看preDump都能够做什么?在MysqlEventParser中,我们可以看到,主要做了几件事:
- 针对binlog格式进行过滤,也就是我们在配置文件中指定binlog的格式,不过目前我们默认的都是ROW模式。
- 针对binlog image进行过滤,目前默认是FULL,也就是binlog记录的是变更前后的数据,如果配置为minimal,那么只记录变更后的值,可以减少binlog的文件大小。
- 构造表结构源数据的缓存TableMetaCache
2.4 获取最后的位置信息
这一步是比较核心的,也是保证binlog不丢失的核心代码。
EntryPosition position = findStartPosition(erosaConnection);
final EntryPosition startPosition = position;
if (startPosition == null) {
throw new CanalParseException("can't find start position for " + destination);
}
if (!processTableMeta(startPosition)) {
throw new CanalParseException("can't find init table meta for " + destination
+ " with position : " + startPosition);
}
具体的findStartPosition是怎么实现的,请查阅下一篇文章。
如果没有找到最后的位置信息,那么直接抛出异常,否则还要进行一次判断,也就是processTableMeta,我们看下这个方法做了什么。
protected boolean processTableMeta(EntryPosition position) {
if (isGTIDMode()) {
if (binlogParser instanceof LogEventConvert) {