Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for PARTIAL_UPDATE_ROWS_EVENT binlog event and PARTIAL_JSON mode #774

Merged
merged 2 commits into from
Apr 6, 2023

Conversation

atercattus
Copy link
Member

Implementation for PARTIAL_UPDATE_ROWS_EVENT binlog event.

PARTIAL_UPDATE_ROWS_EVENT is an extension of UPDATE_ROWS_EVENT, allowing partial values according to binlog_row_value_options in mysql8. Value binlog_row_value_options=PARTIAL_JSON allows for mysql store only minimal diff from the previous column value.

Tested for mysql 5.7 and 8, binlog_row_image FULL and MINIMAL, with binlog_row_value_options and without.

Known limitations:

  • current implementation doesn't apply a diff to a column value. Instead BinlogParser returns RowsEvent where a field Rows contains instances of a new type:
JsonDiff struct {
	Op    JsonDiffOperation
	Path  string
	Value string
}

And a user can apply a patch in any way. Why? In binlog_row_image=MINIMAL mode a mysql doesn't write the previous value (BEFORE_IMAGE) to binlog. So the code cannot apply the path to an unknown value.

For example:

SET SESSION binlog_row_image = 'MINIMAL';

SET SESSION binlog_row_value_options = 'PARTIAL_JSON';

INSERT INTO test_json_v2 VALUES (101, '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}');

UPDATE test_json_v2 SET c = JSON_SET(c, '$.ab', '["ab_updatedccc"]') WHERE id = 101;

After this PARTIAL_UPDATE_ROWS_EVENT event will contain only enum_json_diff_operation::REPLACE, $.ab, and ["ab_updatedccc"]'. And nothing all.

@atercattus atercattus changed the title Wip - support for PARTIAL_UPDATE_ROWS_EVENT binlog event WiP - support for PARTIAL_UPDATE_ROWS_EVENT binlog event Mar 3, 2023
@lance6716
Copy link
Collaborator

Hi, is this still a WIP?

@atercattus atercattus changed the title WiP - support for PARTIAL_UPDATE_ROWS_EVENT binlog event Support for PARTIAL_UPDATE_ROWS_EVENT binlog event Mar 18, 2023
@atercattus
Copy link
Member Author

I checked it in our prod and now it looks working and correct :)

@atercattus atercattus requested a review from lance6716 March 18, 2023 15:31
Copy link
Collaborator

@lance6716 lance6716 left a comment

Choose a reason for hiding this comment

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

rest lgtm 👍

replication/row_event.go Outdated Show resolved Hide resolved
@@ -856,6 +877,39 @@ type RowsEvent struct {
ignoreJSONDecodeErr bool
}

// enum class enum_row_image_type { WRITE_AI, UPDATE_BI, UPDATE_AI, DELETE_BI };
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does AI and BI represent "after image" and "before image"? A bit unfamiliar

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I preserve naming from mysql sources. I can rename it for more clarity if you think so.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can see their meanings in the linked MySQL code now 😄

replication/row_event.go Outdated Show resolved Hide resolved
for i := 0; i < int(e.ColumnCount); i++ {
isPartial := isPartialJsonUpdate &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

seems isPartialIndex is same as i? and we can move creating isPartial closer to e.decodeValue(..., isPartial)

Copy link
Member Author

@atercattus atercattus Mar 20, 2023

Choose a reason for hiding this comment

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

seems isPartialIndex is same as i?

No, it's an index inside a partial bitmap and we increment it only for partial fields.

can move creating isPartial closer to e.decodeValue(..., isPartial)

Partial bitmap checking must prepend to null bitmap checking.

I'll update this code for more clarity.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I just forget a false table.ColumnType[i] == MYSQL_TYPE_JSON will short circuit isBitSetIncr(partialBitmap, &partialBitmapIndex),

diff, err = e.decodeJsonPartialBinary(data[meta:n])
if err == nil {
if diff == nil {
v = []byte{}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add a "JsonDiffOperationNoOp" JsonDiff, or tell the caller nil is no-op for JsonDiff? It's a bit ambiguous that we return a []byte{}

Copy link
Member Author

Choose a reason for hiding this comment

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

MySQL doesn't allow any other variants. So I just removed a nil JsonDiff :)

@atercattus atercattus requested a review from lance6716 March 20, 2023 08:22
for i := 0; i < int(e.ColumnCount); i++ {
isPartial := isPartialJsonUpdate &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

I just forget a false table.ColumnType[i] == MYSQL_TYPE_JSON will short circuit isBitSetIncr(partialBitmap, &partialBitmapIndex),

@@ -856,6 +877,39 @@ type RowsEvent struct {
ignoreJSONDecodeErr bool
}

// enum class enum_row_image_type { WRITE_AI, UPDATE_BI, UPDATE_AI, DELETE_BI };
Copy link
Collaborator

Choose a reason for hiding this comment

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

I can see their meanings in the linked MySQL code now 😄

@atercattus atercattus changed the title Support for PARTIAL_UPDATE_ROWS_EVENT binlog event Support for PARTIAL_UPDATE_ROWS_EVENT binlog event and PARTIAL_JSON mode Mar 21, 2023
@atercattus
Copy link
Member Author

OK. I'll make last checks and merge it.

@lance6716
Copy link
Collaborator

ping @atercattus looking forward to this commit

@atercattus
Copy link
Member Author

@lance6716 I'm done with this PR

@atercattus atercattus force-pushed the PARTIAL_UPDATE_ROWS_EVENT branch from 82c1282 to f594b7e Compare April 5, 2023 14:10
@atercattus atercattus requested a review from lance6716 April 5, 2023 14:13
@atercattus atercattus closed this Apr 5, 2023
@atercattus atercattus force-pushed the PARTIAL_UPDATE_ROWS_EVENT branch from f594b7e to b096301 Compare April 5, 2023 14:19
@atercattus atercattus reopened this Apr 5, 2023
@atercattus atercattus force-pushed the PARTIAL_UPDATE_ROWS_EVENT branch from cdd955d to 3d2be20 Compare April 5, 2023 14:45
@atercattus
Copy link
Member Author

I accidentally messed up the branch, but fixed it through force push :)

@lance6716 lance6716 merged commit 431f20a into master Apr 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants