Skip to content

Add more MySQL-8.0 meta data to GTIDEvent and TableMapEvent #468

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

Merged
merged 23 commits into from
Mar 11, 2020

Conversation

huangjunwen
Copy link
Contributor

@huangjunwen huangjunwen commented Jan 31, 2020

This pr adds more meta data added after MySQL-8.0:

GTIDEvent:

  • immediate/original commit timestamp for this trx
  • transaction length (in bytes) for all binlog events of this trx, including this GTIDEvent. This is useful to detect transaction boundry
  • immediate/original server version

TableMapEvent:

  • column names
  • primary key info
  • signedness info for numeric columns
  • collation info for character and enum/set columns
  • geometry type info

These can be hopefully to solve #427 if using MySQL-8.0

Example GTIDEvent dump (MySQL-8.0):

=== GTIDEvent === 
Date: 2020-02-01 19:15:26
Log position: 3440812
Event size: 88
Commit flag: 1                                                                                                                                           
GTID_NEXT: 5aa72a7f-44a8-11ea-947f-0242ac190002:55
LAST_COMMITTED: 54
SEQUENCE_NUMBER: 55
Immediate commmit timestamp: 1580555726309342 (2020-02-01T19:15:26.309342+08:00)
Orignal commmit timestamp: 0 (<n/a>)
Transaction length: 197
Immediate server version: 80019
Orignal server version: 0

Example GTIDEvent dump for the same event (MySQL-5.7):

=== GTIDEvent ===
Date: 2020-02-01 19:15:26
Log position: 15156
Event size: 65
Commit flag: 1
GTID_NEXT: 5aa72a7f-44a8-11ea-947f-0242ac190002:55
LAST_COMMITTED: 49                                                                                                                                       
SEQUENCE_NUMBER: 50
Immediate commmit timestamp: 0 (<n/a>)
Orignal commmit timestamp: 0 (<n/a>)
Transaction length: 0
Immediate server version: 0
Orignal server version: 0

Example TableMapEvent dump (MySQL-8.0):

=== TableMapEvent ===
Date: 2020-03-10 15:24:58
Log position: 78747
Event size: 580
TableID: 118
TableID size: 6
Flags: 1
Schema: test
Table: _types
Column count: 42
Column type: 
00000000  10 01 01 02 09 03 08 f6  04 05 01 02 09 03 08 f6  |................|
00000010  04 05 0d 0a 13 13 12 12  11 11 fe 0f fe 0f fc fc  |................|
00000020  fc fc fc fc fc fc fe fe  ff f5                    |..........|
NULL bitmap: 
00000000  00 00 fc c0 ff 03                                 |......|
Signedness bitmap: 
00000000  00 7f 80                                          |...|
Default charset: []
Column charset: [224 224 63 63 63 63 63 63 224 224 224 224]
Set str value: [[1 2]]
Enum str value: [[a b]]
Column name: [b_bit n_boolean n_tinyint n_smallint n_mediumint n_int n_bigint n_decimal n_float n_double nu_tinyint nu_smallint nu_mediumint nu_int nu_bigint nu_decimal nu_float nu_double t_year t_date t_time t_ftime t_datetime t_fdatetime t_timestamp t_ftimestamp c_char c_varchar c_binary c_varbinary c_tinyblob c_blob c_mediumblob c_longblob c_tinytext c_text c_mediumtext c_longtext e_enum s_set g_geometry j_json]
Geometry type: [0]
Primary key: []
Primary key prefix: []
Enum/set default charset: [224]
Enum/set column charset: []

Example TableMapEvent dump for the same event (MySQL-5.7):

=== TableMapEvent ===
Date: 2020-03-10 15:24:58
Log position: 31058
Event size: 133
TableID: 117
TableID size: 6
Flags: 1
Schema: test
Table: _types
Column count: 42
Column type: 
00000000  10 01 01 02 09 03 08 f6  04 05 01 02 09 03 08 f6  |................|
00000010  04 05 0d 0a 13 13 12 12  11 11 fe 0f fe 0f fc fc  |................|
00000020  fc fc fc fc fc fc fe fe  ff f5                    |..........|
NULL bitmap: 
00000000  00 00 fc c0 ff 03                                 |......|
Signedness bitmap: 
Default charset: []
Column charset: []
Set str value: []
Enum str value: []
Column name: []
Geometry type: []
Primary key: []
Primary key prefix: []
Enum/set default charset: []
Enum/set column charset: []

