• Venkatesh Duggirala's avatar
    Bug#17234370 LAST_INSERT_ID IS REPLICATED INCORRECTLY IF · 2b07397b
    Venkatesh Duggirala authored
    REPLICATION FILTERS ARE USED.
    
    Problem:
    When Filtered-slave applies Int_var_log_event and when it
    tries to write the event to its own binlog, LAST_INSERT_ID
    value is written wrongly.
    
    Analysis:
    THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
    is a variable which is set when LAST_INSERT_ID() is used by
    a statement. If it is set, first_successful_insert_id_in_
    prev_stmt_for_binlog will be stored in the statement-based
    binlog. This variable is CUMULATIVE along the execution of
    a stored function or trigger: if one substatement sets it
    to 1 it will stay 1 until the function/trigger ends,
    thus making sure that first_successful_insert_id_in_
    prev_stmt_for_binlog does not change anymore and is
    propagated to the caller for binlogging. This is achieved
    using the following code
    if(!stmt_depends_on_first_successful_insert_id_in_prev_stmt)               
    {                                                                           
      /* It's the first time we read it */                                      
      first_successful_insert_id_in_prev_stmt_for_binlog=                       
      first_successful_insert_id_in_prev_stmt;                                
      stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;               
    }
    
    Slave server, after receiving Int_var_log_event event from
    master, it is setting
    stmt_depends_on_first_successful_insert_id_in_prev_stmt
    to true(*which is wrong*) and not setting
    first_successful_insert_id_in_prev_stmt_for_binlog. Because
    of this problem, when the actual DML statement with
    LAST_INSERT_ID() is parsed by slave SQL thread,
    first_successful_insert_id_in_prev_stmt_for_binlog is not
    set. Hence the value zero (default value) is written to
    slave's binlog.
    
    Why only *Filtered slave* is effected when the code is
    in common place:
    -------------------------------------------------------
    In Query_log_event::do_apply_event,
    THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
    is reset to zero at the end of the function. In case of
    normal slave (No Filters), this variable will be reset. 
    In Filtered slave, Slave SQL thread defers all IRU events's
    execution until IRU's Query_log event is received. Once it
    receives Query_log_event it executes all pending IRU events
    and then it executes Query_log_event. Hence the variable is
    not getting reset to 0, causing this bug.
    
    Fix: As described above, the root cause was setting 
    THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
    when Int_var_log_event was executed by a SQL thread. Hence
    removing the problematic line from the code.
    2b07397b
log_event.cc 321 KB