Merge mail.hezx.com:/media/sda3/work/mysql/bkroot/mysql-5.1-new-rpl
into mail.hezx.com:/media/sda3/work/mysql/bkwork/b33029_5.0_to_5.1_fails_on_dup_key/5.1 sql/slave.cc: Auto merged sql/slave.h: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged
This commit is contained in:
commit
6d2976c044
@ -1,4 +1,9 @@
|
|||||||
--let $binlog_start=106
|
# $binlog_start can be set by caller or take a default value
|
||||||
|
|
||||||
|
if (!$binlog_start)
|
||||||
|
{
|
||||||
|
let $binlog_start=106;
|
||||||
|
}
|
||||||
--replace_result $binlog_start <binlog_start>
|
--replace_result $binlog_start <binlog_start>
|
||||||
--replace_column 2 # 4 # 5 #
|
--replace_column 2 # 4 # 5 #
|
||||||
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/
|
--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /file_id=[0-9]+/file_id=#/
|
||||||
|
BIN
mysql-test/std_data/bug33029-slave-relay-bin.000001
Normal file
BIN
mysql-test/std_data/bug33029-slave-relay-bin.000001
Normal file
Binary file not shown.
@ -0,0 +1,33 @@
|
|||||||
|
change master to
|
||||||
|
MASTER_HOST='dummy.localdomain',
|
||||||
|
RELAY_LOG_FILE='slave-relay-bin.000001',
|
||||||
|
RELAY_LOG_POS=4;
|
||||||
|
start slave sql_thread;
|
||||||
|
select MASTER_POS_WAIT('master-bin.000001', 3776);
|
||||||
|
# Result on slave
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
SELECT * FROM t2;
|
||||||
|
id
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14
|
||||||
|
15
|
||||||
|
16
|
||||||
|
17
|
||||||
|
18
|
||||||
|
19
|
@ -0,0 +1 @@
|
|||||||
|
--replicate-same-server-id --relay-log=slave-relay-bin --skip-slave-start
|
@ -0,0 +1,36 @@
|
|||||||
|
# BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
|
||||||
|
# using a trig in SP
|
||||||
|
|
||||||
|
# For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12 exclusive,
|
||||||
|
# if one statement in a SP generated AUTO_INCREMENT value by the top
|
||||||
|
# statement, all statements after it would be considered generated
|
||||||
|
# AUTO_INCREMENT value by the top statement, and a erroneous INSERT_ID
|
||||||
|
# value might be associated with these statement, which could cause
|
||||||
|
# duplicate entry error and stop the slave.
|
||||||
|
|
||||||
|
# Test if the slave can replicate from such a buggy master
|
||||||
|
|
||||||
|
# The bug33029-slave-relay-bin.000001 file is the
|
||||||
|
# slave-replay-bin.000003 file generated by run the
|
||||||
|
# rpl_auto_increment_bug33029.test with clean up statements at the end
|
||||||
|
# of the test case removed on a buggy 5.0 server
|
||||||
|
|
||||||
|
copy_file $MYSQL_TEST_DIR/std_data/bug33029-slave-relay-bin.000001 $MYSQLTEST_VARDIR/master-data/slave-relay-bin.000001;
|
||||||
|
|
||||||
|
write_file $MYSQLTEST_VARDIR/master-data/slave-relay-bin.index;
|
||||||
|
slave-relay-bin.000001
|
||||||
|
EOF
|
||||||
|
|
||||||
|
change master to
|
||||||
|
MASTER_HOST='dummy.localdomain',
|
||||||
|
RELAY_LOG_FILE='slave-relay-bin.000001',
|
||||||
|
RELAY_LOG_POS=4;
|
||||||
|
|
||||||
|
start slave sql_thread;
|
||||||
|
disable_result_log;
|
||||||
|
select MASTER_POS_WAIT('master-bin.000001', 3776);
|
||||||
|
enable_result_log;
|
||||||
|
|
||||||
|
echo # Result on slave;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
30
sql/slave.cc
30
sql/slave.cc
@ -4026,9 +4026,10 @@ end:
|
|||||||
has a certain bug.
|
has a certain bug.
|
||||||
@param rli Relay_log_info which tells the master's version
|
@param rli Relay_log_info which tells the master's version
|
||||||
@param bug_id Number of the bug as found in bugs.mysql.com
|
@param bug_id Number of the bug as found in bugs.mysql.com
|
||||||
|
@param report bool report error message, default TRUE
|
||||||
@return TRUE if master has the bug, FALSE if it does not.
|
@return TRUE if master has the bug, FALSE if it does not.
|
||||||
*/
|
*/
|
||||||
bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id)
|
bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id, bool report)
|
||||||
{
|
{
|
||||||
struct st_version_range_for_one_bug {
|
struct st_version_range_for_one_bug {
|
||||||
uint bug_id;
|
uint bug_id;
|
||||||
@ -4038,7 +4039,9 @@ bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id)
|
|||||||
static struct st_version_range_for_one_bug versions_for_all_bugs[]=
|
static struct st_version_range_for_one_bug versions_for_all_bugs[]=
|
||||||
{
|
{
|
||||||
{24432, { 5, 0, 24 }, { 5, 0, 38 } },
|
{24432, { 5, 0, 24 }, { 5, 0, 38 } },
|
||||||
{24432, { 5, 1, 12 }, { 5, 1, 17 } }
|
{24432, { 5, 1, 12 }, { 5, 1, 17 } },
|
||||||
|
{33029, { 5, 0, 0 }, { 5, 0, 58 } },
|
||||||
|
{33029, { 5, 1, 0 }, { 5, 1, 12 } },
|
||||||
};
|
};
|
||||||
const uchar *master_ver=
|
const uchar *master_ver=
|
||||||
rli->relay_log.description_event_for_exec->server_version_split;
|
rli->relay_log.description_event_for_exec->server_version_split;
|
||||||
@ -4054,6 +4057,9 @@ bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id)
|
|||||||
(memcmp(introduced_in, master_ver, 3) <= 0) &&
|
(memcmp(introduced_in, master_ver, 3) <= 0) &&
|
||||||
(memcmp(fixed_in, master_ver, 3) > 0))
|
(memcmp(fixed_in, master_ver, 3) > 0))
|
||||||
{
|
{
|
||||||
|
if (!report)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
// a short message for SHOW SLAVE STATUS (message length constraints)
|
// a short message for SHOW SLAVE STATUS (message length constraints)
|
||||||
my_printf_error(ER_UNKNOWN_ERROR, "master may suffer from"
|
my_printf_error(ER_UNKNOWN_ERROR, "master may suffer from"
|
||||||
" http://bugs.mysql.com/bug.php?id=%u"
|
" http://bugs.mysql.com/bug.php?id=%u"
|
||||||
@ -4085,6 +4091,26 @@ bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
BUG#33029, For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12
|
||||||
|
exclusive, if one statement in a SP generated AUTO_INCREMENT value
|
||||||
|
by the top statement, all statements after it would be considered
|
||||||
|
generated AUTO_INCREMENT value by the top statement, and a
|
||||||
|
erroneous INSERT_ID value might be associated with these statement,
|
||||||
|
which could cause duplicate entry error and stop the slave.
|
||||||
|
|
||||||
|
Detect buggy master to work around.
|
||||||
|
*/
|
||||||
|
bool rpl_master_erroneous_autoinc(THD *thd)
|
||||||
|
{
|
||||||
|
if (active_mi && active_mi->rli.sql_thd == thd)
|
||||||
|
{
|
||||||
|
Relay_log_info *rli= &active_mi->rli;
|
||||||
|
return rpl_master_has_bug(rli, 33029, FALSE);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||||
template class I_List_iterator<i_string>;
|
template class I_List_iterator<i_string>;
|
||||||
template class I_List_iterator<i_string_pair>;
|
template class I_List_iterator<i_string_pair>;
|
||||||
|
@ -165,7 +165,8 @@ int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
|||||||
|
|
||||||
bool show_master_info(THD* thd, Master_info* mi);
|
bool show_master_info(THD* thd, Master_info* mi);
|
||||||
bool show_binlog_info(THD* thd);
|
bool show_binlog_info(THD* thd);
|
||||||
bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id);
|
bool rpl_master_has_bug(Relay_log_info *rli, uint bug_id, bool report=TRUE);
|
||||||
|
bool rpl_master_erroneous_autoinc(THD* thd);
|
||||||
|
|
||||||
const char *print_slave_db_safe(const char *db);
|
const char *print_slave_db_safe(const char *db);
|
||||||
int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code);
|
int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "rpl_rli.h"
|
#include "rpl_rli.h"
|
||||||
#include "rpl_record.h"
|
#include "rpl_record.h"
|
||||||
|
#include "slave.h"
|
||||||
#include <my_bitmap.h>
|
#include <my_bitmap.h>
|
||||||
#include "log_event.h"
|
#include "log_event.h"
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
@ -2843,6 +2844,18 @@ extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
|
|||||||
void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
||||||
uint new_state)
|
uint new_state)
|
||||||
{
|
{
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
/* BUG#33029, if we are replicating from a buggy master, reset
|
||||||
|
auto_inc_intervals_forced to prevent substatement
|
||||||
|
(triggers/functions) from using erroneous INSERT_ID value
|
||||||
|
*/
|
||||||
|
if (rpl_master_erroneous_autoinc(this))
|
||||||
|
{
|
||||||
|
backup->auto_inc_intervals_forced= auto_inc_intervals_forced;
|
||||||
|
auto_inc_intervals_forced.empty();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
backup->options= options;
|
backup->options= options;
|
||||||
backup->in_sub_stmt= in_sub_stmt;
|
backup->in_sub_stmt= in_sub_stmt;
|
||||||
backup->enable_slow_log= enable_slow_log;
|
backup->enable_slow_log= enable_slow_log;
|
||||||
@ -2880,6 +2893,18 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||||||
|
|
||||||
void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
||||||
{
|
{
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
/* BUG#33029, if we are replicating from a buggy master, restore
|
||||||
|
auto_inc_intervals_forced so that the top statement can use the
|
||||||
|
INSERT_ID value set before this statement.
|
||||||
|
*/
|
||||||
|
if (rpl_master_erroneous_autoinc(this))
|
||||||
|
{
|
||||||
|
auto_inc_intervals_forced= backup->auto_inc_intervals_forced;
|
||||||
|
backup->auto_inc_intervals_forced.empty();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To save resources we want to release savepoints which were created
|
To save resources we want to release savepoints which were created
|
||||||
during execution of function or trigger before leaving their savepoint
|
during execution of function or trigger before leaving their savepoint
|
||||||
@ -3585,7 +3610,15 @@ bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
|
|||||||
{
|
{
|
||||||
/* it cannot, so need to add a new interval */
|
/* it cannot, so need to add a new interval */
|
||||||
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
|
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
|
||||||
if (unlikely(new_interval == NULL)) // out of memory
|
DBUG_RETURN(append(new_interval));
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Discrete_intervals_list::append");
|
||||||
|
if (unlikely(new_interval == NULL))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
DBUG_PRINT("info",("adding new auto_increment interval"));
|
DBUG_PRINT("info",("adding new auto_increment interval"));
|
||||||
if (head == NULL)
|
if (head == NULL)
|
||||||
@ -3594,7 +3627,6 @@ bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
|
|||||||
tail->next= new_interval;
|
tail->next= new_interval;
|
||||||
tail= new_interval;
|
tail= new_interval;
|
||||||
elements++;
|
elements++;
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,6 +912,7 @@ public:
|
|||||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||||
ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
|
ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
|
||||||
Discrete_interval auto_inc_interval_for_cur_row;
|
Discrete_interval auto_inc_interval_for_cur_row;
|
||||||
|
Discrete_intervals_list auto_inc_intervals_forced;
|
||||||
ulonglong limit_found_rows;
|
ulonglong limit_found_rows;
|
||||||
ha_rows cuted_fields, sent_row_count, examined_row_count;
|
ha_rows cuted_fields, sent_row_count, examined_row_count;
|
||||||
ulong client_capabilities;
|
ulong client_capabilities;
|
||||||
|
@ -314,8 +314,27 @@ private:
|
|||||||
*/
|
*/
|
||||||
Discrete_interval *current;
|
Discrete_interval *current;
|
||||||
uint elements; // number of elements
|
uint elements; // number of elements
|
||||||
|
|
||||||
|
/* helper function for copy construct and assignment operator */
|
||||||
|
void copy_(const Discrete_intervals_list& from)
|
||||||
|
{
|
||||||
|
for (Discrete_interval *i= from.head; i; i= i->next)
|
||||||
|
{
|
||||||
|
Discrete_interval j= *i;
|
||||||
|
append(&j);
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
|
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
|
||||||
|
Discrete_intervals_list(const Discrete_intervals_list& from)
|
||||||
|
{
|
||||||
|
copy_(from);
|
||||||
|
}
|
||||||
|
void operator=(const Discrete_intervals_list& from)
|
||||||
|
{
|
||||||
|
empty();
|
||||||
|
copy_(from);
|
||||||
|
}
|
||||||
void empty_no_free()
|
void empty_no_free()
|
||||||
{
|
{
|
||||||
head= current= NULL;
|
head= current= NULL;
|
||||||
@ -331,6 +350,7 @@ public:
|
|||||||
}
|
}
|
||||||
empty_no_free();
|
empty_no_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Discrete_interval* get_next()
|
const Discrete_interval* get_next()
|
||||||
{
|
{
|
||||||
Discrete_interval *tmp= current;
|
Discrete_interval *tmp= current;
|
||||||
@ -340,6 +360,7 @@ public:
|
|||||||
}
|
}
|
||||||
~Discrete_intervals_list() { empty(); };
|
~Discrete_intervals_list() { empty(); };
|
||||||
bool append(ulonglong start, ulonglong val, ulonglong incr);
|
bool append(ulonglong start, ulonglong val, ulonglong incr);
|
||||||
|
bool append(Discrete_interval *interval);
|
||||||
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
||||||
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
||||||
uint nb_elements() const { return elements; }
|
uint nb_elements() const { return elements; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user