Bug #106001 Incorrect computation of MAX_SIZE_LOG_EVENT_STATUS
Submitted: 29 Dec 2021 15:35 Modified: 28 Jul 2022 19:23
Reporter: Venkatesh Prasad Venugopal (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Replication Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[29 Dec 2021 15:35] Venkatesh Prasad Venugopal
Description:
MAX_SIZE_LOG_EVENT_STATUS macro defined in the `libbinlogevents/include/binlog_event.h` defines the maximum possible extra bytes in a replication event. 

Till the introduction of `sql_require_primary_key`, the server was correctly calculating the value of MAX_SIZE_LOG_EVENT_STATUS. But after `sql_require_primary_key` was made to include in the Query_log_event, the server started incorrectly calcuating the max value possible.

Please see https://github.com/mysql/mysql-server/blob/mysql-8.0.27/libbinlogevents/include/binlog_eve... to check how the calculation is done.

===
  if (thd && need_sql_require_primary_key) {
    *start++ = Q_SQL_REQUIRE_PRIMARY_KEY;
    *start++ = thd->variables.sql_require_primary_key;
  }

  if (thd && needs_default_table_encryption) {
    *start++ = Q_DEFAULT_TABLE_ENCRYPTION;
    *start++ = thd->variables.default_table_encryption;
  } 
===

Above code is in the `Query_log_event::write()` and it is the place where we write the value of the session's `sql_require_primary_key` and `default_table_encryption` into the binlog. These operations actually require 2 bytes of memory, one byte for the type and one byte for the value.

But however the code in https://github.com/mysql/mysql-server/blob/mysql-8.0.27/libbinlogevents/include/binlog_eve... assumes that it writes only one byte, which is responsible for the wrong calculation.

How to repeat:
Inspect the code.

Suggested fix:
Suggested Fix:

=== BEGIN ===
diff --git a/libbinlogevents/include/binlog_event.h b/libbinlogevents/include/binlog_event.h
index 62d43c75561..c0c9c235265 100644
--- a/libbinlogevents/include/binlog_event.h
+++ b/libbinlogevents/include/binlog_event.h
@@ -128,8 +128,9 @@
    /* type, microseconds */ +1U + 32 * 3 + /* type, user_len, user */         \
    1 + 255 /* host_len, host */ + 1U + 1 /* type, explicit_def..ts*/ + 1U +   \
    8 /* type, xid of DDL */ + 1U +                                            \
-   2 /* type, default_collation_for_utf8mb4_number */ +                       \
-   1 /* sql_require_primary_key */ + 1 /* type, default_table_encryption */)
+   2 /* type, default_collation_for_utf8mb4_number */ + 1U +                  \
+   1 /* sql_require_primary_key */ + 1U +                                     \
+   1 /* type, default_table_encryption */)
 
 /**
    Uninitialized timestamp value (for either last committed or sequence number).
=== END ===
[30 Dec 2021 6:27] MySQL Verification Team
Hi,

Thanks for the report and suggested fix

happy holidays
[28 Jul 2022 19:23] Jon Stephens
Documented fix as follows in the MySQL 8.0.31 changelog:

    Calculation of the maximum length of status variables
    (MAX_SIZE_LOG_EVENT_STATUS) was not performed correctly.

    Issues corrected in this fix are listed here:

        ·sql_require_primary_key and default_table_encryption require
        2 bytes (one for type ID, one for the variable)

        ·The maximum length of time_zone was calculated as 255
        instead of MAX_TIME_ZONE_NAME_LENGTH

        ·An additional byte (each) is required to save the length of
        the user variable, the number of database IDs stored in
        binlog_accessed_db_names, and the type of microseconds

    In addition, master_data_written was not used, and has been
    removed.

Closed.