From fd85ae0c0400e70621dd87b650452993953007d1 Mon Sep 17 00:00:00 2001 From: Clemens Kolbitsch Date: Tue, 12 May 2020 15:12:35 -0700 Subject: [PATCH] Fix resuming state without inline verifier If the inline-verifier is not enabled (as is the case for various production uses of ghostferry), its binlog position can grow stale. In some cases it points to such an old position that resuming from it fails (if the source has already deleted such old replication logs). This commit fixes this by relying solely on the binlog writer resume position if the inline verifier is not enabled. We still fail if the inline verifier *is* enabled and the position is stale, but there is nothing one can do about that. If verification is enabled, one must ensure that it's able to keep up with migration. This fixes #184 Change-Id: I24cef00bb78c266705107b2b8b4008171186940d --- ferry.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ferry.go b/ferry.go index 0493afc0..d7e4ba82 100644 --- a/ferry.go +++ b/ferry.go @@ -508,14 +508,25 @@ func (f *Ferry) Start() error { // miss some records that are inserted between the time the // DataIterator determines the range of IDs to copy and the time that // the starting binlog coordinates are determined. + // + // NOTE: If we don't use the inline verifier, we don't consider its last + // position for the resume position. We could be migrating for a long time, + // and the inline verifier position may grow outdated to the point that it + // is no-longer a valid position (the logs could have been deleted). Since + // the inline verifier position is not updated if it's not enabled and we + // use the oldest position in `MinBinlogPosition()`, resume may fail for + // the minimum position. + // In this case, using the last written position is the better state to use var sourcePos siddontangmysql.Position var targetPos siddontangmysql.Position var err error - if f.StateToResumeFrom != nil { + if f.StateToResumeFrom == nil { + sourcePos, err = f.BinlogStreamer.ConnectBinlogStreamerToMysql() + } else if f.inlineVerifier != nil { sourcePos, err = f.BinlogStreamer.ConnectBinlogStreamerToMysqlFrom(f.StateToResumeFrom.MinSourceBinlogPosition()) } else { - sourcePos, err = f.BinlogStreamer.ConnectBinlogStreamerToMysql() + sourcePos, err = f.BinlogStreamer.ConnectBinlogStreamerToMysqlFrom(f.StateToResumeFrom.LastWrittenBinlogPosition) } if err != nil { return err