• unknown's avatar
    * Mixed replication mode * : · 81a80049
    unknown authored
    1) Fix for BUG#19630 "stored function inserting into two auto_increment breaks
    statement-based binlog":
    a stored function inserting into two such tables may fail to replicate
    (inserting wrong data in the slave's copy of the second table) if the slave's
    second table had an internal auto_increment counter different from master's.
    Because the auto_increment value autogenerated by master for the 2nd table
    does not go into binlog, only the first does, so the slave lacks information.
    To fix this, if running in mixed binlogging mode, if the stored function or
    trigger plans to update two different tables both having auto_increment
    columns, we switch to row-based for the whole function.
    We don't have a simple solution for statement-based binlogging mode, there
    the bug remains and will be documented as a known problem.
    Re-enabling rpl_switch_stm_row_mixed.
    2) Fix for BUG#20630 "Mixed binlogging mode does not work with stored
    functions, triggers, views", which was a documented limitation (in mixed
    mode, we didn't detect that a stored function's execution needed row-based
    binlogging (due to some UUID() call for example); same for
    triggers, same for views (a view created from a SELECT UUID(), and doing
    INSERT INTO sometable SELECT theview; would not replicate row-based).
    This is implemented by, after parsing a routine's body, remembering in sp_head
    that this routine needs row-based binlogging. Then when this routine is used,
    the caller is marked to require row-based binlogging too.
    Same for views: when we parse a view and detect that its SELECT needs
    row-based binary logging, we mark the calling LEX as such.
    3) Fix for BUG#20499 "mixed mode with temporary table breaks binlog":
    a temporary table containing e.g. UUID has its changes not binlogged,
    so any query updating a permanent table with data from the temporary table
    will run wrongly on slave. Solution: in mixed mode we don't switch back
    from row-based to statement-based when there exists temporary tables.
    4) Attempt to test mysqlbinlog on a binlog generated by mysqlbinlog;
    impossible due to BUG#11312 and BUG#20329, but test is in place for when
    they are fixed.
    
    
    mysql-test/r/rpl_switch_stm_row_mixed.result:
      testing BUG#19630 "stored function inserting into two auto_increment breaks
      statement-based binlog",
      testing BUG#20930 "Mixed binlogging mode does not work with stored functions,
      triggers, views.
      testing BUG#20499 "mixed mode with temporary table breaks binlog".
      I have carefully checked this big result file, it is correct.
    mysql-test/t/disabled.def:
      re-enabling test
    mysql-test/t/rpl_switch_stm_row_mixed.test:
      Test for BUG#19630 "stored function inserting into two auto_increment breaks
      statement-based binlog":
      we test that it goes row-based, but only when needed;
      without the bugfix, master and slave's data differed.
      Test for BUG#20499 "mixed mode with temporary table breaks binlog":
      without the bugfix, slave had 2 rows, not 3.
      Test for BUG#20930 "Mixed binlogging mode does not work with stored
      functions, triggers, views".
      Making strings used more different, for easier tracking of "by which routine
      was this binlog line generated".
      Towards the end, an attempt to test mysqlbinlog on a binlog generated by
      the mixed mode; attempt failed because of BUG#11312 and BUG#20929.
    sql/item_create.cc:
      fix for build without row-based replication
    sql/set_var.cc:
      cosmetic: in_sub_stmt is exactly meant to say if we are in stored
      function/trigger, so better use it.
    sql/sp.cc:
      When a routine adds its tables to the top statement's tables, if this routine
      needs row-based binlogging, mark the entire top statement as well.
      Same for triggers.
      Needed for making the mixed replication mode work with stored functions
      and triggers.
    sql/sp_head.cc:
      new enum value for sp_head::m_flags, remembers if, when parsing the 
      routine, we found at least one element (UUID(), UDF) requiring row-based
      binlogging.
    sql/sp_head.h:
      new enum value for sp_head::m_flags (see sp_head.cc).
      An utility method, intended for attributes of a routine which need
      to propagate upwards to the caller; so far only used for binlogging
      information, but open to any other attribute.
    sql/sql_base.cc:
      For BUG#19630 "stored function inserting into two auto_increment
      breaks statement-based binlog":
      When we come to locking tables, we have collected all tables used by
      functions, views and triggers, we detect if we're going to update two tables
      having auto_increment columns. If yes, statement-based binlogging won't work
      (Intvar_log_event records only one insert_id) so, if in mixed binlogging
      mode, switch to row-based.
      For making mixed mode work with stored functions using UUID/UDF:
      when we come to locking tables, we have parsed the whole body so know if
      some elements need row-based. Generation of row-based binlog events
      depends on locked tables, so this is the good place to decide of the binlog
      format.
    sql/sql_class.h:
      Fix for BUG#20499 "mixed mode with temporary table breaks binlog".
      Making mixed mode work with stored functions/triggers: don't reset
      back to statement-based if in executing a stored function/trigger.
    sql/sql_lex.cc:
      fix for build without row-based replication.
      binlog_row_based_if_mixed moves from st_lex to Query_tables_list, because
      that boolean should not be affected when a SELECT reads the INFORMATION_SCHEMA
      and thus implicitely parses a view or routine's body: this body may
      contain needing-row-based components like UUID() but the SELECT on
      INFORMATION_SCHEMA should not be affected by that and should not use
      row-based; as Query_tables_list is backed-up/reset/restored when parsing
      the view/routine's body, so does binlog_row_based_if_mixed and the
      top SELECT is not affected.
    sql/sql_lex.h:
      fix for build without row-based replication.
      binlog_row_based_if_mixed moves from st_lex to Query_tables_list
      (see sql_lex.cc)
    sql/sql_parse.cc:
      For the mixed mode to work with stored functions using UUID and UDF, we need
      to move the switch-back-from-row-to-statement out of
      mysql_execute_command() (which is executed for each statement, causing
      the binlogging mode to change in the middle of the function, which would
      not work)
      The switch to row-based is now done in lock_tables(), no need to keep it
      in mysql_execute_command(); in lock_tables() we also switch back from 
      row-based to statement-based (so in a stored procedure, all statements
      have their binlogging mode). We must however keep a resetting in
      mysql_reset_thd_for_next_command() as e.g. CREATE PROCEDURE does not call
      lock_tables().
    sql/sql_view.cc:
      When a view's body needs row-based binlogging (e.g. the view is created
      from SELECT UUID()), propagate this fact to the top st_lex.
    sql/sql_yacc.yy:
      use TRUE instead of 1, for binlog_row_based_if_mixed.
    81a80049
sql_lex.h 38.9 KB