Description:
In mysql8.0, I created a table named "20210103_一二三四五六七八九十TST一二三四五六七00". its character length is only 31 characters, while the byte length is 65. When I parse the binlog file, it will report an error "ROLLBACK /* added by mysqlbinlog */ /*!*/;".
If this instance has a slave node, the slave will also report error.The slave status information is as follows:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.7.28
Master_User: rdsRepl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000010
Read_Master_Log_Pos: 196
Relay_Log_File: rds_mysql-relay-bin.000002
Relay_Log_Pos: 371
Relay_Master_Log_File: mysql-bin.000008
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 13121
Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, the server was unable to fetch a keyring key required to open an encrypted relay log file, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
Skip_Counter: 0
Exec_Master_Log_Pos: 196
Relay_Log_Space: 3130
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 13121
Last_SQL_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, the server was unable to fetch a keyring key required to open an encrypted relay log file, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2197345845
Master_UUID: ff54011e-0edc-11ec-83f7-fa163e12b3f6
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 210906 16:28:13
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: ff54011e-0edc-11ec-83f7-fa163e12b3f6:32
Executed_Gtid_Set: ff54011e-0edc-11ec-83f7-fa163e12b3f6:1-31
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
How to repeat:
Create a table name with non English characters, and the number of bytes occupied by a single character is greater than 1.
When the number of bytes of the created table name is greater than 64 but the number of characters is less than 64, and a DML statement is performed, its binlog file cannot be parsed normally; And will cause replication exceptions
Suggested fix:
In mysql8.0 code, the constructor of "Table_map_event", I see the following code added:
READER_TRY_SET(m_dblen, read<uint8_t>);
if (m_dblen > 64 /* NAME_CHAR_LEN */)
READER_THROW("Database name length too long.")
ptr_dbnam = READER_TRY_CALL(ptr, m_dblen + 1);
m_dbnam = std::string(ptr_dbnam, m_dblen);
READER_TRY_SET(m_tbllen, read<uint8_t>);
if (m_tbllen > 64 /* NAME_CHAR_LEN */)
READER_THROW("Table name length too long.")
ptr_tblnam = READER_TRY_CALL(ptr, m_tbllen + 1);
m_tblnam = std::string(ptr_tblnam, m_tbllen);
There is no similar length check in MySQL 5.7. I suspect that the table name length of log event is assigned incorrectly. For example, a function similar to strlen is used to obtain the length of the table name instead of the number of characters after character encoding and decoding.