Skip to content

Commit e187ab6

Browse files
committed
Add support for MariaDB compressed binlog events
1 parent f854680 commit e187ab6

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

Diff for: canal/sync.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,11 @@ func (c *Canal) handleRowsEvent(e *replication.BinlogEvent) error {
253253
}
254254
var action string
255255
switch e.Header.EventType {
256-
case replication.WRITE_ROWS_EVENTv1, replication.WRITE_ROWS_EVENTv2:
256+
case replication.WRITE_ROWS_EVENTv1, replication.WRITE_ROWS_EVENTv2, replication.MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1:
257257
action = InsertAction
258-
case replication.DELETE_ROWS_EVENTv1, replication.DELETE_ROWS_EVENTv2:
258+
case replication.DELETE_ROWS_EVENTv1, replication.DELETE_ROWS_EVENTv2, replication.MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1:
259259
action = DeleteAction
260-
case replication.UPDATE_ROWS_EVENTv1, replication.UPDATE_ROWS_EVENTv2:
260+
case replication.UPDATE_ROWS_EVENTv1, replication.UPDATE_ROWS_EVENTv2, replication.MARIADB_UPDATE_ROWS_COMPRESSED_EVENT_V1:
261261
action = UpdateAction
262262
default:
263263
return errors.Errorf("%s not supported now", e.Header.EventType)

Diff for: replication/const.go

+11
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ const (
101101
MARIADB_BINLOG_CHECKPOINT_EVENT
102102
MARIADB_GTID_EVENT
103103
MARIADB_GTID_LIST_EVENT
104+
MARIADB_START_ENCRYPTION_EVENT
105+
MARIADB_QUERY_COMPRESSED_EVENT
106+
MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1
107+
MARIADB_UPDATE_ROWS_COMPRESSED_EVENT_V1
108+
MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1
104109
)
105110

106111
func (e EventType) String() string {
@@ -197,6 +202,12 @@ func (e EventType) String() string {
197202
return "TransactionPayloadEvent"
198203
case HEARTBEAT_LOG_EVENT_V2:
199204
return "HeartbeatLogEventV2"
205+
case MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1:
206+
return "MariadbWriteRowsCompressedEventV1"
207+
case MARIADB_UPDATE_ROWS_COMPRESSED_EVENT_V1:
208+
return "MariadbUpdateRowsCompressedEventV1"
209+
case MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1:
210+
return "MariadbDeleteRowsCompressedEventV1"
200211

201212
default:
202213
return "UnknownEvent"

Diff for: replication/parser.go

+14
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,11 @@ func (p *BinlogParser) parseEvent(h *EventHeader, data []byte, rawData []byte) (
270270
WRITE_ROWS_EVENTv2,
271271
UPDATE_ROWS_EVENTv2,
272272
DELETE_ROWS_EVENTv2,
273+
MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1,
274+
MARIADB_UPDATE_ROWS_COMPRESSED_EVENT_V1,
275+
MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1,
273276
PARTIAL_UPDATE_ROWS_EVENT: // Extension of UPDATE_ROWS_EVENT, allowing partial values according to binlog_row_value_options
277+
274278
e = p.newRowsEvent(h)
275279
case ROWS_QUERY_EVENT:
276280
e = &RowsQueryEvent{}
@@ -412,6 +416,16 @@ func (p *BinlogParser) newRowsEvent(h *EventHeader) *RowsEvent {
412416
case UPDATE_ROWS_EVENTv1:
413417
e.Version = 1
414418
e.needBitmap2 = true
419+
case MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1:
420+
e.Version = 1
421+
e.compressed = true
422+
case MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1:
423+
e.Version = 1
424+
e.compressed = true
425+
case MARIADB_UPDATE_ROWS_COMPRESSED_EVENT_V1:
426+
e.Version = 1
427+
e.compressed = true
428+
e.needBitmap2 = true
415429
case WRITE_ROWS_EVENTv2:
416430
e.Version = 2
417431
case UPDATE_ROWS_EVENTv2:

Diff for: replication/row_event.go

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package replication
22

33
import (
4+
"bytes"
5+
"compress/zlib"
46
"encoding/binary"
57
"encoding/hex"
68
"fmt"
@@ -830,6 +832,9 @@ type RowsEvent struct {
830832
tables map[uint64]*TableMapEvent
831833
needBitmap2 bool
832834

835+
// for mariadb *_COMPRESSED_EVENT_V1
836+
compressed bool
837+
833838
eventType EventType
834839

835840
Table *TableMapEvent
@@ -970,9 +975,9 @@ func (e *RowsEvent) DecodeData(pos int, data []byte) (err2 error) {
970975

971976
var rowImageType EnumRowImageType
972977
switch e.eventType {
973-
case WRITE_ROWS_EVENTv0, WRITE_ROWS_EVENTv1, WRITE_ROWS_EVENTv2:
978+
case WRITE_ROWS_EVENTv0, WRITE_ROWS_EVENTv1, WRITE_ROWS_EVENTv2, MARIADB_WRITE_ROWS_COMPRESSED_EVENT_V1:
974979
rowImageType = EnumRowImageTypeWriteAI
975-
case DELETE_ROWS_EVENTv0, DELETE_ROWS_EVENTv1, DELETE_ROWS_EVENTv2:
980+
case DELETE_ROWS_EVENTv0, DELETE_ROWS_EVENTv1, DELETE_ROWS_EVENTv2, MARIADB_DELETE_ROWS_COMPRESSED_EVENT_V1:
976981
rowImageType = EnumRowImageTypeDeleteBI
977982
default:
978983
rowImageType = EnumRowImageTypeUpdateBI
@@ -1002,6 +1007,13 @@ func (e *RowsEvent) Decode(data []byte) error {
10021007
if err != nil {
10031008
return err
10041009
}
1010+
if e.compressed {
1011+
uncompressedData, err := e.decompressData(pos, data)
1012+
if err != nil {
1013+
return err
1014+
}
1015+
return e.DecodeData(0, uncompressedData)
1016+
}
10051017
return e.DecodeData(pos, data)
10061018
}
10071019

@@ -1103,6 +1115,28 @@ func (e *RowsEvent) parseFracTime(t interface{}) interface{} {
11031115
return v.Time
11041116
}
11051117

1118+
func (e *RowsEvent) decompressData(pos int, data []byte) ([]byte, error) {
1119+
// algorithm always 0=zlib
1120+
// algorithm := (data[pos] & 0x07) >> 4
1121+
headerSize := int(data[pos] & 0x07)
1122+
pos++
1123+
1124+
uncompressedDataSize := BFixedLengthInt(data[pos : pos+headerSize])
1125+
1126+
pos += headerSize
1127+
uncompressedData := make([]byte, uncompressedDataSize)
1128+
r, err := zlib.NewReader(bytes.NewReader(data[pos:]))
1129+
if err != nil {
1130+
return nil, err
1131+
}
1132+
defer r.Close()
1133+
_, err = io.ReadFull(r, uncompressedData)
1134+
if err != nil {
1135+
return nil, err
1136+
}
1137+
return uncompressedData, nil
1138+
}
1139+
11061140
// see mysql sql/log_event.cc log_event_print_value
11071141
func (e *RowsEvent) decodeValue(data []byte, tp byte, meta uint16, isPartial bool) (v interface{}, n int, err error) {
11081142
var length = 0

0 commit comments

Comments
 (0)