← Back to team overview

maria-developers team mailing list archive

Re: 9941c6a3179: MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT

 

Hi, Aleksey!

On Apr 09, Aleksey Midenkov wrote:
> > > +#
> > > +# MDEV-17554 Auto-create new partition for system versioned tables with history partitioned by INTERVAL/LIMIT
> > > +#
> > > +# Don't auto-create new partition on DELETE HISTORY:
> > > +create or replace table t (a int) with system versioning
> > > +partition by system_time limit 1000 auto_increment;
> >
> > this looks like a hack, I think we need a dedicated syntax for that.
> > but I couldn't think of anything good now.
> >
> > ok, I see that you allow both AUTO_INCREMENT and AUTO.
> > May be better just to use AUTO?
> 
> AUTO_INCREMENT looks more explanatory. Isn't it?

Not to me. In my opinion it looks
1) confusing
2) hackish, a.k.a. "they didn't want to introduce a new keyword, so
   picked an existing one that looked at least remotely relevant"

> To be continued...

I've attached a proof-of-concept patch that adds a partition using
fallback-and-retry mechanism of open_table().

Regards,
Sergei
VP of MariaDB Server Engineering
and security@xxxxxxxxxxx
commit b5b14eaa775
Author: Sergei Golubchik <serg@xxxxxxxxxxx>
Date:   Thu Apr 9 20:19:54 2020 +0200

    PoC

diff --git a/mysql-test/main/a.test b/mysql-test/main/a.test
new file mode 100644
index 00000000000..e06c3fca54e
--- /dev/null
+++ b/mysql-test/main/a.test
@@ -0,0 +1,14 @@
+source include/have_partition.inc;
+create table ptab (a int, b int) partition by range (a)
+( partition p0 values less than (3),
+  partition p1 values less than (5),
+  partition p2 values less than (7)
+);
+
+insert ptab values (1,1),(2,2),(3,3),(4,4),(5,5);
+show create table ptab;
+set debug_dbug='d,add_partition';
+select * from ptab;
+insert ptab values (8,8);
+show create table ptab;
+drop table ptab;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 31e8fe45a5a..2829e2da7b6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2009,6 +2009,19 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
     tc_add_table(thd, table);
   }
 
+  DBUG_EXECUTE_IF("add_partition", {
+    if (strcmp(table_list->alias.str, "ptab") == 0 &&
+        table_list->lock_type >= TL_WRITE_ALLOW_WRITE &&
+        table_list->mdl_request.type == MDL_SHARED_WRITE &&
+        table->part_info->num_parts == 3) {
+      ot_ctx->request_backoff_action(Open_table_context::OT_ADD_HISTORY_PARTITION,
+                                     table_list);
+      MYSQL_UNBIND_TABLE(table->file);
+      tc_release_table(table);
+      DBUG_RETURN(TRUE);
+    }
+  });
+
   if (!(flags & MYSQL_OPEN_HAS_MDL_LOCK) &&
       table->s->table_category < TABLE_CATEGORY_INFORMATION)
   {
@@ -3035,7 +3048,8 @@ request_backoff_action(enum_open_table_action action_arg,
   */
   if (table)
   {
-    DBUG_ASSERT(action_arg == OT_DISCOVER || action_arg == OT_REPAIR);
+    DBUG_ASSERT(action_arg == OT_DISCOVER || action_arg == OT_REPAIR ||
+                action_arg == OT_ADD_HISTORY_PARTITION);
     m_failed_table= (TABLE_LIST*) m_thd->alloc(sizeof(TABLE_LIST));
     if (m_failed_table == NULL)
       return TRUE;
@@ -3102,6 +3116,7 @@ Open_table_context::recover_from_failed_open()
       break;
     case OT_DISCOVER:
     case OT_REPAIR:
+    case OT_ADD_HISTORY_PARTITION:
       if ((result= lock_table_names(m_thd, m_thd->lex->create_info,
                                     m_failed_table, NULL,
                                     get_timeout(), 0)))
@@ -3136,6 +3151,66 @@ Open_table_context::recover_from_failed_open()
         case OT_REPAIR:
           result= auto_repair_table(m_thd, m_failed_table);
           break;
+        case OT_ADD_HISTORY_PARTITION:
+        {
+          TABLE *table= open_ltable(m_thd, m_failed_table, TL_WRITE,
+                    MYSQL_OPEN_HAS_MDL_LOCK | MYSQL_OPEN_IGNORE_LOGGING_FORMAT);
+          if ((result= table == NULL))
+            break;
+
+          Alter_info alter_info;
+          HA_CREATE_INFO create_info;
+          TABLE_LIST *tl= m_failed_table;
+          THD *thd= m_thd;
+
+          alter_info.partition_flags= ALTER_PARTITION_ADD;
+          create_info.init();
+          create_info.alter_info= &alter_info;
+          Alter_table_ctx alter_ctx(thd, tl, 1, &table->s->db, &table->s->table_name);
+          create_info.db_type= table->s->db_type();
+
+          partition_info *part_info= new partition_info();
+          part_info->use_default_partitions = false;
+          part_info->use_default_num_partitions= false;
+          part_info->use_default_num_subpartitions= false;
+          part_info->num_parts= 1;
+          part_info->num_subparts= table->part_info->num_subparts;
+          part_info->subpart_type= table->part_info->subpart_type;
+          part_info->part_type= RANGE_PARTITION;
+          thd->work_part_info= part_info;
+
+          partition_element *part_elem= new partition_element();
+          part_elem->engine_type= part_info->default_engine_type;
+          part_elem->partition_name= "p3";
+          part_elem->id= 3;
+
+          part_info->partitions.push_back(part_elem);
+          part_info->curr_part_elem= part_elem;
+          part_info->init_column_part(thd);
+          part_info->add_max_value(thd);
+          part_info->num_columns= 1;
+
+
+          bool partition_changed= false;
+          bool fast_alter_partition= false;
+          result= prep_alter_part_table(thd, table, &alter_info, &create_info,
+                                    &partition_changed, &fast_alter_partition);
+          DBUG_ASSERT(!result);
+          DBUG_ASSERT(fast_alter_partition);
+          DBUG_ASSERT(partition_changed);
+
+          result= mysql_prepare_alter_table(thd, table, &create_info,
+                                            &alter_info, &alter_ctx);
+          DBUG_ASSERT(!result);
+          result= fast_alter_partition_table(thd, table, &alter_info,
+                     &create_info, tl, &table->s->db, &table->s->table_name);
+          DBUG_ASSERT(!result);
+
+          close_tables_for_reopen(thd, &tl, start_of_statement_svp());
+
+          m_thd->clear_error(1);
+          break;
+        }
         case OT_BACKOFF_AND_RETRY:
         case OT_REOPEN_TABLES:
         case OT_NO_ACTION:
@@ -4993,7 +5068,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
   table_list->required_type= TABLE_TYPE_NORMAL;
 
   /* This function can't properly handle requests for such metadata locks. */
-  DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
+  DBUG_ASSERT(lock_flags & MYSQL_OPEN_HAS_MDL_LOCK  ||
+              table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
 
   while ((error= open_table(thd, table_list, &ot_ctx)) &&
          ot_ctx.can_recover_from_failed_open())
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 773b95b8317..725abddf1ce 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -531,7 +531,8 @@ class Open_table_context
     OT_BACKOFF_AND_RETRY,
     OT_REOPEN_TABLES,
     OT_DISCOVER,
-    OT_REPAIR
+    OT_REPAIR,
+    OT_ADD_HISTORY_PARTITION
   };
   Open_table_context(THD *thd, uint flags);
 

References