ref:

@IANTHEREAL
Copy link
Collaborator

Cool! We will take a look ASAP @huangjunwen

@IANTHEREAL
Copy link
Collaborator

@csuzhangxc @WangXiangUSTC This pr enhances the mysql 8.0 binlog replication protocol, PTAL

@siddontang
Copy link
Collaborator

can you help us test it for MariaDB 8.0? @huangjunwen

@huangjunwen
Copy link
Contributor Author

ok, i will check the compatibility of MariaDB later

Copy link
Contributor

@csuzhangxc csuzhangxc left a comment

Choose a reason for hiding this comment

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

cool, rest LGTM.
BTW, can you add some unit tests?

mysql/util.go Outdated
case 1:
u |= uint64(b[0])
default:
panic(fmt.Errorf("BytesToUint64 byte slice length must be in range [1, 8]"))
Copy link
Contributor

Choose a reason for hiding this comment

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

How about returning an error instead of panic as other func did in this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No problem

@@ -349,6 +350,18 @@ type GTIDEvent struct {
GNO int64
LastCommitted int64
SequenceNumber int64

// The followings are available only after MySQL-8.0
Copy link
Contributor

Choose a reason for hiding this comment

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

How about adding more details about these fields? (OriginalCommitTimestamp and OriginalCommitTimestamp were introduced in 8.0.1, TransactionLength was introduced in 8.0.2, ImmediateServerVersion and OriginalServerVersion were introduced in 8.0.14).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No problem

continue
}

if collation, ok := collations[p]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use collations[i] here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm... i and p are two different counters in this loop: i is the index of all columns while p is the index of character columns, here is an example to illustrate:

column i p
a int 0 n/a
b char(8) 1 0
c bigint 2 n/a
d char(8) 3 1

Copy link
Contributor

Choose a reason for hiding this comment

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

👍 you're right, I found The column index is counted only in all character columns. now.

@huangjunwen
Copy link
Contributor Author

cool, rest LGTM.
BTW, can you add some unit tests?

Sure, i'd like to add some unit tests for both mysql and mariadb once i have time.

@siddontang
Copy link
Collaborator

can we merge it now? @GregoryIan @csuzhangxc

@csuzhangxc
Copy link
Contributor

I think we can merge it, and address comments later (in another PR) or let them go.

@huangjunwen
Copy link
Contributor Author

huangjunwen commented Mar 7, 2020

Would you like to wait a while, i'm starting to write tests this morning ...

@IANTHEREAL
Copy link
Collaborator

👍 yep, we wait for your test case. This is very worthwhile, especially when encountering enum and set types, collation map will be wrong.

@IANTHEREAL
Copy link
Collaborator

@huangjunwen Cool, we will take a look ASAP

@huangjunwen
Copy link
Contributor Author

I've removed types-related helper methods in TableMapEvent now. This is because these types-related optional meta data is stored in a compact format: for example, signedness bitmap only stores the signedness of numeric fields, default charset/column charset only stores collation id of character fields...

If we want to reconstruct the mapping of column index -> meta (signedness/collation id, ...), we need to know whether the field is considerred as a numeric field or a character field ... But there are many corner cases here, more investigation is needed to implement correctly. So i've decided not to implement them in this pr and open another issue to track this later.

Copy link
Contributor

@csuzhangxc csuzhangxc left a comment

Choose a reason for hiding this comment

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

LGTM

@IANTHEREAL
Copy link
Collaborator

LGTM Cool, let's make it perfect later

@dhlin
Copy link
Contributor

dhlin commented Mar 19, 2020

Hi @GregoryIan @siddontang What do we expect on the commit standard in a PR to merge?
I saw there are some commits seem to be draft:

Move some code.
Remove unneccesary code.

and some merge commits

Merge branch 'master' of github.com:huangjunwen/go-mysql
Merge branch 'master' into master

These commits are essential but they can be organized and cleaned before the merge, do we bother to do so?

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.

5 participants