Skip to content
  • Joao Gramacho's avatar
    be956dbd
    Bug#17620053 SET GTID_NEXT AND DROP TABLE WITH BOTH REGULAR AND · be956dbd
    Joao Gramacho authored
                 TEMPORARY TABLES
    
    Problem:
    =======
    DROP TABLE statement may be split before be sent to binlog if it
    contains regular tables and temporary tables or if it contains
    temporary tables with transactional and non-transactional storage
    engines.
    
    Issuing a DROP TABLE like the described above with GTIDs enables
    and having only one GTID associated to the statement (like the SQL
    thread does after issuing a SET GTID_NEXT='UUID:NUMBER') would lead to
    a problem as there is no GTIDs for all statements after splitting the
    original DROP TABLE.
    
    Analysis:
    ========
    DROP TABLE statements might be split because the behavior of the
    command in respect to the current transaction vary depending on table
    characteristics as follows:
    a) DROP TABLE <regular table> will be committed immediately;
    b) DROP TABLE <temp trans table> will be committed with the current
       transaction (after COMMIT);
    c) DROP TABLE <temp non-trans table> will be committed immediately.
    
    So, mixing these types of tables in a single DROP statement will make
    MySQL server to split the statement in up to three DROP statements in
    the binlog.
    
    Without using GTID, there is no problem with this approach.
    
    If GTIDs are enabled, and it is not in AUTOMATIC mode, issuing a DROP
    TABLE statement that mixes table types above described would lead the
    server to have no GTIDs enough to log all split statements into
    binlog.
    
    Also, DROP TABLE using IF EXISTS will always binlog the drop for all
    tables specified in the statement, even if the tables doesn't exist.
    
    With regular tables it doesn't represent a problem, but with
    temporary tables this was leading to the following problem: as
    temporary tables are split into transactional and non-transactional
    ones, the non-existent tables of a DROP TEMPORARY TABLE statement
    were assumed as transactional ones. So, if a DROP TEMPORARY TABLE
    with two non-transactional temporary tables were issued at the master
    server, it would binlog only one DROP statement containing the two
    tables. But if a filter made one of the temporary tables inexistent
    on the slave, when the SQL thread executes the statement it would
    try to split the statement as it would have a non-transactional
    existent temporary table and a transactional non-existent temporary
    table. And this split will be a problem because the SQL thread will
    have only one GTID for the original DROP statement but having to
    binlog two DROP statements.
    
    Found also a problem with the slave dropping temporary tables when
    it detects that the master has restarted, by calling
    close_temporary_tables()@sql_base.cc, as it was "binlogging" one DROP
    statement per pseudo-thread and per database, but was mixing
    transactional and non-transactional temporary tables in a single
    DROP statement. 
    
    
    Fix:
    ===
    
    The first part of the patch was to throw an error in the client
    session if GTID_NEXT is set to an 'UUID:NUMBER' and a DROP TABLE
    statement is issued mixing the table types above described.
    
    The second part of the patch was to group the inexistent temporary
    tables and only assume them as transactional if at least one
    transactional temporary table is dropped. If no transactional
    temporary tables are dropped, the inexistent temporary tables are
    assumed as non-transactional temporary tables.
    
    The third part of the patch fixed the problem with
    close_temporary_tables().
    
    @ mysql-test/include/save_master_pos.inc
    
      Moved the code that saved the master position to a place that it
      will always be executed.
    
    @ mysql-test/include/sync_slave_sql.inc
    
      Added a new parameter to permit forcing the sync using master
      position instead of GTID_EXECUTED, even if the use_gtids option
      is enabled.
    
      Added a code before the sync to verify is the SQL slave is in the
      current master position (it is already synced).
    
      If the SQL slave is assumed as already synced, we reduce the sync
      timeout to only 1 second. So, if the test is using GTIDs and not
      specified to force sync using master position, the sync command
      will use the master GTID_EXECUTED to sync and will timeout only
      if there is a discrepancy between master and slave GTID_EXECUTED.
    
    @ mysql-test/*/rpl/?/rpl_gtid_drop_table*
    
      mtr files for testing the bug/patch.
    
    @ mysql-test/suite/rpl/r/*.result
    
      Some tests had their result file changed because they listed the
      binlog events for DROP TABLE statements that were split both at
      master and slave and now some of these statements do not split
      anymore.
    
    @ sql/share/errmsg-utf8.txt
    
      Added a new error message for statements that would be split in the
      binary log when @@SESSION.GTID_NEXT is set to 'UUID:NUMBER'.
    
    @ sql/sql_table.cc
    
      Added code to mysql_rm_table() to verify if the statement is safe
      to be executed (if it is not mixing table types or if
      @@SESSION.GTID_NEXT is not set to 'UUID:NUMBER').
    
      Added code to mysql_rm_table_no_locks() to group the inexistent
      temporary tables and assume them as non-transactional if there is no
      transactional temporary tables dropped in the statement.
    
    @sql/sql_base.cc
    
      Changed close_temporary_tables() function to binlog transactional
      and non-transactional temporary tables in distinct DROP statements.
    be956dbd
    Bug#17620053 SET GTID_NEXT AND DROP TABLE WITH BOTH REGULAR AND
    Joao Gramacho authored
                 TEMPORARY TABLES
    
    Problem:
    =======
    DROP TABLE statement may be split before be sent to binlog if it
    contains regular tables and temporary tables or if it contains
    temporary tables with transactional and non-transactional storage
    engines.
    
    Issuing a DROP TABLE like the described above with GTIDs enables
    and having only one GTID associated to the statement (like the SQL
    thread does after issuing a SET GTID_NEXT='UUID:NUMBER') would lead to
    a problem as there is no GTIDs for all statements after splitting the
    original DROP TABLE.
    
    Analysis:
    ========
    DROP TABLE statements might be split because the behavior of the
    command in respect to the current transaction vary depending on table
    characteristics as follows:
    a) DROP TABLE <regular table> will be committed immediately;
    b) DROP TABLE <temp trans table> will be committed with the current
       transaction (after COMMIT);
    c) DROP TABLE <temp non-trans table> will be committed immediately.
    
    So, mixing these types of tables in a single DROP statement will make
    MySQL server to split the statement in up to three DROP statements in
    the binlog.
    
    Without using GTID, there is no problem with this approach.
    
    If GTIDs are enabled, and it is not in AUTOMATIC mode, issuing a DROP
    TABLE statement that mixes table types above described would lead the
    server to have no GTIDs enough to log all split statements into
    binlog.
    
    Also, DROP TABLE using IF EXISTS will always binlog the drop for all
    tables specified in the statement, even if the tables doesn't exist.
    
    With regular tables it doesn't represent a problem, but with
    temporary tables this was leading to the following problem: as
    temporary tables are split into transactional and non-transactional
    ones, the non-existent tables of a DROP TEMPORARY TABLE statement
    were assumed as transactional ones. So, if a DROP TEMPORARY TABLE
    with two non-transactional temporary tables were issued at the master
    server, it would binlog only one DROP statement containing the two
    tables. But if a filter made one of the temporary tables inexistent
    on the slave, when the SQL thread executes the statement it would
    try to split the statement as it would have a non-transactional
    existent temporary table and a transactional non-existent temporary
    table. And this split will be a problem because the SQL thread will
    have only one GTID for the original DROP statement but having to
    binlog two DROP statements.
    
    Found also a problem with the slave dropping temporary tables when
    it detects that the master has restarted, by calling
    close_temporary_tables()@sql_base.cc, as it was "binlogging" one DROP
    statement per pseudo-thread and per database, but was mixing
    transactional and non-transactional temporary tables in a single
    DROP statement. 
    
    
    Fix:
    ===
    
    The first part of the patch was to throw an error in the client
    session if GTID_NEXT is set to an 'UUID:NUMBER' and a DROP TABLE
    statement is issued mixing the table types above described.
    
    The second part of the patch was to group the inexistent temporary
    tables and only assume them as transactional if at least one
    transactional temporary table is dropped. If no transactional
    temporary tables are dropped, the inexistent temporary tables are
    assumed as non-transactional temporary tables.
    
    The third part of the patch fixed the problem with
    close_temporary_tables().
    
    @ mysql-test/include/save_master_pos.inc
    
      Moved the code that saved the master position to a place that it
      will always be executed.
    
    @ mysql-test/include/sync_slave_sql.inc
    
      Added a new parameter to permit forcing the sync using master
      position instead of GTID_EXECUTED, even if the use_gtids option
      is enabled.
    
      Added a code before the sync to verify is the SQL slave is in the
      current master position (it is already synced).
    
      If the SQL slave is assumed as already synced, we reduce the sync
      timeout to only 1 second. So, if the test is using GTIDs and not
      specified to force sync using master position, the sync command
      will use the master GTID_EXECUTED to sync and will timeout only
      if there is a discrepancy between master and slave GTID_EXECUTED.
    
    @ mysql-test/*/rpl/?/rpl_gtid_drop_table*
    
      mtr files for testing the bug/patch.
    
    @ mysql-test/suite/rpl/r/*.result
    
      Some tests had their result file changed because they listed the
      binlog events for DROP TABLE statements that were split both at
      master and slave and now some of these statements do not split
      anymore.
    
    @ sql/share/errmsg-utf8.txt
    
      Added a new error message for statements that would be split in the
      binary log when @@SESSION.GTID_NEXT is set to 'UUID:NUMBER'.
    
    @ sql/sql_table.cc
    
      Added code to mysql_rm_table() to verify if the statement is safe
      to be executed (if it is not mixing table types or if
      @@SESSION.GTID_NEXT is not set to 'UUID:NUMBER').
    
      Added code to mysql_rm_table_no_locks() to group the inexistent
      temporary tables and assume them as non-transactional if there is no
      transactional temporary tables dropped in the statement.
    
    @sql/sql_base.cc
    
      Changed close_temporary_tables() function to binlog transactional
      and non-transactional temporary tables in distinct DROP statements.
Loading