From 75e7132fca1c4634d4aa8d18d386c55932a5e1b6 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 23 Nov 2020 14:12:30 +0400 Subject: [PATCH] MDEV-21842 auto_increment does not increment with compound primary key on partitioned table. The idea of this fix is that it's enough to prevent the next_auto_inc_val from incrementing if an error, to fix this problem and also the MDEV-17333. So this patch basically reverts the existing fix to the MDEV-17333. --- .../main/auto_increment_ranges_innodb.result | 48 +++++++++++++++ .../main/auto_increment_ranges_innodb.test | 59 +++++++++++++++++++ mysql-test/main/partition_innodb.result | 2 +- sql/ha_partition.cc | 2 +- sql/ha_partition.h | 20 ------- sql/handler.h | 16 +---- sql/sql_insert.cc | 8 +-- storage/mroonga/ha_mroonga.hpp | 5 -- 8 files changed, 114 insertions(+), 46 deletions(-) diff --git a/mysql-test/main/auto_increment_ranges_innodb.result b/mysql-test/main/auto_increment_ranges_innodb.result index 61eccc6f944..7800099200f 100644 --- a/mysql-test/main/auto_increment_ranges_innodb.result +++ b/mysql-test/main/auto_increment_ranges_innodb.result @@ -289,3 +289,51 @@ pk f 5 a 6 <=== drop table t1; +# +# MDEV-21842: auto_increment does not increment with compound primary +# key on partitioned table +# +create or replace table `t` ( +`id` bigint(20) unsigned not null auto_increment, +`a` int(10) not null , +`dt` date not null, +primary key (`id`, `dt`) , +unique key (`a`, `dt`) +) +partition by range columns(`dt`) +( +partition `p202002` values less than ('2020-03-01'), +partition `P202003` values less than ('2020-04-01') +); +connect con1, localhost, root,,; +connect con2, localhost, root,,; +connection con1; +start transaction; +insert into t (a, dt) values (1, '2020-02-29'); +connection con2; +start transaction; +insert into t (a, dt) values (1, '2020-02-29'); +connection con1; +insert into t (a, dt) values (2, '2020-02-29'); +select auto_increment from information_schema.tables where table_name='t'; +auto_increment +4 +commit; +connection con2; +ERROR 23000: Duplicate entry '1-2020-02-29' for key 'a' +connection con1; +select auto_increment from information_schema.tables where table_name='t'; +auto_increment +4 +insert into t (a, dt) values (3, '2020-02-29'); +insert into t (a, dt) values (4, '2020-02-29'); +disconnect con1; +disconnect con2; +connection default; +select * from t; +id a dt +1 1 2020-02-29 +3 2 2020-02-29 +4 3 2020-02-29 +5 4 2020-02-29 +drop table t; diff --git a/mysql-test/main/auto_increment_ranges_innodb.test b/mysql-test/main/auto_increment_ranges_innodb.test index 016ca16bd91..92d377eb147 100644 --- a/mysql-test/main/auto_increment_ranges_innodb.test +++ b/mysql-test/main/auto_increment_ranges_innodb.test @@ -18,3 +18,62 @@ select * from t1; drop table t1; --let $datadir=`select @@datadir` --remove_file $datadir/test/load.data + +--echo # +--echo # MDEV-21842: auto_increment does not increment with compound primary +--echo # key on partitioned table +--echo # + +create or replace table `t` ( + `id` bigint(20) unsigned not null auto_increment, + `a` int(10) not null , + `dt` date not null, + primary key (`id`, `dt`) , + unique key (`a`, `dt`) +) + partition by range columns(`dt`) +( + partition `p202002` values less than ('2020-03-01'), + partition `P202003` values less than ('2020-04-01') +); + +connect (con1, localhost, root,,); +connect (con2, localhost, root,,); + +--connection con1 +start transaction; +insert into t (a, dt) values (1, '2020-02-29'); + +--connection con2 +start transaction; +let $conn2_id= `SELECT CONNECTION_ID()`; +send insert into t (a, dt) values (1, '2020-02-29'); + +--connection con1 +# Ensure that the above insert via conn2 increments next_auto_inc_val +# before the following insert via conn1 starts. +let $wait_condition=select 1 from Information_schema.INNODB_TRX + where trx_mysql_thread_id = $conn2_id and trx_state = 'LOCK WAIT' + and trx_query = "insert into t (a, dt) values (1, '2020-02-29')"; +--source include/wait_condition.inc + +insert into t (a, dt) values (2, '2020-02-29'); +select auto_increment from information_schema.tables where table_name='t'; +commit; + +--connection con2 +--error ER_DUP_ENTRY +reap; + +--connection con1 +select auto_increment from information_schema.tables where table_name='t'; +insert into t (a, dt) values (3, '2020-02-29'); +insert into t (a, dt) values (4, '2020-02-29'); + +disconnect con1; +disconnect con2; + +--connection default +select * from t; +drop table t; + diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index 70bfa4840ee..1a823c37760 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -1046,10 +1046,10 @@ INSERT INTO t1 VALUES (); SELECT * FROM t1; a -1 -1 3 4 6 +7 DROP TABLE t1; # # End of 10.3 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b11890aaffb..88385900e5e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4341,7 +4341,7 @@ int ha_partition::write_row(uchar * buf) tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ error= m_file[part_id]->ha_write_row(buf); - if (have_auto_increment && !table->s->next_number_keypart) + if (!error && have_auto_increment && !table->s->next_number_keypart) set_auto_increment_if_higher(table->next_number_field); reenable_binlog(thd); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index b80c2174658..b16675e868f 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -92,7 +92,6 @@ public: bool auto_inc_initialized; mysql_mutex_t auto_inc_mutex; /**< protecting auto_inc val */ ulonglong next_auto_inc_val; /**< first non reserved value */ - ulonglong prev_auto_inc_val; /**< stored next_auto_inc_val */ /** Hash of partition names. Initialized in the first ha_partition::open() for the table_share. After that it is read-only, i.e. no locking required. @@ -104,7 +103,6 @@ public: Partition_share() : auto_inc_initialized(false), next_auto_inc_val(0), - prev_auto_inc_val(0), partition_name_hash_initialized(false), partition_names(NULL) { @@ -430,24 +428,6 @@ private: MY_BITMAP m_locked_partitions; /** Stores shared auto_increment etc. */ Partition_share *part_share; - /** Fix spurious -Werror=overloaded-virtual in GCC 9 */ - virtual void restore_auto_increment(ulonglong prev_insert_id) - { - handler::restore_auto_increment(prev_insert_id); - } - /** Store and restore next_auto_inc_val over duplicate key errors. */ - virtual void store_auto_increment() - { - DBUG_ASSERT(part_share); - part_share->prev_auto_inc_val= part_share->next_auto_inc_val; - handler::store_auto_increment(); - } - virtual void restore_auto_increment() - { - DBUG_ASSERT(part_share); - part_share->next_auto_inc_val= part_share->prev_auto_inc_val; - handler::restore_auto_increment(); - } /** Temporary storage for new partitions Handler_shares during ALTER */ List m_new_partitions_share_refs; /** Sorted array of partition ids in descending order of number of rows. */ diff --git a/sql/handler.h b/sql/handler.h index eb06cf4e1dd..2a346e8d9d1 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3015,10 +3015,6 @@ private: */ Handler_share **ha_share; - /** Stores next_insert_id for handling duplicate key errors. */ - ulonglong m_prev_insert_id; - - public: handler(handlerton *ht_arg, TABLE_SHARE *share_arg) :table_share(share_arg), table(0), @@ -3041,7 +3037,7 @@ public: auto_inc_intervals_count(0), m_psi(NULL), set_top_table_fields(FALSE), top_table(0), top_table_field(0), top_table_fields(0), - m_lock_type(F_UNLCK), ha_share(NULL), m_prev_insert_id(0) + m_lock_type(F_UNLCK), ha_share(NULL) { DBUG_PRINT("info", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", @@ -3705,16 +3701,6 @@ public: insert_id_for_cur_row; } - /** Store and restore next_insert_id over duplicate key errors. */ - virtual void store_auto_increment() - { - m_prev_insert_id= next_insert_id; - } - virtual void restore_auto_increment() - { - restore_auto_increment(m_prev_insert_id); - } - virtual void update_create_info(HA_CREATE_INFO *create_info) {} int check_old_types(); virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5ec1387a6eb..34c4211070b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1697,7 +1697,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) int error, trg_error= 0; char *key=0; MY_BITMAP *save_read_set, *save_write_set; - table->file->store_auto_increment(); + ulonglong prev_insert_id= table->file->next_insert_id; ulonglong insert_id_for_cur_row= 0; ulonglong prev_insert_id_for_cur_row= 0; DBUG_ENTER("write_record"); @@ -1848,7 +1848,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res == VIEW_CHECK_ERROR) goto before_trg_err; - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); info->touched++; if (different_records) { @@ -2042,7 +2042,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) table->file->print_error(error, MYF(ME_JUST_WARNING)); - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); goto ok_or_after_trg_err; } @@ -2065,7 +2065,7 @@ err: table->file->print_error(error,MYF(0)); before_trg_err: - table->file->restore_auto_increment(); + table->file->restore_auto_increment(prev_insert_id); if (key) my_safe_afree(key, table->s->max_unique_length); table->column_bitmaps_set(save_read_set, save_write_set); diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp index e1dbb63178e..f2fb2bfe8e7 100644 --- a/storage/mroonga/ha_mroonga.hpp +++ b/storage/mroonga/ha_mroonga.hpp @@ -571,11 +571,6 @@ public: void set_next_insert_id(ulonglong id); void get_auto_increment(ulonglong offset, ulonglong increment, ulonglong nb_desired_values, ulonglong *first_value, ulonglong *nb_reserved_values) mrn_override; - /** Fix spurious -Werror=overloaded-virtual in GCC 9 */ - void restore_auto_increment() mrn_override - { - handler::restore_auto_increment(); - } void restore_auto_increment(ulonglong prev_insert_id) mrn_override; void release_auto_increment() mrn_override; int check_for_upgrade(HA_CHECK_OPT *check_opt) mrn_override;