If we have a 2+ node cluster which is replicating from an async master
and the binlog_format is set to STATEMENT and multi-row inserts are executed
on a table with an auto_increment column such that values are automatically
generated by MySQL, then the server node generates wrong auto_increment
values, which are different from what was generated on the async master.

The causes and fixes:

1. We need to improve processing of changing the auto-increment values
after changing the cluster size.

2. If wsrep auto_increment_control switched on during operation of
the node, then we should immediately update the auto_increment_increment
and auto_increment_offset global variables, without waiting of the next
invocation of the wsrep_view_handler_cb() callback. In the current version
these variables retain its initial values if wsrep_auto_increment_control
is switched on during operation of the node, which leads to inconsistent
results on the different nodes in some scenarios.

3. If wsrep auto_increment_control switched off during operation of the node,
then we must return the original values of the auto_increment_increment and
auto_increment_offset global variables, as the user has set. To make this
possible, we need to add a "shadow copies" of these variables (which stores
the latest values set by the user).
This commit is contained in:
Julius Goryavsky 2018-07-26 15:04:11 +02:00 committed by Jan Lindström
parent 5960815630
commit 75dfd4acb9
11 changed files with 677 additions and 30 deletions

View file

@ -0,0 +1,147 @@
SET GLOBAL wsrep_forced_binlog_format='STATEMENT';
SET GLOBAL wsrep_forced_binlog_format='STATEMENT';
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
i c
1 dummy_text
insert into t1(i) values(null), (null), (null);
select * from t1;
i c
1 dummy_text
3 dummy_text
5 dummy_text
7 dummy_text
select * from t1;
i c
1 dummy_text
3 dummy_text
5 dummy_text
7 dummy_text
SET GLOBAL wsrep_forced_binlog_format='none';
SET GLOBAL wsrep_forced_binlog_format='none';
drop table t1;
SET SESSION binlog_format='STATEMENT';
show variables like 'binlog_format';
Variable_name Value
binlog_format STATEMENT
SET GLOBAL wsrep_auto_increment_control='OFF';
SET SESSION auto_increment_increment = 3;
SET SESSION auto_increment_offset = 1;
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
i c
1 dummy_text
insert into t1(i) values(null), (null), (null);
select * from t1;
i c
1 dummy_text
4 dummy_text
7 dummy_text
10 dummy_text
select * from t1;
i c
1 dummy_text
4 dummy_text
7 dummy_text
10 dummy_text
SET GLOBAL wsrep_auto_increment_control='ON';
SET SESSION binlog_format='ROW';
show variables like 'binlog_format';
Variable_name Value
binlog_format ROW
show variables like '%auto_increment%';
Variable_name Value
auto_increment_increment 2
auto_increment_offset 1
wsrep_auto_increment_control ON
SET GLOBAL wsrep_auto_increment_control='OFF';
show variables like '%auto_increment%';
Variable_name Value
auto_increment_increment 3
auto_increment_offset 1
wsrep_auto_increment_control OFF
SET GLOBAL wsrep_auto_increment_control='ON';
drop table t1;
SET GLOBAL wsrep_forced_binlog_format='ROW';
SET GLOBAL wsrep_forced_binlog_format='ROW';
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
i c
1 dummy_text
insert into t1(i) values(null), (null), (null);
select * from t1;
i c
1 dummy_text
3 dummy_text
5 dummy_text
7 dummy_text
select * from t1;
i c
1 dummy_text
3 dummy_text
5 dummy_text
7 dummy_text
SET GLOBAL wsrep_forced_binlog_format='none';
SET GLOBAL wsrep_forced_binlog_format='none';
drop table t1;
SET SESSION binlog_format='ROW';
show variables like 'binlog_format';
Variable_name Value
binlog_format ROW
SET GLOBAL wsrep_auto_increment_control='OFF';
SET SESSION auto_increment_increment = 3;
SET SESSION auto_increment_offset = 1;
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
i c
1 dummy_text
insert into t1(i) values(null), (null), (null);
select * from t1;
i c
1 dummy_text
4 dummy_text
7 dummy_text
10 dummy_text
select * from t1;
i c
1 dummy_text
4 dummy_text
7 dummy_text
10 dummy_text
SET GLOBAL wsrep_auto_increment_control='ON';
show variables like 'binlog_format';
Variable_name Value
binlog_format ROW
show variables like '%auto_increment%';
Variable_name Value
auto_increment_increment 2
auto_increment_offset 1
wsrep_auto_increment_control ON
SET GLOBAL wsrep_auto_increment_control='OFF';
show variables like '%auto_increment%';
Variable_name Value
auto_increment_increment 3
auto_increment_offset 1
wsrep_auto_increment_control OFF
SET GLOBAL wsrep_auto_increment_control='ON';
drop table t1;

