Skip to content

Add MySQL GTID support#950

Draft
timvaillancourt wants to merge 52 commits intogithub:masterfrom
timvaillancourt:add-gtid
Draft

Add MySQL GTID support#950
timvaillancourt wants to merge 52 commits intogithub:masterfrom
timvaillancourt:add-gtid

Conversation

@timvaillancourt
Copy link
Collaborator

@timvaillancourt timvaillancourt commented Mar 27, 2021

Description

This PR adds support for MySQL GTIDs for replication binlog positioning. This support will unblock future reliability improvements to the project. Currently gh-ost support the old-style log files and positions only 👎

This new support is enabled using the flag -gtid and it requires that gtid_mode=ON and enforce_gtid_consitency=ON is set

NOTE: after I get some feedback on the approach and have proven it works I will add some unit testing

cc @shlomi-noach

In case this PR introduced Go code changes:

  • contributed code is using same conventions as original code
  • script/cibuild returns with no formatting errors, build errors or unit test errors.

@timvaillancourt timvaillancourt changed the title Add MySQL GTID support WIP: Add MySQL GTID support Mar 27, 2021
@timvaillancourt
Copy link
Collaborator Author

timvaillancourt commented Apr 1, 2021

Still outstanding:

  • Fail on GTID SID change (Primary failover)
    • As GTID support improves this can be reconsidered
    • This already breaks gh-ost in file-based mode
  • Add GTID support to .SmallerThan() and .SmallerThanOrEqual()
    • Unsure why this is working as-is without this 🤔
  • Unit testing
  • Reviews

@timvaillancourt timvaillancourt changed the title WIP: Add MySQL GTID support Add MySQL GTID support Apr 2, 2021
@timvaillancourt
Copy link
Collaborator Author

Alright, unit testing is done and I've added GTID support to the following *BinlogCoordinate methods:

  • DisplayString()
  • String()
  • Equals()
  • IsEmpty()
  • SmallerThan()
  • SmallerThanOrEquals()

I DID NOT add GTID support to the following because it's unused code, plus many methods aren't possible to reproduce with GTIDs:

  • FileSmallerThan()
  • FileNumberDistance()
  • FileNumber()
  • PreviousFileCoordinatesBy()
  • PreviousFileCoordinates()
  • NextFileCoordinates()
  • DetachedCoordinates()

cc @shlomi-noach / @gtowey / @rashiq for review if anyone has time 🙇

gtowey
gtowey previously approved these changes Jul 12, 2021
// StreamEvents
func (this *GoMySQLReader) handleRowsEvent(ev *replication.BinlogEvent, rowsEvent *replication.RowsEvent, entriesChannel chan<- *BinlogEntry) error {
if this.currentCoordinates.SmallerThanOrEquals(&this.LastAppliedRowsEventHint) {
if !this.migrationContext.UseGTIDs && this.currentCoordinates.SmallerThanOrEquals(&this.LastAppliedRowsEventHint) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a chance that we could also receive a GTID event with an ID that has already been processed? Or is that handled completely by the binlogSyncer.StartSyncGTID method?

}
if this.migrationContext.UseGTIDs {
this.currentCoordinatesMutex.Lock()
defer this.currentCoordinatesMutex.Unlock()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that might be better is to simply move this line to after 132 without using defer. This is because the defer will wait until the method ends to actually release the mutex lock, which is often longer than needed. Since there's literally only one assignment operation between the lock/unlock then there's really no chance for the method to panic, and there's no branches which include a return after the lock.

defer this.currentCoordinatesMutex.Unlock()
this.nextCoordinates = this.currentCoordinates
interval := gomysql.Interval{Start: event.GNO, Stop: event.GNO + 1}
this.nextCoordinates.GTIDSet.AddSet(gomysql.NewUUIDSet(sid, interval))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this assumes that each GTID event is always one and only one GTID. Which sounds like it's probably correct, I just wanted to ask if that was something you specifically checked on when writing this code.

@timvaillancourt timvaillancourt marked this pull request as draft July 6, 2022 22:45
@timvaillancourt timvaillancourt dismissed stale reviews from gtowey and ghost via 8c3938c October 21, 2022 15:47
@timvaillancourt timvaillancourt removed this from the v1.2.0 milestone Dec 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants