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_column 2 # 4 # 5 #
|
||||
--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.
|
||||
@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 report bool report error message, default TRUE
|
||||
@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 {
|
||||
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[]=
|
||||
{
|
||||
{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=
|
||||
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(fixed_in, master_ver, 3) > 0))
|
||||
{
|
||||
if (!report)
|
||||
return TRUE;
|
||||
|
||||
// a short message for SHOW SLAVE STATUS (message length constraints)
|
||||
my_printf_error(ER_UNKNOWN_ERROR, "master may suffer from"
|
||||
" 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;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
template class I_List_iterator<i_string>;
|
||||
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_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);
|
||||
int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "mysql_priv.h"
|
||||
#include "rpl_rli.h"
|
||||
#include "rpl_record.h"
|
||||
#include "slave.h"
|
||||
#include <my_bitmap.h>
|
||||
#include "log_event.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,
|
||||
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->in_sub_stmt= in_sub_stmt;
|
||||
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)
|
||||
{
|
||||
#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
|
||||
during execution of function or trigger before leaving their savepoint
|
||||
@ -3585,17 +3610,24 @@ bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
|
||||
{
|
||||
/* it cannot, so need to add a new interval */
|
||||
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
|
||||
if (unlikely(new_interval == NULL)) // out of memory
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info",("adding new auto_increment interval"));
|
||||
if (head == NULL)
|
||||
head= current= new_interval;
|
||||
else
|
||||
tail->next= new_interval;
|
||||
tail= new_interval;
|
||||
elements++;
|
||||
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_PRINT("info",("adding new auto_increment interval"));
|
||||
if (head == NULL)
|
||||
head= current= new_interval;
|
||||
else
|
||||
tail->next= new_interval;
|
||||
tail= new_interval;
|
||||
elements++;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
#endif /* !defined(MYSQL_CLIENT) */
|
||||
|
@ -912,6 +912,7 @@ public:
|
||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||
ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
|
||||
Discrete_interval auto_inc_interval_for_cur_row;
|
||||
Discrete_intervals_list auto_inc_intervals_forced;
|
||||
ulonglong limit_found_rows;
|
||||
ha_rows cuted_fields, sent_row_count, examined_row_count;
|
||||
ulong client_capabilities;
|
||||
|
@ -314,8 +314,27 @@ private:
|
||||
*/
|
||||
Discrete_interval *current;
|
||||
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:
|
||||
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()
|
||||
{
|
||||
head= current= NULL;
|
||||
@ -331,6 +350,7 @@ public:
|
||||
}
|
||||
empty_no_free();
|
||||
}
|
||||
|
||||
const Discrete_interval* get_next()
|
||||
{
|
||||
Discrete_interval *tmp= current;
|
||||
@ -340,6 +360,7 @@ public:
|
||||
}
|
||||
~Discrete_intervals_list() { empty(); };
|
||||
bool append(ulonglong start, ulonglong val, ulonglong incr);
|
||||
bool append(Discrete_interval *interval);
|
||||
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
||||
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
||||
uint nb_elements() const { return elements; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user