View file

@ -0,0 +1,223 @@
##
## Tests the auto-increment with binlog in STATEMENT mode.
##
--source include/galera_cluster.inc
--source include/have_innodb.inc
--let $node_1=node_1
--let $node_2=node_2
--source include/auto_increment_offset_save.inc
##
## Verify the correct operation of the auto-increment when the binlog
## format artificially set to the 'STATEMENT' (although this mode is
## not recommended in the current version):
##
--connection node_2
SET GLOBAL wsrep_forced_binlog_format='STATEMENT';
--connection node_1
SET GLOBAL wsrep_forced_binlog_format='STATEMENT';
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
insert into t1(i) values(null), (null), (null);
select * from t1;
--connection node_2
select * from t1;
SET GLOBAL wsrep_forced_binlog_format='none';
--connection node_1
SET GLOBAL wsrep_forced_binlog_format='none';
drop table t1;
##
## Check the operation when the automatic control over the auto-increment
## settings is switched off, that is, when we use the increment step and
## the offset specified by the user. In the current session, the binlog
## format is set to 'STATEMENT'. It is important that the values of the
## auto-increment options does not changed on other node - it allows us
## to check the correct transmission of the auto-increment options to
## other nodes:
##
--disable_warnings
SET SESSION binlog_format='STATEMENT';
--enable_warnings
show variables like 'binlog_format';
SET GLOBAL wsrep_auto_increment_control='OFF';
SET SESSION auto_increment_increment = 3;
SET SESSION auto_increment_offset = 1;
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
insert into t1(i) values(null), (null), (null);
select * from t1;
--connection node_2
select * from t1;
--connection node_1
##
## Verify the return to automatic calculation of the step
## and offset of the auto-increment:
##
SET GLOBAL wsrep_auto_increment_control='ON';
SET SESSION binlog_format='ROW';
show variables like 'binlog_format';
show variables like '%auto_increment%';
##
## Verify the recovery of original user-defined values after
## stopping the automatic control over auto-increment:
##
SET GLOBAL wsrep_auto_increment_control='OFF';
show variables like '%auto_increment%';
##
## Restore original options and drop test table:
##
SET GLOBAL wsrep_auto_increment_control='ON';
drop table t1;
##
## Verify the correct operation of the auto-increment when the binlog
## format set to the 'ROW':
##
--connection node_2
SET GLOBAL wsrep_forced_binlog_format='ROW';
--connection node_1
SET GLOBAL wsrep_forced_binlog_format='ROW';
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
insert into t1(i) values(null), (null), (null);
select * from t1;
--connection node_2
select * from t1;
SET GLOBAL wsrep_forced_binlog_format='none';
--connection node_1
SET GLOBAL wsrep_forced_binlog_format='none';
drop table t1;
##
## Check the operation when the automatic control over the auto-increment
## settings is switched off, that is, when we use the increment step and
## the offset specified by the user. In the current session, the binlog
## format is set to 'ROW'. It is important that the values of the
## auto-increment options does not changed on other node - it allows us
## to check the correct transmission of the auto-increment options to
## other nodes:
##
SET SESSION binlog_format='ROW';
show variables like 'binlog_format';
SET GLOBAL wsrep_auto_increment_control='OFF';
SET SESSION auto_increment_increment = 3;
SET SESSION auto_increment_offset = 1;
CREATE TABLE t1 (
i int(11) NOT NULL AUTO_INCREMENT,
c char(32) DEFAULT 'dummy_text',
PRIMARY KEY (i)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1(i) values(null);
select * from t1;
insert into t1(i) values(null), (null), (null);
select * from t1;
--connection node_2
select * from t1;
--connection node_1
##
## Verify the return to automatic calculation of the step
## and offset of the auto-increment:
##
SET GLOBAL wsrep_auto_increment_control='ON';
show variables like 'binlog_format';
show variables like '%auto_increment%';
##
## Verify the recovery of original user-defined values after
## stopping the automatic control over auto-increment:
##
SET GLOBAL wsrep_auto_increment_control='OFF';
show variables like '%auto_increment%';
##
## Restore original options and drop test table:
##
SET GLOBAL wsrep_auto_increment_control='ON';
drop table t1;
--source include/auto_increment_offset_restore.inc

View file

@ -1329,6 +1329,17 @@ public:
/* Hash value */
virtual void hash(ulong *nr, ulong *nr2);
/**
Get the upper limit of the MySQL integral and floating-point type.
@return maximum allowed value for the field
*/
virtual ulonglong get_max_int_value() const
{
DBUG_ASSERT(false);
return 0ULL;
}
/**
Checks whether a string field is part of write_set.
@ -1796,6 +1807,11 @@ public:
*to= *from;
return from + 1;
}
virtual ulonglong get_max_int_value() const
{
return unsigned_flag ? 0xFFULL : 0x7FULL;
}
};
@ -1837,6 +1853,10 @@ public:
virtual const uchar *unpack(uchar* to, const uchar *from,
const uchar *from_end, uint param_data)
{ return unpack_int16(to, from, from_end); }
virtual ulonglong get_max_int_value() const
{
return unsigned_flag ? 0xFFFFULL : 0x7FFFULL;
}
};
class Field_medium :public Field_num {
@ -1870,6 +1890,10 @@ public:
{
return Field::pack(to, from, max_length);
}
virtual ulonglong get_max_int_value() const
{
return unsigned_flag ? 0xFFFFFFULL : 0x7FFFFFULL;
}
};
@ -1915,6 +1939,10 @@ public:
{
return unpack_int32(to, from, from_end);
}
virtual ulonglong get_max_int_value() const
{
return unsigned_flag ? 0xFFFFFFFFULL : 0x7FFFFFFFULL;
}
};
@ -1964,6 +1992,10 @@ public:
{
return unpack_int64(to, from, from_end);
}
virtual ulonglong get_max_int_value() const
{
return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL;
}
};
@ -1997,6 +2029,13 @@ public:
uint32 pack_length() const { return sizeof(float); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
virtual ulonglong get_max_int_value() const
{
/*
We use the maximum as per IEEE754-2008 standard, 2^24
*/
return 0x1000000ULL;
}
private:
int do_save_field_metadata(uchar *first_byte);
};
@ -2039,6 +2078,13 @@ public:
uint32 pack_length() const { return sizeof(double); }
uint row_pack_length() const { return pack_length(); }
void sql_type(String &str) const;
virtual ulonglong get_max_int_value() const
{
/*
We use the maximum as per IEEE754-2008 standard, 2^53
*/
return 0x20000000000000ULL;
}
private:
int do_save_field_metadata(uchar *first_byte);
};

