From 2f16c3754308d255b7a34e344256c98358dcf822 Mon Sep 17 00:00:00 2001 From: Jan Grodowski Date: Thu, 6 Nov 2025 11:53:10 +0100 Subject: [PATCH 1/2] Parse binlog file numbers numerically instead of lexicographically to correctly order files like binlog.999999 < binlog.1000000. Would cause the stream to ignore all incoming events and render the gh-ost process stuck: https://github.com/github/gh-ost/blob/48b34bcbfde730b2548d598dee98e9c1f0d2fcce/go/binlog/gomysql_reader.go#L85-L88 Possibly remediated by 005043d5 too, which drops the SmallerThanOrEqual check from GoMySqlReader.handleRowsEvent --- go/mysql/binlog_file.go | 11 +++++------ go/mysql/binlog_file_test.go | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/go/mysql/binlog_file.go b/go/mysql/binlog_file.go index 426e54076..4d1cf08c6 100644 --- a/go/mysql/binlog_file.go +++ b/go/mysql/binlog_file.go @@ -78,13 +78,12 @@ func (this *FileBinlogCoordinates) SmallerThan(other BinlogCoordinates) bool { if !ok || other == nil { return false } - if this.LogFile < coord.LogFile { - return true - } - if this.LogFile == coord.LogFile && this.LogPos < coord.LogPos { - return true + + fileNumberDist := this.FileNumberDistance(coord) + if fileNumberDist == 0 { + return this.LogPos < coord.LogPos } - return false + return fileNumberDist > 0 } // SmallerThanOrEquals returns true if this coordinate is the same or equal to the other one. diff --git a/go/mysql/binlog_file_test.go b/go/mysql/binlog_file_test.go index f12f5514f..50d513698 100644 --- a/go/mysql/binlog_file_test.go +++ b/go/mysql/binlog_file_test.go @@ -134,3 +134,19 @@ func TestIsLogPosOverflowBeyond4Bytes(t *testing.T) { require.True(t, curCoordinates.IsLogPosOverflowBeyond4Bytes(preCoordinates)) } } + +func TestBinlogCoordinates_LogFileZeroPaddedTransition(t *testing.T) { + c1 := FileBinlogCoordinates{LogFile: "mysql-bin.999999", LogPos: 100} + c2 := FileBinlogCoordinates{LogFile: "mysql-bin.1000000", LogPos: 100} + + require.True(t, c1.SmallerThan(&c2)) +} + +func TestBinlogCoordinates_SameLogFileDifferentPosition(t *testing.T) { + c1 := FileBinlogCoordinates{LogFile: "binlog.000001", LogPos: 100} + c2 := FileBinlogCoordinates{LogFile: "binlog.000001", LogPos: 200} + + require.True(t, c1.SmallerThan(&c2)) + require.False(t, c2.SmallerThan(&c1)) + require.False(t, c1.SmallerThan(&c1)) +} From 4368f2a170d9316f95fa2f071465ea69f2db7b62 Mon Sep 17 00:00:00 2001 From: Jan Grodowski Date: Thu, 6 Nov 2025 12:08:39 +0100 Subject: [PATCH 2/2] Remove unused fn FileBinlogCoordinates.FileSmallerThan --- go/mysql/binlog_file.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/go/mysql/binlog_file.go b/go/mysql/binlog_file.go index 4d1cf08c6..b9df215bf 100644 --- a/go/mysql/binlog_file.go +++ b/go/mysql/binlog_file.go @@ -99,15 +99,6 @@ func (this *FileBinlogCoordinates) SmallerThanOrEquals(other BinlogCoordinates) return this.LogFile == coord.LogFile && this.LogPos == coord.LogPos // No Type comparison } -// FileSmallerThan returns true if this coordinate's file is strictly smaller than the other's. -func (this *FileBinlogCoordinates) FileSmallerThan(other BinlogCoordinates) bool { - coord, ok := other.(*FileBinlogCoordinates) - if !ok || other == nil { - return false - } - return this.LogFile < coord.LogFile -} - // FileNumberDistance returns the numeric distance between this coordinate's file number and the other's. // Effectively it means "how many rotates/FLUSHes would make these coordinates's file reach the other's" func (this *FileBinlogCoordinates) FileNumberDistance(other *FileBinlogCoordinates) int {