Skip to content

Commit

Permalink
Merge branch 'main' into ds-21-summary
Browse files Browse the repository at this point in the history
  • Loading branch information
deepthi committed Oct 3, 2024
2 parents a2037b9 + 35ff2f2 commit ac8a8db
Show file tree
Hide file tree
Showing 32 changed files with 958 additions and 227 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/vitess_tester_vtgate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
go install github.com/vitessio/go-junit-report@HEAD
# install vitess tester
go install github.com/vitessio/vitess-tester@89dd933a9ea0e15f69ca58b9c8ea09a358762cca
go install github.com/vitessio/vitess-tester/go/vt@374fd9f495c1afd3b6bea9d4ec7728119714055
- name: Setup launchable dependencies
if: steps.skip-workflow.outputs.is_draft == 'false' && steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' && github.base_ref == 'main'
Expand Down Expand Up @@ -144,9 +144,9 @@ jobs:
# We go over all the directories in the given path.
# If there is a vschema file there, we use it, otherwise we let vitess-tester autogenerate it.
if [ -f $dir/vschema.json ]; then
vitess-tester --xunit --vschema "$dir"vschema.json $dir/*.test
vt tester --xunit --vschema "$dir"vschema.json $dir/*.test
else
vitess-tester --sharded --xunit $dir/*.test
vt tester --sharded --xunit $dir/*.test
fi
# Number the reports by changing their file names.
mv report.xml report"$i".xml
Expand Down
13 changes: 11 additions & 2 deletions changelog/21.0/21.0.0/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- **[Dynamic VReplication Configuration](#dynamic-vreplication-configuration)**
- **[Reference Table Materialization](#reference-table-materialization)**
- **[New VEXPLAIN Modes: TRACE and KEYS](#new-vexplain-modes)**
- **[Errant GTID Detection on VTTablets](#errant-gtid-vttablet)**

## <a id="major-changes"/>Major Changes

Expand Down Expand Up @@ -161,8 +162,8 @@ so please read the [documentation](https://vitess.io/docs/21.0/user-guides/opera

### <a id="dynamic-vreplication-configuration"/>Dynamic VReplication Configuration

Previously, many of the configuration options for VReplication Workflows had to be provided using vttablet flags. This
meant that any change to VReplication configuration required restarting vttablets. We now allow these to be overridden
Previously, many of the configuration options for VReplication Workflows had to be provided using VTTablet flags. This
meant that any change to VReplication configuration required restarting VTTablets. We now allow these to be overridden
while creating a workflow or dynamically after the workflow is already in progress.

### <a id="reference-table-materialization"/>Reference Table Materialization
Expand Down Expand Up @@ -200,3 +201,11 @@ filter columns (potential candidates for indexes, primary keys, or sharding keys

These new `VEXPLAIN` modes enhance Vitess's query analysis capabilities, allowing for more informed decisions about sharding
strategies and query optimization.

### <a id="errant-gtid-vttablet"/>Errant GTID Detection on VTTablets

VTTablets now run an errant GTID detection logic before they join the replication stream. So, if a replica has an errant GTID, it will
not start replicating from the primary. This protects us from running into situations which are very difficult to recover from.

For users running with the vitess-operator on Kubernetes, this change means that replica tablets with errant GTIDs will have broken
replication and will report as unready. Users will need to manually replace and clean up these errant replica tablets.
27 changes: 27 additions & 0 deletions go/mysql/replication/mysql56_gtid_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,33 @@ func (set Mysql56GTIDSet) SIDBlock() []byte {
return buf.Bytes()
}

// ErrantGTIDsOnReplica gets the errant GTIDs on the replica by comparing against the primary position and UUID.
func ErrantGTIDsOnReplica(replicaPosition Position, primaryPosition Position) (string, error) {
replicaGTIDSet, replicaOk := replicaPosition.GTIDSet.(Mysql56GTIDSet)
primaryGTIDSet, primaryOk := primaryPosition.GTIDSet.(Mysql56GTIDSet)

// Currently we only support errant GTID detection for MySQL 56 flavour.
if !replicaOk || !primaryOk {
return "", nil
}

// Calculate the difference between the replica and primary GTID sets.
diffSet := replicaGTIDSet.Difference(primaryGTIDSet)
return diffSet.String(), nil
}

// RemoveUUID removes a specific UUID from the gtid set.
func (set Mysql56GTIDSet) RemoveUUID(uuid SID) Mysql56GTIDSet {
newSet := make(Mysql56GTIDSet)
for sid, intervals := range set {
if sid == uuid {
continue
}
newSet[sid] = intervals
}
return newSet
}

// Difference will supply the difference between the receiver and supplied Mysql56GTIDSets, and supply the result
// as a Mysql56GTIDSet.
func (set Mysql56GTIDSet) Difference(other Mysql56GTIDSet) Mysql56GTIDSet {
Expand Down
85 changes: 85 additions & 0 deletions go/mysql/replication/mysql56_gtid_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -704,3 +704,88 @@ func BenchmarkMySQL56GTIDParsing(b *testing.B) {
}
}
}

func TestErrantGTIDsOnReplica(t *testing.T) {
tests := []struct {
name string
replicaPosition string
primaryPosition string
errantGtidWanted string
wantErr string
}{
{
name: "Empty replica position",
replicaPosition: "MySQL56/",
primaryPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8",
errantGtidWanted: "",
}, {
name: "Empty primary position",
replicaPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8",
primaryPosition: "MySQL56/",
errantGtidWanted: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8",
}, {
name: "Empty primary position - with multiple errant gtids",
replicaPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1",
primaryPosition: "MySQL56/",
errantGtidWanted: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1",
}, {
name: "Single errant GTID",
replicaPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1,8bc65cca-3fe4-11ed-bbfb-091034d48bd3:34",
primaryPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-50,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1-30",
errantGtidWanted: "8bc65cca-3fe4-11ed-bbfb-091034d48bd3:34",
}, {
name: "Multiple errant GTID",
replicaPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1-32,8bc65cca-3fe4-11ed-bbfb-091034d48bd3:3-35",
primaryPosition: "MySQL56/8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-50,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1-30,8bc65cca-3fe4-11ed-bbfb-091034d48bd3:34",
errantGtidWanted: "8bc65cca-3fe4-11ed-bbfb-091034d48b3e:31-32,8bc65cca-3fe4-11ed-bbfb-091034d48bd3:3-33:35",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
replPos, err := DecodePosition(tt.replicaPosition)
require.NoError(t, err)
primaryPos, err := DecodePosition(tt.primaryPosition)
require.NoError(t, err)
errantGTIDs, err := ErrantGTIDsOnReplica(replPos, primaryPos)
if tt.wantErr != "" {
require.ErrorContains(t, err, tt.wantErr)
} else {
require.NoError(t, err)
require.EqualValues(t, tt.errantGtidWanted, errantGTIDs)
}

})
}
}

func TestMysql56GTIDSet_RemoveUUID(t *testing.T) {
tests := []struct {
name string
initialSet string
uuid string
wantSet string
}{
{
name: "Remove unknown UUID",
initialSet: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1:4-24",
uuid: "8bc65c84-3fe4-11ed-a912-257f0fcde6c9",
wantSet: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1:4-24",
},
{
name: "Remove a single UUID",
initialSet: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9:1-8,8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1:4-24",
uuid: "8bc65c84-3fe4-11ed-a912-257f0fcdd6c9",
wantSet: "8bc65cca-3fe4-11ed-bbfb-091034d48b3e:1:4-24",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gtidSet, err := ParseMysql56GTIDSet(tt.initialSet)
require.NoError(t, err)
sid, err := ParseSID(tt.uuid)
require.NoError(t, err)
gtidSet = gtidSet.RemoveUUID(sid)
require.EqualValues(t, tt.wantSet, gtidSet.String())
})
}
}
Loading

0 comments on commit ac8a8db

Please sign in to comment.