summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Soares <luis.soares@sun.com>2010-03-17 00:06:13 +0000
committerLuis Soares <luis.soares@sun.com>2010-03-17 00:06:13 +0000
commit92b5e586758de97ebf3272e337b965d43cdf571c (patch)
tree5100e704c6b5312c7170166f1217fcfea545441d
parent5937da69a6d5b3461373dfc7abd8d003f4013fce (diff)
downloadmariadb-git-92b5e586758de97ebf3272e337b965d43cdf571c.tar.gz
BUG#51426: overflow for auto_increment column causes slave to stop
In BUG#49562 we fixed the case where numeric user var events would not serialize the flag stating whether the value was signed or unsigned (unsigned_flag). This fixed the case that the slave would get an overflow while treating the unsigned values as signed. In this bug, we find that the unsigned_flag can sometimes change between the moment that the user value is recorded for binlogging purposes and the actual binlogging time. Since we take the unsigned_flag from the runtime variable data, at binlogging time, and the variable value is comes from the copy taken earlier in the execution, there may be inconsistency in the User_var_log_event between the variable value and its unsigned_flag. We fix this by also copying the unsigned_flag of the user_var_entry when its value is copied, for binlogging purposes. Later, at binlogging time, we use the copied unsigned_flag and not the one in the runtime user_var_entry instance.
-rw-r--r--mysql-test/suite/rpl/r/rpl_stm_user_variables.result16
-rw-r--r--mysql-test/suite/rpl/t/rpl_stm_user_variables.test33
-rw-r--r--sql/item_func.cc1
-rw-r--r--sql/log.cc2
-rw-r--r--sql/sql_class.h1
5 files changed, 52 insertions, 1 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_stm_user_variables.result b/mysql-test/suite/rpl/r/rpl_stm_user_variables.result
index 5e758fc02f3..8f43425b201 100644
--- a/mysql-test/suite/rpl/r/rpl_stm_user_variables.result
+++ b/mysql-test/suite/rpl/r/rpl_stm_user_variables.result
@@ -206,3 +206,19 @@ Comparing tables master:test.t1 and slave:test.t1
TRUNCATE t1;
## check: contents of both tables master's and slave's
DROP TABLE t1;
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1 ( c INT, PRIMARY KEY (c)) Engine=MyISAM;
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW SET @aux = -1 ;
+SET @aux = 10294947273192243200;
+SET @aux1= @aux;
+INSERT INTO t1 VALUES (@aux) , (@aux1);
+ERROR 23000: Duplicate entry '2147483647' for key 'PRIMARY'
+## assertion: master and slave tables are in sync
+Comparing tables master:test.t1 and slave:test.t1
+DROP TRIGGER tr1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/rpl/t/rpl_stm_user_variables.test b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test
index c58acdcb084..05adc597776 100644
--- a/mysql-test/suite/rpl/t/rpl_stm_user_variables.test
+++ b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test
@@ -139,3 +139,36 @@ TRUNCATE t1;
-- connection master
DROP TABLE t1;
-- sync_slave_with_master
+
+#####################################################################
+#
+# BUG#51426
+#
+#####################################################################
+-- source include/master-slave-reset.inc
+-- connection master
+
+CREATE TABLE t1 ( c INT, PRIMARY KEY (c)) Engine=MyISAM;
+
+# offending trigger that would reset the unsigned flag for aux before
+# binlogging of User_var_log_event would take place.
+CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW SET @aux = -1 ;
+
+SET @aux = 10294947273192243200;
+SET @aux1= @aux;
+-- error ER_DUP_ENTRY
+INSERT INTO t1 VALUES (@aux) , (@aux1);
+
+-- sync_slave_with_master
+
+-- echo ## assertion: master and slave tables are in sync
+-- let $diff_table_1=master:test.t1
+-- let $diff_table_2=slave:test.t1
+-- source include/diff_tables.inc
+
+--connection master
+DROP TRIGGER tr1;
+DROP TABLE t1;
+
+-- sync_slave_with_master
+
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ca8f5d00bb1..391ddfa4a7c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4766,6 +4766,7 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
user_var_event->user_var_event= var_entry;
user_var_event->type= var_entry->type;
user_var_event->charset_number= var_entry->collation.collation->number;
+ user_var_event->unsigned_flag= var_entry->unsigned_flag;
if (!var_entry->value)
{
/* NULL value*/
diff --git a/sql/log.cc b/sql/log.cc
index ce9d75089d1..279782d271b 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -4671,7 +4671,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
/* setting flags for user var log event */
uchar flags= User_var_log_event::UNDEF_F;
- if (user_var_event->user_var_event->unsigned_flag)
+ if (user_var_event->unsigned_flag)
flags|= User_var_log_event::UNSIGNED_F;
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
diff --git a/sql/sql_class.h b/sql/sql_class.h
index f8e8942e244..de6d92eccfd 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -75,6 +75,7 @@ typedef struct st_user_var_events
ulong length;
Item_result type;
uint charset_number;
+ bool unsigned_flag;
} BINLOG_USER_VAR_EVENT;
#define RP_LOCK_LOG_IS_ALREADY_LOCKED 1