Skip to content

Commit b8c5d34

Browse files
committed
replication: Support GTID tag in PreviousGTIDsEvent
Issue: closes go-mysql-org#845 The `PreviousGTIDsEvent` / `PREVIOUS_GTIDS_LOG_EVENT` has changed to work with tagged GTIDs. First the `uuidCount` has changed, it encodes the GTID format. Here format 1 is tagged and format 0 is untagged. Then each entry may have a tag. If there is a tag then the uuid itself isn't printed but the tag is appended to the last entry. Examples: - `896e7882-18fe-11ef-ab88-22222d34d411:1-3` regular format, compatible with both formats - `896e7882-18fe-11ef-ab88-22222d34d411:1-4:aaaa:1` tagged format. Combination of `896e7882-18fe-11ef-ab88-22222d34d411:1-4` and `896e7882-18fe-11ef-ab88-22222d34d411:aaaa:1` - `896e7882-18fe-11ef-ab88-22222d34d411:1-4:aaaa:1:abc:1-3:bbbbb:1:bbbbbb:1:x:1,896e7882-18fe-11ef-ab88-22222d34d412:1-2` Combination of: ``` 896e7882-18fe-11ef-ab88-22222d34d411:1-4 :aaaa:1 🔤1-3 :bbbbb:1 :bbbbbb:1 ❌1, 896e7882-18fe-11ef-ab88-22222d34d412:1-2 ``` Please also see: `mysqlbinlog --read-from-remote-server --hexdump $binlogfile` to see how MySQL encodes/decodes this. See also: - https://dev.mysql.com/doc/refman/8.4/en/replication-gtids-concepts.html
1 parent 95109e7 commit b8c5d34

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

replication/event.go

+53-4
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,59 @@ type PreviousGTIDsEvent struct {
229229
GTIDSets string
230230
}
231231

232+
type GtidFormat int
233+
234+
const (
235+
GtidFormatClassic = iota
236+
GtidFormatTagged
237+
)
238+
239+
func decodeSid(data []byte) (format GtidFormat, sidnr uint64) {
240+
if data[7] == 1 {
241+
format = GtidFormatTagged
242+
}
243+
244+
if format == GtidFormatTagged {
245+
sid_mask := []byte{0, 255, 255, 255, 255, 255, 255, 0}
246+
247+
// Apply the mask
248+
for i, _ := range data[:8] {
249+
data[i] &= sid_mask[i]
250+
}
251+
data = append(data, 0)
252+
253+
// sidnr
254+
sidnr = binary.LittleEndian.Uint64(data[1:])
255+
return
256+
}
257+
sidnr = binary.LittleEndian.Uint64(data)
258+
return
259+
}
260+
232261
func (e *PreviousGTIDsEvent) Decode(data []byte) error {
233262
pos := 0
234-
uuidCount := binary.LittleEndian.Uint16(data[pos : pos+8])
263+
264+
gtidinfo := make([]byte, 8)
265+
copy(gtidinfo, data[:8])
266+
format, uuidCount := decodeSid(gtidinfo)
235267
pos += 8
236268

237269
previousGTIDSets := make([]string, uuidCount)
238-
for i := range previousGTIDSets {
270+
currentSetnr := 0
271+
for _ = range previousGTIDSets {
239272
uuid := e.decodeUuid(data[pos : pos+16])
240273
pos += 16
274+
isTag := false
275+
var tag string
276+
if format == GtidFormatTagged {
277+
tagLength := int(data[pos]) / 2
278+
pos += 1
279+
if tagLength > 0 {
280+
isTag = true
281+
tag = string(data[pos : pos+tagLength])
282+
pos += tagLength
283+
}
284+
}
241285
sliceCount := binary.LittleEndian.Uint16(data[pos : pos+8])
242286
pos += 8
243287
intervals := make([]string, sliceCount)
@@ -254,9 +298,14 @@ func (e *PreviousGTIDsEvent) Decode(data []byte) error {
254298
}
255299
intervals[i] = interval
256300
}
257-
previousGTIDSets[i] = fmt.Sprintf("%s:%s", uuid, strings.Join(intervals, ":"))
301+
if isTag {
302+
previousGTIDSets[currentSetnr-1] += fmt.Sprintf(":%s:%s", tag, strings.Join(intervals, ":"))
303+
} else {
304+
previousGTIDSets[currentSetnr] = fmt.Sprintf("%s:%s", uuid, strings.Join(intervals, ":"))
305+
currentSetnr += 1
306+
}
258307
}
259-
e.GTIDSets = strings.Join(previousGTIDSets, ",")
308+
e.GTIDSets = strings.Join(previousGTIDSets[:currentSetnr], ",")
260309
return nil
261310
}
262311

0 commit comments

Comments
 (0)