summaryrefslogtreecommitdiff
path: root/sql/partition_info.cc
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2022-04-25 13:58:41 +0300
committerAleksey Midenkov <midenok@gmail.com>2022-04-29 13:31:42 +0300
commitddc416c60698e1f8939faff0cb09c5b5af8e03a7 (patch)
treeff1fc268b37abe33a4bc0955ec9ec02b763584e5 /sql/partition_info.cc
parentea2f09979fc74a8fa7fb1e74c874e00df757c6db (diff)
downloadmariadb-git-ddc416c60698e1f8939faff0cb09c5b5af8e03a7.tar.gz
MDEV-20077 Warning on full history partition is delayed until next DML statement
Moved LIMIT warning from vers_set_hist_part() to new call vers_check_limit() at table unlock phase. At that point read_partitions bitmap is already pruned by DML code (see prune_partitions(), find_used_partitions()) so we have to set corresponding bits for working history partition. Also we don't do my_error(ME_WARNING|ME_ERROR_LOG), because at that point it doesn't update warnings number, so command reports 0 warnings (but warning list is still updated). Instead we do push_warning_printf() and sql_print_warning() separately. Under LOCK TABLES external_lock(F_UNLCK) is not executed. There is start_stmt(), but no corresponding "stop_stmt()". So for that mode we call vers_check_limit() directly from close_thread_tables(). Test result has been changed according to new LIMIT and warning printing algorithm. For convenience all LIMIT warnings are marked with "You see warning above ^". TODO MDEV-20345 fixed. Now vers_history_generating() contains fine-grained list of DML-commands that can generate history (and TODO mechanism worked well).
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r--sql/partition_info.cc53
1 files changed, 43 insertions, 10 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index f523415f6cc..90ef388f3b9 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -835,6 +835,9 @@ bool partition_info::has_unique_name(partition_element *element)
int partition_info::vers_set_hist_part(THD *thd)
{
+ if (!vers_require_hist_part(thd))
+ return 0;
+
if (table->pos_in_table_list &&
table->pos_in_table_list->partition_names)
{
@@ -856,12 +859,8 @@ int partition_info::vers_set_hist_part(THD *thd)
vers_info->hist_part= next;
records= next_records;
}
- if (records > vers_info->limit)
- {
- if (next == vers_info->now_part)
- goto warn;
+ if (records >= vers_info->limit && next != vers_info->now_part)
vers_info->hist_part= next;
- }
return 0;
}
@@ -883,11 +882,45 @@ int partition_info::vers_set_hist_part(THD *thd)
}
}
return 0;
-warn:
- my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
- table->s->db.str, table->s->table_name.str,
- vers_info->hist_part->partition_name);
- return 0;
+}
+
+
+/**
+ Warn at the end of DML command if the last history partition is out of LIMIT.
+*/
+void partition_info::vers_check_limit(THD *thd)
+{
+ if (!vers_info->limit ||
+ vers_info->hist_part->id + 1 < vers_info->now_part->id)
+ return;
+
+ /*
+ NOTE: at this point read_partitions bitmap is already pruned by DML code,
+ we have to set read bits for working history partition. We could use
+ bitmap_set_all(), but this is not optimal since there can be quite a number
+ of partitions.
+ */
+ const uint32 sub_factor= num_subparts ? num_subparts : 1;
+ uint32 part_id= vers_info->hist_part->id * sub_factor;
+ const uint32 part_id_end= part_id + sub_factor;
+ DBUG_ASSERT(part_id_end <= num_parts * sub_factor);
+ for (; part_id < part_id_end; ++part_id)
+ bitmap_set_bit(&read_partitions, part_id);
+
+ ha_partition *hp= (ha_partition*)(table->file);
+ ha_rows hist_rows= hp->part_records(vers_info->hist_part);
+ if (hist_rows >= vers_info->limit)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ WARN_VERS_PART_FULL,
+ ER_THD(thd, WARN_VERS_PART_FULL),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name);
+
+ sql_print_warning(ER_THD(thd, WARN_VERS_PART_FULL),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name);
+ }
}