MDEV-9519: Data corruption will happen on the Galera cluster size change
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. In the title of the MDEV-9519 it was proposed to ban start slave on a Galera if master binlog_format = statement and wsrep_auto_increment_control = 1, but the problem can be solved without such a restriction. 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). https://jira.mariadb.org/browse/MDEV-9519
This commit is contained in:
parent
28cb041754
commit
243f829c1c
@ -107,6 +107,7 @@ extern struct wsrep_service_st {
|
|||||||
bool (*wsrep_thd_ignore_table_func)(THD *thd);
|
bool (*wsrep_thd_ignore_table_func)(THD *thd);
|
||||||
long long (*wsrep_thd_trx_seqno_func)(THD *thd);
|
long long (*wsrep_thd_trx_seqno_func)(THD *thd);
|
||||||
struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd);
|
struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd);
|
||||||
|
void (*wsrep_thd_auto_increment_variables_func)(THD *thd, unsigned long long *offset, unsigned long long *increment);
|
||||||
int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd);
|
int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd);
|
||||||
int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD);
|
int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD);
|
||||||
void (*wsrep_unlock_rollback_func)();
|
void (*wsrep_unlock_rollback_func)();
|
||||||
@ -149,6 +150,7 @@ extern struct wsrep_service_st {
|
|||||||
#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T)
|
#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T)
|
||||||
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
|
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
|
||||||
#define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T)
|
#define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T)
|
||||||
|
#define wsrep_thd_auto_increment_variables(T,O,I) wsrep_service->wsrep_thd_auto_increment_variables_func(T,O,I)
|
||||||
#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T)
|
#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T)
|
||||||
#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2)
|
#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2)
|
||||||
#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func()
|
#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func()
|
||||||
@ -201,6 +203,7 @@ my_bool wsrep_thd_is_BF(MYSQL_THD thd, my_bool sync);
|
|||||||
my_bool wsrep_thd_is_wsrep(MYSQL_THD thd);
|
my_bool wsrep_thd_is_wsrep(MYSQL_THD thd);
|
||||||
struct wsrep *get_wsrep();
|
struct wsrep *get_wsrep();
|
||||||
struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd);
|
struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd);
|
||||||
|
void wsrep_thd_auto_increment_variables(THD *thd, unsigned long long *offset, unsigned long long *increment);
|
||||||
void wsrep_aborting_thd_enqueue(THD *thd);
|
void wsrep_aborting_thd_enqueue(THD *thd);
|
||||||
void wsrep_lock_rollback();
|
void wsrep_lock_rollback();
|
||||||
void wsrep_post_commit(THD* thd, bool all);
|
void wsrep_post_commit(THD* thd, bool all);
|
||||||
|
@ -25,7 +25,6 @@ galera.MW-329 : wsrep_local_replays not stable
|
|||||||
MW-416 : MDEV-13549 Galera test failures
|
MW-416 : MDEV-13549 Galera test failures
|
||||||
MW-388 : MDEV-13549 Galera test failures
|
MW-388 : MDEV-13549 Galera test failures
|
||||||
galera_sst_mysqldump_with_key : MDEV-16890 Galera test failure
|
galera_sst_mysqldump_with_key : MDEV-16890 Galera test failure
|
||||||
galera_binlog_stmt_autoinc: MDEV-17106 Test failure on galera.galera_binlog_stmt_autoinc
|
|
||||||
galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit
|
galera_gc_fc_limit : MDEV-17061 Test failure on galera.galera_gc_fc_limit
|
||||||
galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion
|
galera_as_slave_replication_budle : MDEV-15785 Test case galera_as_slave_replication_bundle caused debug assertion
|
||||||
galera_wan : MDEV-17259: Test failure on galera.galera_wan
|
galera_wan : MDEV-17259: Test failure on galera.galera_wan
|
||||||
|
@ -8,20 +8,20 @@ PRIMARY KEY (i)
|
|||||||
insert into t1(i) values(null);
|
insert into t1(i) values(null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
3 dummy_text
|
1 dummy_text
|
||||||
insert into t1(i) values(null), (null), (null);
|
insert into t1(i) values(null), (null), (null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
3 dummy_text
|
3 dummy_text
|
||||||
5 dummy_text
|
5 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
9 dummy_text
|
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
3 dummy_text
|
3 dummy_text
|
||||||
5 dummy_text
|
5 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
9 dummy_text
|
|
||||||
SET GLOBAL wsrep_forced_binlog_format='none';
|
SET GLOBAL wsrep_forced_binlog_format='none';
|
||||||
SET GLOBAL wsrep_forced_binlog_format='none';
|
SET GLOBAL wsrep_forced_binlog_format='none';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
@ -40,20 +40,20 @@ PRIMARY KEY (i)
|
|||||||
insert into t1(i) values(null);
|
insert into t1(i) values(null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
4 dummy_text
|
1 dummy_text
|
||||||
insert into t1(i) values(null), (null), (null);
|
insert into t1(i) values(null), (null), (null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
4 dummy_text
|
4 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
10 dummy_text
|
10 dummy_text
|
||||||
13 dummy_text
|
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
4 dummy_text
|
4 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
10 dummy_text
|
10 dummy_text
|
||||||
13 dummy_text
|
|
||||||
SET GLOBAL wsrep_auto_increment_control='ON';
|
SET GLOBAL wsrep_auto_increment_control='ON';
|
||||||
SET SESSION binlog_format='ROW';
|
SET SESSION binlog_format='ROW';
|
||||||
show variables like 'binlog_format';
|
show variables like 'binlog_format';
|
||||||
@ -67,7 +67,7 @@ wsrep_auto_increment_control ON
|
|||||||
SET GLOBAL wsrep_auto_increment_control='OFF';
|
SET GLOBAL wsrep_auto_increment_control='OFF';
|
||||||
show variables like '%auto_increment%';
|
show variables like '%auto_increment%';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
auto_increment_increment 2
|
auto_increment_increment 3
|
||||||
auto_increment_offset 1
|
auto_increment_offset 1
|
||||||
wsrep_auto_increment_control OFF
|
wsrep_auto_increment_control OFF
|
||||||
SET GLOBAL wsrep_auto_increment_control='ON';
|
SET GLOBAL wsrep_auto_increment_control='ON';
|
||||||
@ -82,20 +82,20 @@ PRIMARY KEY (i)
|
|||||||
insert into t1(i) values(null);
|
insert into t1(i) values(null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
3 dummy_text
|
1 dummy_text
|
||||||
insert into t1(i) values(null), (null), (null);
|
insert into t1(i) values(null), (null), (null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
3 dummy_text
|
3 dummy_text
|
||||||
5 dummy_text
|
5 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
9 dummy_text
|
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
3 dummy_text
|
3 dummy_text
|
||||||
5 dummy_text
|
5 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
9 dummy_text
|
|
||||||
SET GLOBAL wsrep_forced_binlog_format='none';
|
SET GLOBAL wsrep_forced_binlog_format='none';
|
||||||
SET GLOBAL wsrep_forced_binlog_format='none';
|
SET GLOBAL wsrep_forced_binlog_format='none';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
@ -114,20 +114,20 @@ PRIMARY KEY (i)
|
|||||||
insert into t1(i) values(null);
|
insert into t1(i) values(null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
4 dummy_text
|
1 dummy_text
|
||||||
insert into t1(i) values(null), (null), (null);
|
insert into t1(i) values(null), (null), (null);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
4 dummy_text
|
4 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
10 dummy_text
|
10 dummy_text
|
||||||
13 dummy_text
|
|
||||||
select * from t1;
|
select * from t1;
|
||||||
i c
|
i c
|
||||||
|
1 dummy_text
|
||||||
4 dummy_text
|
4 dummy_text
|
||||||
7 dummy_text
|
7 dummy_text
|
||||||
10 dummy_text
|
10 dummy_text
|
||||||
13 dummy_text
|
|
||||||
SET GLOBAL wsrep_auto_increment_control='ON';
|
SET GLOBAL wsrep_auto_increment_control='ON';
|
||||||
show variables like 'binlog_format';
|
show variables like 'binlog_format';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
@ -140,7 +140,7 @@ wsrep_auto_increment_control ON
|
|||||||
SET GLOBAL wsrep_auto_increment_control='OFF';
|
SET GLOBAL wsrep_auto_increment_control='OFF';
|
||||||
show variables like '%auto_increment%';
|
show variables like '%auto_increment%';
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
auto_increment_increment 2
|
auto_increment_increment 3
|
||||||
auto_increment_offset 1
|
auto_increment_offset 1
|
||||||
wsrep_auto_increment_control OFF
|
wsrep_auto_increment_control OFF
|
||||||
SET GLOBAL wsrep_auto_increment_control='ON';
|
SET GLOBAL wsrep_auto_increment_control='ON';
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY) PARTITION BY KEY (pk) PARTITIONS 2;
|
||||||
|
INSERT INTO t1 VALUES (NULL),(NULL);
|
||||||
|
UPDATE t1 SET pk = 2147483647;
|
||||||
|
ERROR 23000: Duplicate entry '2147483647' for key 'PRIMARY'
|
||||||
|
REPLACE INTO t1 VALUES (NULL);
|
||||||
|
ERROR 22003: Out of range value for column 'pk' at row 1
|
||||||
|
DROP TABLE t1;
|
12
mysql-test/suite/parts/t/partition_auto_increment_max.test
Normal file
12
mysql-test/suite/parts/t/partition_auto_increment_max.test
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
--source include/have_partition.inc
|
||||||
|
--source include/have_log_bin.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY) PARTITION BY KEY (pk) PARTITIONS 2;
|
||||||
|
INSERT INTO t1 VALUES (NULL),(NULL);
|
||||||
|
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
UPDATE t1 SET pk = 2147483647;
|
||||||
|
--error HA_ERR_AUTOINC_ERANGE
|
||||||
|
REPLACE INTO t1 VALUES (NULL);
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
49
sql/field.h
49
sql/field.h
@ -1329,6 +1329,17 @@ public:
|
|||||||
/* Hash value */
|
/* Hash value */
|
||||||
virtual void hash(ulong *nr, ulong *nr2);
|
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.
|
Checks whether a string field is part of write_set.
|
||||||
|
|
||||||
@ -1796,6 +1807,11 @@ public:
|
|||||||
*to= *from;
|
*to= *from;
|
||||||
return from + 1;
|
return from + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ulonglong get_max_int_value() const
|
||||||
|
{
|
||||||
|
return unsigned_flag ? 0xFFULL : 0x7FULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1837,6 +1853,11 @@ public:
|
|||||||
virtual const uchar *unpack(uchar* to, const uchar *from,
|
virtual const uchar *unpack(uchar* to, const uchar *from,
|
||||||
const uchar *from_end, uint param_data)
|
const uchar *from_end, uint param_data)
|
||||||
{ return unpack_int16(to, from, from_end); }
|
{ 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 {
|
class Field_medium :public Field_num {
|
||||||
@ -1870,6 +1891,11 @@ public:
|
|||||||
{
|
{
|
||||||
return Field::pack(to, from, max_length);
|
return Field::pack(to, from, max_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ulonglong get_max_int_value() const
|
||||||
|
{
|
||||||
|
return unsigned_flag ? 0xFFFFFFULL : 0x7FFFFFULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1915,6 +1941,11 @@ public:
|
|||||||
{
|
{
|
||||||
return unpack_int32(to, from, from_end);
|
return unpack_int32(to, from, from_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ulonglong get_max_int_value() const
|
||||||
|
{
|
||||||
|
return unsigned_flag ? 0xFFFFFFFFULL : 0x7FFFFFFFULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1964,6 +1995,10 @@ public:
|
|||||||
{
|
{
|
||||||
return unpack_int64(to, from, from_end);
|
return unpack_int64(to, from, from_end);
|
||||||
}
|
}
|
||||||
|
virtual ulonglong get_max_int_value() const
|
||||||
|
{
|
||||||
|
return unsigned_flag ? 0xFFFFFFFFFFFFFFFFULL : 0x7FFFFFFFFFFFFFFFULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1997,6 +2032,13 @@ public:
|
|||||||
uint32 pack_length() const { return sizeof(float); }
|
uint32 pack_length() const { return sizeof(float); }
|
||||||
uint row_pack_length() const { return pack_length(); }
|
uint row_pack_length() const { return pack_length(); }
|
||||||
void sql_type(String &str) const;
|
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:
|
private:
|
||||||
int do_save_field_metadata(uchar *first_byte);
|
int do_save_field_metadata(uchar *first_byte);
|
||||||
};
|
};
|
||||||
@ -2039,6 +2081,13 @@ public:
|
|||||||
uint32 pack_length() const { return sizeof(double); }
|
uint32 pack_length() const { return sizeof(double); }
|
||||||
uint row_pack_length() const { return pack_length(); }
|
uint row_pack_length() const { return pack_length(); }
|
||||||
void sql_type(String &str) const;
|
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:
|
private:
|
||||||
int do_save_field_metadata(uchar *first_byte);
|
int do_save_field_metadata(uchar *first_byte);
|
||||||
};
|
};
|
||||||
|
@ -8706,11 +8706,12 @@ void ha_partition::release_auto_increment()
|
|||||||
m_file[i]->ha_release_auto_increment();
|
m_file[i]->ha_release_auto_increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (next_insert_id)
|
else
|
||||||
{
|
{
|
||||||
ulonglong next_auto_inc_val;
|
|
||||||
lock_auto_increment();
|
lock_auto_increment();
|
||||||
next_auto_inc_val= part_share->next_auto_inc_val;
|
if (next_insert_id)
|
||||||
|
{
|
||||||
|
ulonglong next_auto_inc_val= part_share->next_auto_inc_val;
|
||||||
/*
|
/*
|
||||||
If the current auto_increment values is lower than the reserved
|
If the current auto_increment values is lower than the reserved
|
||||||
value, and the reserved value was reserved by this thread,
|
value, and the reserved value was reserved by this thread,
|
||||||
@ -8729,8 +8730,13 @@ void ha_partition::release_auto_increment()
|
|||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("part_share->next_auto_inc_val: %lu",
|
DBUG_PRINT("info", ("part_share->next_auto_inc_val: %lu",
|
||||||
(ulong) part_share->next_auto_inc_val));
|
(ulong) part_share->next_auto_inc_val));
|
||||||
|
}
|
||||||
/* Unlock the multi row statement lock taken in get_auto_increment */
|
/*
|
||||||
|
Unlock the multi-row statement lock taken in get_auto_increment.
|
||||||
|
These actions must be performed even if the next_insert_id field
|
||||||
|
contains zero, otherwise if the update_auto_increment fails then
|
||||||
|
an unnecessary lock will remain:
|
||||||
|
*/
|
||||||
if (auto_increment_safe_stmt_log_lock)
|
if (auto_increment_safe_stmt_log_lock)
|
||||||
{
|
{
|
||||||
auto_increment_safe_stmt_log_lock= FALSE;
|
auto_increment_safe_stmt_log_lock= FALSE;
|
||||||
|
@ -2854,11 +2854,17 @@ compute_next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||||||
nr= nr + 1; // optimization of the formula below
|
nr= nr + 1; // optimization of the formula below
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nr= (((nr+ variables->auto_increment_increment -
|
/*
|
||||||
variables->auto_increment_offset)) /
|
Calculating the number of complete auto_increment_increment extents:
|
||||||
(ulonglong) variables->auto_increment_increment);
|
*/
|
||||||
nr= (nr* (ulonglong) variables->auto_increment_increment +
|
nr= (nr + variables->auto_increment_increment -
|
||||||
variables->auto_increment_offset);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(nr <= save_nr))
|
if (unlikely(nr <= save_nr))
|
||||||
@ -2912,8 +2918,14 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
|
|||||||
}
|
}
|
||||||
if (variables->auto_increment_increment == 1)
|
if (variables->auto_increment_increment == 1)
|
||||||
return nr; // optimization of the formula below
|
return nr; // optimization of the formula below
|
||||||
nr= (((nr - variables->auto_increment_offset)) /
|
/*
|
||||||
(ulonglong) variables->auto_increment_increment);
|
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 +
|
return (nr * (ulonglong) variables->auto_increment_increment +
|
||||||
variables->auto_increment_offset);
|
variables->auto_increment_offset);
|
||||||
}
|
}
|
||||||
@ -3004,7 +3016,7 @@ int handler::update_auto_increment()
|
|||||||
bool append= FALSE;
|
bool append= FALSE;
|
||||||
THD *thd= table->in_use;
|
THD *thd= table->in_use;
|
||||||
struct system_variables *variables= &thd->variables;
|
struct system_variables *variables= &thd->variables;
|
||||||
int result=0, tmp;
|
int tmp;
|
||||||
enum enum_check_fields save_count_cuted_fields;
|
enum enum_check_fields save_count_cuted_fields;
|
||||||
DBUG_ENTER("handler::update_auto_increment");
|
DBUG_ENTER("handler::update_auto_increment");
|
||||||
|
|
||||||
@ -3135,10 +3147,23 @@ int handler::update_auto_increment()
|
|||||||
if (unlikely(tmp)) // Out of range value in store
|
if (unlikely(tmp)) // Out of range value in store
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
It's better to return an error here than getting a confusing
|
First, test if the query was aborted due to strict mode constraints
|
||||||
'duplicate key error' later.
|
or new field value greater than maximum integer value:
|
||||||
*/
|
*/
|
||||||
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)
|
if (append)
|
||||||
{
|
{
|
||||||
@ -3163,9 +3188,6 @@ int handler::update_auto_increment()
|
|||||||
*/
|
*/
|
||||||
insert_id_for_cur_row= nr;
|
insert_id_for_cur_row= nr;
|
||||||
|
|
||||||
if (result) // overflow
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set next insert id to point to next auto-increment value to be able to
|
Set next insert id to point to next auto-increment value to be able to
|
||||||
handle multi-row statements.
|
handle multi-row statements.
|
||||||
|
@ -4563,6 +4563,20 @@ static int init_common_variables()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,6 +550,16 @@ typedef struct system_variables
|
|||||||
ha_rows max_join_size;
|
ha_rows max_join_size;
|
||||||
ha_rows expensive_subquery_limit;
|
ha_rows expensive_subquery_limit;
|
||||||
ulong auto_increment_increment, auto_increment_offset;
|
ulong auto_increment_increment, auto_increment_offset;
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/*
|
||||||
|
Stored values of the auto_increment_increment and auto_increment_offset
|
||||||
|
that are will be restored 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 ones (which
|
||||||
|
are based on the cluster size):
|
||||||
|
*/
|
||||||
|
ulong saved_auto_increment_increment, saved_auto_increment_offset;
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
ulong lock_wait_timeout;
|
ulong lock_wait_timeout;
|
||||||
ulong join_cache_level;
|
ulong join_cache_level;
|
||||||
ulong max_allowed_packet;
|
ulong max_allowed_packet;
|
||||||
|
@ -1862,7 +1862,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
info->deleted++;
|
info->deleted++;
|
||||||
else
|
else
|
||||||
error= 0;
|
error= 0;
|
||||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
|
||||||
/*
|
/*
|
||||||
Since we pretend that we have done insert we should call
|
Since we pretend that we have done insert we should call
|
||||||
its after triggers.
|
its after triggers.
|
||||||
@ -1903,7 +1902,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
if (table->file->insert_id_for_cur_row == 0)
|
if (table->file->insert_id_for_cur_row == 0)
|
||||||
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
|
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
|
||||||
|
|
||||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
|
||||||
/*
|
/*
|
||||||
Restore column maps if they where replaced during an duplicate key
|
Restore column maps if they where replaced during an duplicate key
|
||||||
problem.
|
problem.
|
||||||
|
@ -177,6 +177,7 @@ static struct wsrep_service_st wsrep_handler = {
|
|||||||
wsrep_thd_ignore_table,
|
wsrep_thd_ignore_table,
|
||||||
wsrep_thd_trx_seqno,
|
wsrep_thd_trx_seqno,
|
||||||
wsrep_thd_ws_handle,
|
wsrep_thd_ws_handle,
|
||||||
|
wsrep_thd_auto_increment_variables,
|
||||||
wsrep_trx_is_aborting,
|
wsrep_trx_is_aborting,
|
||||||
wsrep_trx_order_before,
|
wsrep_trx_order_before,
|
||||||
wsrep_unlock_rollback,
|
wsrep_unlock_rollback,
|
||||||
|
@ -345,13 +345,56 @@ static Sys_var_long Sys_pfs_connect_attrs_size(
|
|||||||
|
|
||||||
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
|
#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(
|
static Sys_var_ulong Sys_auto_increment_increment(
|
||||||
"auto_increment_increment",
|
"auto_increment_increment",
|
||||||
"Auto-increment columns are incremented by this",
|
"Auto-increment columns are incremented by this",
|
||||||
SESSION_VAR(auto_increment_increment),
|
SESSION_VAR(auto_increment_increment),
|
||||||
CMD_LINE(OPT_ARG),
|
CMD_LINE(OPT_ARG),
|
||||||
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
|
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);
|
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(
|
static Sys_var_ulong Sys_auto_increment_offset(
|
||||||
"auto_increment_offset",
|
"auto_increment_offset",
|
||||||
@ -360,7 +403,12 @@ static Sys_var_ulong Sys_auto_increment_offset(
|
|||||||
SESSION_VAR(auto_increment_offset),
|
SESSION_VAR(auto_increment_offset),
|
||||||
CMD_LINE(OPT_ARG),
|
CMD_LINE(OPT_ARG),
|
||||||
VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1),
|
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);
|
NO_MUTEX_GUARD, IN_BINLOG);
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
static Sys_var_mybool Sys_automatic_sp_privileges(
|
static Sys_var_mybool Sys_automatic_sp_privileges(
|
||||||
"automatic_sp_privileges",
|
"automatic_sp_privileges",
|
||||||
@ -4851,11 +4899,54 @@ static Sys_var_ulong Sys_wsrep_retry_autocommit(
|
|||||||
SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG),
|
SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG),
|
||||||
VALID_RANGE(0, 10000), DEFAULT(1), BLOCK_SIZE(1));
|
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(
|
static Sys_var_mybool Sys_wsrep_auto_increment_control(
|
||||||
"wsrep_auto_increment_control", "To automatically control the "
|
"wsrep_auto_increment_control", "To automatically control the "
|
||||||
"assignment of autoincrement variables",
|
"assignment of autoincrement variables",
|
||||||
GLOBAL_VAR(wsrep_auto_increment_control),
|
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(
|
static Sys_var_mybool Sys_wsrep_drupal_282555_workaround(
|
||||||
"wsrep_drupal_282555_workaround", "Enable a workaround to handle the "
|
"wsrep_drupal_282555_workaround", "Enable a workaround to handle the "
|
||||||
|
@ -125,6 +125,14 @@ longlong wsrep_thd_trx_seqno(THD *)
|
|||||||
struct wsrep_ws_handle* wsrep_thd_ws_handle(THD *)
|
struct wsrep_ws_handle* wsrep_thd_ws_handle(THD *)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
||||||
|
void wsrep_thd_auto_increment_variables(THD *thd,
|
||||||
|
unsigned long long *offset,
|
||||||
|
unsigned long long *increment)
|
||||||
|
{
|
||||||
|
*offset= thd->variables.auto_increment_offset;
|
||||||
|
*increment= thd->variables.auto_increment_increment;
|
||||||
|
}
|
||||||
|
|
||||||
int wsrep_trx_is_aborting(THD *)
|
int wsrep_trx_is_aborting(THD *)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
||||||
|
@ -676,3 +676,24 @@ bool wsrep_thd_has_explicit_locks(THD *thd)
|
|||||||
assert(thd);
|
assert(thd);
|
||||||
return thd->mdl_context.has_explicit_locks();
|
return thd->mdl_context.has_explicit_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get auto increment variables for THD. Use global settings for
|
||||||
|
applier threads.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8324,8 +8324,8 @@ no_commit:
|
|||||||
|
|
||||||
/* We need the upper limit of the col type to check for
|
/* We need the upper limit of the col type to check for
|
||||||
whether we update the table autoinc counter or not. */
|
whether we update the table autoinc counter or not. */
|
||||||
col_max_value = innobase_get_int_col_max_value(
|
col_max_value =
|
||||||
table->next_number_field);
|
table->next_number_field->get_max_int_value();
|
||||||
|
|
||||||
/* Get the value that MySQL attempted to store in the table.*/
|
/* Get the value that MySQL attempted to store in the table.*/
|
||||||
auto_inc = table->next_number_field->val_uint();
|
auto_inc = table->next_number_field->val_uint();
|
||||||
@ -8402,15 +8402,33 @@ set_max_autoinc:
|
|||||||
/* This should filter out the negative
|
/* This should filter out the negative
|
||||||
values set explicitly by the user. */
|
values set explicitly by the user. */
|
||||||
if (auto_inc <= col_max_value) {
|
if (auto_inc <= col_max_value) {
|
||||||
ut_a(prebuilt->autoinc_increment > 0);
|
|
||||||
|
|
||||||
ulonglong offset;
|
ulonglong offset;
|
||||||
ulonglong increment;
|
ulonglong increment;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/* Applier threads which are processing
|
||||||
|
ROW events and don't go through server
|
||||||
|
level autoinc processing, therefore
|
||||||
|
prebuilt autoinc values don't get
|
||||||
|
properly assigned. Fetch values from
|
||||||
|
server side. */
|
||||||
|
if (wsrep_on(user_thd) &&
|
||||||
|
wsrep_thd_exec_mode(user_thd) == REPL_RECV)
|
||||||
|
{
|
||||||
|
wsrep_thd_auto_increment_variables(
|
||||||
|
user_thd, &offset, &increment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
ut_a(prebuilt->autoinc_increment > 0);
|
||||||
offset = prebuilt->autoinc_offset;
|
offset = prebuilt->autoinc_offset;
|
||||||
increment = prebuilt->autoinc_increment;
|
increment = prebuilt->autoinc_increment;
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
auto_inc = innobase_next_autoinc(
|
auto_inc = innobase_next_autoinc(
|
||||||
auto_inc,
|
auto_inc,
|
||||||
1, increment, offset,
|
1, increment, offset,
|
||||||
@ -8925,17 +8943,35 @@ ha_innobase::update_row(
|
|||||||
|
|
||||||
/* We need the upper limit of the col type to check for
|
/* We need the upper limit of the col type to check for
|
||||||
whether we update the table autoinc counter or not. */
|
whether we update the table autoinc counter or not. */
|
||||||
col_max_value = innobase_get_int_col_max_value(
|
col_max_value =
|
||||||
table->next_number_field);
|
table->next_number_field->get_max_int_value();
|
||||||
|
|
||||||
if (auto_inc <= col_max_value && auto_inc != 0) {
|
if (auto_inc <= col_max_value && auto_inc != 0) {
|
||||||
|
|
||||||
ulonglong offset;
|
ulonglong offset;
|
||||||
ulonglong increment;
|
ulonglong increment;
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/* Applier threads which are processing
|
||||||
|
ROW events and don't go through server
|
||||||
|
level autoinc processing, therefore
|
||||||
|
prebuilt autoinc values don't get
|
||||||
|
properly assigned. Fetch values from
|
||||||
|
server side. */
|
||||||
|
if (wsrep_on(user_thd) &&
|
||||||
|
wsrep_thd_exec_mode(user_thd) == REPL_RECV)
|
||||||
|
{
|
||||||
|
wsrep_thd_auto_increment_variables(
|
||||||
|
user_thd, &offset, &increment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
offset = prebuilt->autoinc_offset;
|
offset = prebuilt->autoinc_offset;
|
||||||
increment = prebuilt->autoinc_increment;
|
increment = prebuilt->autoinc_increment;
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
auto_inc = innobase_next_autoinc(
|
auto_inc = innobase_next_autoinc(
|
||||||
auto_inc, 1, increment, offset, col_max_value);
|
auto_inc, 1, increment, offset, col_max_value);
|
||||||
|
|
||||||
@ -16041,10 +16077,9 @@ ha_innobase::get_auto_increment(
|
|||||||
if (!wsrep_on(ha_thd()))
|
if (!wsrep_on(ha_thd()))
|
||||||
{
|
{
|
||||||
current = autoinc - prebuilt->autoinc_increment;
|
current = autoinc - prebuilt->autoinc_increment;
|
||||||
}
|
|
||||||
|
|
||||||
current = innobase_next_autoinc(
|
current = innobase_next_autoinc(
|
||||||
current, 1, increment, offset, col_max_value);
|
current, 1, increment, offset, col_max_value);
|
||||||
|
}
|
||||||
|
|
||||||
dict_table_autoinc_initialize(prebuilt->table, current);
|
dict_table_autoinc_initialize(prebuilt->table, current);
|
||||||
|
|
||||||
|
@ -8911,8 +8911,8 @@ no_commit:
|
|||||||
|
|
||||||
/* We need the upper limit of the col type to check for
|
/* We need the upper limit of the col type to check for
|
||||||
whether we update the table autoinc counter or not. */
|
whether we update the table autoinc counter or not. */
|
||||||
col_max_value = innobase_get_int_col_max_value(
|
col_max_value =
|
||||||
table->next_number_field);
|
table->next_number_field->get_max_int_value();
|
||||||
|
|
||||||
/* Get the value that MySQL attempted to store in the table.*/
|
/* Get the value that MySQL attempted to store in the table.*/
|
||||||
auto_inc = table->next_number_field->val_uint();
|
auto_inc = table->next_number_field->val_uint();
|
||||||
@ -8989,15 +8989,33 @@ set_max_autoinc:
|
|||||||
/* This should filter out the negative
|
/* This should filter out the negative
|
||||||
values set explicitly by the user. */
|
values set explicitly by the user. */
|
||||||
if (auto_inc <= col_max_value) {
|
if (auto_inc <= col_max_value) {
|
||||||
ut_a(prebuilt->autoinc_increment > 0);
|
|
||||||
|
|
||||||
ulonglong offset;
|
ulonglong offset;
|
||||||
ulonglong increment;
|
ulonglong increment;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/* Applier threads which are processing
|
||||||
|
ROW events and don't go through server
|
||||||
|
level autoinc processing, therefore
|
||||||
|
prebuilt autoinc values don't get
|
||||||
|
properly assigned. Fetch values from
|
||||||
|
server side. */
|
||||||
|
if (wsrep_on(user_thd) &&
|
||||||
|
wsrep_thd_exec_mode(user_thd) == REPL_RECV)
|
||||||
|
{
|
||||||
|
wsrep_thd_auto_increment_variables(
|
||||||
|
user_thd, &offset, &increment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
ut_a(prebuilt->autoinc_increment > 0);
|
||||||
offset = prebuilt->autoinc_offset;
|
offset = prebuilt->autoinc_offset;
|
||||||
increment = prebuilt->autoinc_increment;
|
increment = prebuilt->autoinc_increment;
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
auto_inc = innobase_next_autoinc(
|
auto_inc = innobase_next_autoinc(
|
||||||
auto_inc,
|
auto_inc,
|
||||||
1, increment, offset,
|
1, increment, offset,
|
||||||
@ -9509,17 +9527,35 @@ ha_innobase::update_row(
|
|||||||
|
|
||||||
/* We need the upper limit of the col type to check for
|
/* We need the upper limit of the col type to check for
|
||||||
whether we update the table autoinc counter or not. */
|
whether we update the table autoinc counter or not. */
|
||||||
col_max_value = innobase_get_int_col_max_value(
|
col_max_value =
|
||||||
table->next_number_field);
|
table->next_number_field->get_max_int_value();
|
||||||
|
|
||||||
if (auto_inc <= col_max_value && auto_inc != 0) {
|
if (auto_inc <= col_max_value && auto_inc != 0) {
|
||||||
|
|
||||||
ulonglong offset;
|
ulonglong offset;
|
||||||
ulonglong increment;
|
ulonglong increment;
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/* Applier threads which are processing
|
||||||
|
ROW events and don't go through server
|
||||||
|
level autoinc processing, therefore
|
||||||
|
prebuilt autoinc values don't get
|
||||||
|
properly assigned. Fetch values from
|
||||||
|
server side. */
|
||||||
|
if (wsrep_on(user_thd) &&
|
||||||
|
wsrep_thd_exec_mode(user_thd) == REPL_RECV)
|
||||||
|
{
|
||||||
|
wsrep_thd_auto_increment_variables(
|
||||||
|
user_thd, &offset, &increment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
offset = prebuilt->autoinc_offset;
|
offset = prebuilt->autoinc_offset;
|
||||||
increment = prebuilt->autoinc_increment;
|
increment = prebuilt->autoinc_increment;
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
auto_inc = innobase_next_autoinc(
|
auto_inc = innobase_next_autoinc(
|
||||||
auto_inc, 1, increment, offset, col_max_value);
|
auto_inc, 1, increment, offset, col_max_value);
|
||||||
|
|
||||||
@ -16745,10 +16781,9 @@ ha_innobase::get_auto_increment(
|
|||||||
if (!wsrep_on(ha_thd()))
|
if (!wsrep_on(ha_thd()))
|
||||||
{
|
{
|
||||||
current = autoinc - prebuilt->autoinc_increment;
|
current = autoinc - prebuilt->autoinc_increment;
|
||||||
}
|
|
||||||
|
|
||||||
current = innobase_next_autoinc(
|
current = innobase_next_autoinc(
|
||||||
current, 1, increment, offset, col_max_value);
|
current, 1, increment, offset, col_max_value);
|
||||||
|
}
|
||||||
|
|
||||||
dict_table_autoinc_initialize(prebuilt->table, current);
|
dict_table_autoinc_initialize(prebuilt->table, current);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user