View file

@ -2853,9 +2853,15 @@ compute_next_insert_id(ulonglong nr,struct system_variables *variables)
nr= nr + 1; // optimization of the formula below
else
{
/*
Calculating the number of complete auto_increment_increment extents:
*/
nr= (((nr+ variables->auto_increment_increment -
variables->auto_increment_offset)) /
(ulonglong) variables->auto_increment_increment);
/*
Adding an offset to the auto_increment_increment extent boundary:
*/
nr= (nr* (ulonglong) variables->auto_increment_increment +
variables->auto_increment_offset);
}
@ -2911,8 +2917,14 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
}
if (variables->auto_increment_increment == 1)
return nr; // optimization of the formula below
/*
Calculating the number of complete auto_increment_increment extents:
*/
nr= (((nr - variables->auto_increment_offset)) /
(ulonglong) variables->auto_increment_increment);
/*
Adding an offset to the auto_increment_increment extent boundary:
*/
return (nr * (ulonglong) variables->auto_increment_increment +
variables->auto_increment_offset);
}
@ -3134,10 +3146,23 @@ int handler::update_auto_increment()
if (unlikely(tmp)) // Out of range value in store
{
/*
It's better to return an error here than getting a confusing
'duplicate key error' later.
first test if the query was aborted due to strict mode constraints
*/
result= HA_ERR_AUTOINC_ERANGE;
if (thd->killed == KILL_BAD_DATA ||
nr > table->next_number_field->get_max_int_value())
DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
/*
field refused this value (overflow) and truncated it, use the result of
the truncation (which is going to be inserted); however we try to
decrease it to honour auto_increment_* variables.
That will shift the left bound of the reserved interval, we don't
bother shifting the right bound (anyway any other value from this
interval will cause a duplicate key).
*/
nr= prev_insert_id(table->next_number_field->val_int(), variables);
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
nr= table->next_number_field->val_int();
}
if (append)
{

View file

@ -4193,6 +4193,20 @@ static int init_common_variables()
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
server_version, SYSTEM_TYPE,MACHINE_TYPE));
#ifdef WITH_WSREP
/*
We need to initialize auxiliary variables, that will be
further keep the original values of auto-increment options
as they set by the user. These variables used to restore
user-defined values of the auto-increment options after
setting of the wsrep_auto_increment_control to 'OFF'.
*/
global_system_variables.saved_auto_increment_increment=
global_system_variables.auto_increment_increment;
global_system_variables.saved_auto_increment_offset=
global_system_variables.auto_increment_offset;
#endif /* WITH_WSREP */
#ifdef HAVE_LARGE_PAGES
/* Initialize large page size */
if (opt_large_pages)

View file

@ -552,6 +552,17 @@ typedef struct system_variables
ha_rows max_join_size;
ha_rows expensive_subquery_limit;
ulong auto_increment_increment, auto_increment_offset;
#ifdef WITH_WSREP
/*
Variables with stored values of the auto_increment_increment
and auto_increment_offset options that are will be needed when
wsrep_auto_increment_control will be set to 'OFF', because the
setting it to 'ON' leads to overwriting of the original values
(which are set by the user) by calculated values (which are
based on the cluster's size):
*/
ulong saved_auto_increment_increment, saved_auto_increment_offset;
#endif /* WITH_WSREP */
ulong lock_wait_timeout;
ulong join_cache_level;
ulong max_allowed_packet;

View file

@ -345,13 +345,56 @@ static Sys_var_long Sys_pfs_connect_attrs_size(
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
#ifdef WITH_WSREP
/*
We need to keep the original values set by the user, as they will
be lost if wsrep_auto_increment_control set to 'ON':
*/
static bool update_auto_increment_increment (sys_var *self, THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.saved_auto_increment_increment=
global_system_variables.auto_increment_increment;
else
thd->variables.saved_auto_increment_increment=
thd->variables.auto_increment_increment;
return false;
}
#endif /* WITH_WSREP */
static Sys_var_ulong Sys_auto_increment_increment(
"auto_increment_increment",
"Auto-increment columns are incremented by this",
SESSION_VAR(auto_increment_increment),
CMD_LINE(OPT_ARG),
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
#ifdef WITH_WSREP
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_auto_increment_increment));
#else
NO_MUTEX_GUARD, IN_BINLOG);
#endif /* WITH_WSREP */
#ifdef WITH_WSREP
/*
We need to keep the original values set by the user, as they will
be lost if wsrep_auto_increment_control set to 'ON':
*/
static bool update_auto_increment_offset (sys_var *self, THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.saved_auto_increment_offset=
global_system_variables.auto_increment_offset;
else
thd->variables.saved_auto_increment_offset=
thd->variables.auto_increment_offset;
return false;
}
#endif /* WITH_WSREP */
static Sys_var_ulong Sys_auto_increment_offset(
"auto_increment_offset",
@ -360,7 +403,12 @@ static Sys_var_ulong Sys_auto_increment_offset(
SESSION_VAR(auto_increment_offset),
CMD_LINE(OPT_ARG),
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
#ifdef WITH_WSREP
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_auto_increment_offset));
#else
NO_MUTEX_GUARD, IN_BINLOG);
#endif /* WITH_WSREP */
static Sys_var_mybool Sys_automatic_sp_privileges(
"automatic_sp_privileges",
@ -4847,11 +4895,54 @@ static Sys_var_ulong Sys_wsrep_retry_autocommit(
SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, 10000), DEFAULT(1), BLOCK_SIZE(1));
static bool update_wsrep_auto_increment_control (sys_var *self, THD *thd, enum_var_type type)
{
if (wsrep_auto_increment_control)
{
/*
The variables that control auto increment shall be calculated
automaticaly based on the size of the cluster. This usually done
within the wsrep_view_handler_cb callback. However, if the user
manually sets the value of wsrep_auto_increment_control to 'ON',
then we should to re-calculate these variables again (because
these values may be required before wsrep_view_handler_cb will
be re-invoked, which is rarely invoked if the cluster stays in
the stable state):
*/
global_system_variables.auto_increment_increment=
wsrep_cluster_size ? wsrep_cluster_size : 1;
global_system_variables.auto_increment_offset=
wsrep_local_index >= 0 ? wsrep_local_index + 1 : 1;
thd->variables.auto_increment_increment=
global_system_variables.auto_increment_increment;
thd->variables.auto_increment_offset=
global_system_variables.auto_increment_offset;
}
else
{
/*
We must restore the last values of the variables that
are explicitly specified by the user:
*/
global_system_variables.auto_increment_increment=
global_system_variables.saved_auto_increment_increment;
global_system_variables.auto_increment_offset=
global_system_variables.saved_auto_increment_offset;
thd->variables.auto_increment_increment=
thd->variables.saved_auto_increment_increment;
thd->variables.auto_increment_offset=
thd->variables.saved_auto_increment_offset;
}
return false;
}
static Sys_var_mybool Sys_wsrep_auto_increment_control(
"wsrep_auto_increment_control", "To automatically control the "
"assignment of autoincrement variables",
GLOBAL_VAR(wsrep_auto_increment_control),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_wsrep_auto_increment_control));
static Sys_var_mybool Sys_wsrep_drupal_282555_workaround(
"wsrep_drupal_282555_workaround", "Enable a workaround to handle the "

View file

@ -161,6 +161,10 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd);
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
extern "C" void wsrep_thd_auto_increment_variables(THD*,
unsigned long long *offset,
unsigned long long *increment);
extern void wsrep_close_client_connections(my_bool wait_to_end);
extern int wsrep_wait_committing_connections_close(int wait_time);
extern void wsrep_close_applier(THD *thd);

View file

@ -676,3 +676,25 @@ bool wsrep_thd_has_explicit_locks(THD *thd)
assert(thd);
return thd->mdl_context.has_explicit_locks();
}
/*
Get auto increment variables for THD. Use global settings for
applier threads.
*/
extern "C"
void wsrep_thd_auto_increment_variables(THD* thd,
unsigned long long* offset,
unsigned long long* increment)
{
if (thd->wsrep_exec_mode == REPL_RECV &&
thd->wsrep_conflict_state != REPLAYING)
{
*offset= global_system_variables.auto_increment_offset;
*increment= global_system_variables.auto_increment_increment;
}
else
{
*offset= thd->variables.auto_increment_offset;
*increment= thd->variables.auto_increment_increment;
}
}

View file

@ -8396,14 +8396,29 @@ set_max_autoinc:
/* This should filter out the negative
values set explicitly by the user. */
if (auto_inc <= col_max_value) {
ut_a(prebuilt->autoinc_increment > 0);
ulonglong offset;
ulonglong increment;
dberr_t err;
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
/* Applier threads which are
processing ROW events and don't go
through server level autoinc
processing, therefore m_prebuilt
autoinc values don't get
properly assigned. Fetch values from
server side. */
if (wsrep_on(current_thd) &&
wsrep_thd_exec_mode(current_thd) == REPL_RECV) {
wsrep_thd_auto_increment_variables(current_thd, &offset, &increment);
} else {
#endif /* WITH_WSREP */
ut_a(prebuilt->autoinc_increment > 0);
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
auto_inc = innobase_next_autoinc(
auto_inc,
@ -8918,16 +8933,32 @@ ha_innobase::update_row(
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
col_max_value =
table->next_number_field->get_max_int_value();
if (auto_inc <= col_max_value && auto_inc != 0) {
ulonglong offset;
ulonglong increment;
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
/* Applier threads which are processing
ROW events and don't go through server
level autoinc processing, therefore
m_prebuilt autoinc values don't get
properly assigned. Fetch values from
server side. */
if (wsrep_on(current_thd) &&
wsrep_thd_exec_mode(current_thd) == REPL_RECV) {
wsrep_thd_auto_increment_variables(
current_thd, &offset, &increment);
} else {
#endif /* WITH_WSREP */
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
auto_inc = innobase_next_autoinc(
auto_inc, 1, increment, offset, col_max_value);
@ -16038,13 +16069,13 @@ ha_innobase::get_auto_increment(
increment,
thd_get_thread_id(ha_thd()),
current, autoinc);
if (!wsrep_on(ha_thd()))
{
current = autoinc - prebuilt->autoinc_increment;
}
current = innobase_next_autoinc(
current, 1, increment, offset, col_max_value);
if (!wsrep_on(ha_thd())) {
current = autoinc - prebuilt->autoinc_increment;
current = innobase_next_autoinc(
current, 1, increment, offset, col_max_value);
}
dict_table_autoinc_initialize(prebuilt->table, current);

View file

@ -8988,8 +8988,25 @@ set_max_autoinc:
ulonglong increment;
dberr_t err;
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
/* Applier threads which are
processing ROW events and don't go
through server level autoinc
processing, therefore m_prebuilt
autoinc values don't get
properly assigned. Fetch values from
server side. */
if (wsrep_on(current_thd) &&
wsrep_thd_exec_mode(current_thd) == REPL_RECV) {
wsrep_thd_auto_increment_variables(current_thd, &offset, &increment);
} else {
#endif /* WITH_WSREP */
ut_a(prebuilt->autoinc_increment > 0);
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
auto_inc = innobase_next_autoinc(
auto_inc,
@ -9502,16 +9519,32 @@ ha_innobase::update_row(
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
col_max_value =
table->next_number_field->get_max_int_value();
if (auto_inc <= col_max_value && auto_inc != 0) {
ulonglong offset;
ulonglong increment;
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
/* Applier threads which are processing
ROW events and don't go through server
level autoinc processing, therefore
m_prebuilt autoinc values don't get
properly assigned. Fetch values from
server side. */
if (wsrep_on(current_thd) &&
wsrep_thd_exec_mode(current_thd) == REPL_RECV) {
wsrep_thd_auto_increment_variables(
current_thd, &offset, &increment);
} else {
#endif /* WITH_WSREP */
offset = prebuilt->autoinc_offset;
increment = prebuilt->autoinc_increment;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
auto_inc = innobase_next_autoinc(
auto_inc, 1, increment, offset, col_max_value);
@ -16742,13 +16775,13 @@ ha_innobase::get_auto_increment(
increment,
thd_get_thread_id(ha_thd()),
current, autoinc);
if (!wsrep_on(ha_thd()))
{
current = autoinc - prebuilt->autoinc_increment;
}
current = innobase_next_autoinc(
current, 1, increment, offset, col_max_value);
if (!wsrep_on(ha_thd())) {
current = autoinc - prebuilt->autoinc_increment;
current = innobase_next_autoinc(
current, 1, increment, offset, col_max_value);
}
dict_table_autoinc_initialize(prebuilt->table, current);