Commit 905659a2 authored by hezx@mail.hezx.com's avatar hezx@mail.hezx.com

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
parents 69a755d6 a3d02647
--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=#/
......
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
--replicate-same-server-id --relay-log=slave-relay-bin --skip-slave-start
# 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;
...@@ -4026,9 +4026,10 @@ end: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 @@ ...@@ -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) ...@@ -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, ...@@ -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,17 +3610,24 @@ bool Discrete_intervals_list::append(ulonglong start, ulonglong val, ...@@ -3585,17 +3610,24 @@ 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(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); 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) */ #endif /* !defined(MYSQL_CLIENT) */
...@@ -912,6 +912,7 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment