summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.h3
-rw-r--r--sql/ha_sequence.h3
-rw-r--r--sql/handler.cc10
-rw-r--r--sql/handler.h6
-rw-r--r--sql/json_table.cc2
-rw-r--r--sql/opt_range.h11
-rw-r--r--sql/sql_delete.cc85
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc9
-rw-r--r--sql/sql_select.h48
-rw-r--r--sql/sql_update.cc88
11 files changed, 132 insertions, 135 deletions
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index 54f628138c9..9cbb6c928ee 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1642,8 +1642,5 @@ public:
bool can_convert_blob(
const Field_blob* field,
const Column_definition& new_field) const override;
-
- void start_operations_batch() {}
- void end_operations_batch() {}
};
#endif /* HA_PARTITION_INCLUDED */
diff --git a/sql/ha_sequence.h b/sql/ha_sequence.h
index 94d861ae8f9..72e59a40479 100644
--- a/sql/ha_sequence.h
+++ b/sql/ha_sequence.h
@@ -161,8 +161,5 @@ public:
file= file_arg;
init(); /* Update cached_table_flags */
}
-
- void start_operations_batch() {}
- void end_operations_batch() {}
};
#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index 51222146b35..2f2c7064e6a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -8661,13 +8661,3 @@ Table_scope_and_contents_source_st::fix_period_fields(THD *thd,
}
return false;
}
-
-void handler::ha_start_operations_batch() // currently useless??
-{
- table->file->start_operations_batch();
-}
-
-void handler::ha_end_operations_batch() // currently useless??
-{
- table->file->end_operations_batch();
-}
diff --git a/sql/handler.h b/sql/handler.h
index 72f9b4dfde0..a337a109707 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3558,10 +3558,8 @@ public:
int ha_drop_partitions(const char *path);
int ha_rename_partitions(const char *path);
- virtual void ha_start_operations_batch();
- virtual void ha_end_operations_batch();
- virtual void start_operations_batch(){}
- virtual void end_operations_batch(){}
+ virtual void start_mini_transaction() {}
+ virtual void end_mini_transaction() {}
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
int update_auto_increment();
virtual void print_error(int error, myf errflag);
diff --git a/sql/json_table.cc b/sql/json_table.cc
index e4c7d0f1e45..a9e882291b6 100644
--- a/sql/json_table.cc
+++ b/sql/json_table.cc
@@ -235,8 +235,6 @@ public:
buf->length(0);
return TRUE;
}
- void start_operations_batch() {}
- void end_operations_batch() {}
};
diff --git a/sql/opt_range.h b/sql/opt_range.h
index f3ccd4d8311..22ddce91e96 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -1264,6 +1264,8 @@ public:
This is used by an optimization in filesort.
*/
virtual void add_used_key_part_to_set()=0;
+
+ virtual bool are_mini_transactions_applicable() const= 0;
};
@@ -1361,6 +1363,8 @@ public:
QUICK_SELECT_I *make_reverse(uint used_key_parts_arg);
virtual void add_used_key_part_to_set();
+ bool are_mini_transactions_applicable() const override
+ { return !in_ror_merged_scan && !mrr_flags; }
private:
/* Default copy ctor used by QUICK_SELECT_DESC */
@@ -1398,7 +1402,6 @@ private:
};
-
class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT
{
public:
@@ -1531,6 +1534,7 @@ public:
READ_RECORD read_record;
virtual void add_used_key_part_to_set();
+ bool are_mini_transactions_applicable() const override { return false; }
};
@@ -1642,6 +1646,8 @@ public:
return valid;
}
+ bool are_mini_transactions_applicable() const override { return false; }
+
/*
Merged quick select that uses Clustered PK, if there is one. This quick
select is not used for row retrieval, it is used for row retrieval.
@@ -1710,6 +1716,8 @@ public:
return valid;
}
+ bool are_mini_transactions_applicable() const override { return false; }
+
QUEUE queue; /* Priority queue for merge operation */
MEM_ROOT alloc; /* Memory pool for this and merged quick selects data. */
@@ -1836,6 +1844,7 @@ public:
bool is_agg_distinct() { return have_agg_distinct; }
bool loose_scan_is_scanning() { return is_index_scan; }
Explain_quick_select *get_explain(MEM_ROOT *alloc);
+ bool are_mini_transactions_applicable() const override { return true; }
};
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 96d4d226060..573b9370151 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -332,12 +332,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool delete_record= false;
bool delete_while_scanning;
bool portion_of_time_through_update;
- bool ops_batch_started= false;
DBUG_ENTER("mysql_delete");
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- query_plan.using_batched_ops= can_use_operations_batch(table_list);
create_explain_query(thd->lex, thd->mem_root);
if (open_and_lock_tables(thd, table_list, TRUE, 0))
@@ -367,6 +365,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
table->map=1;
query_plan.select_lex= thd->lex->first_select_lex();
query_plan.table= table;
+ Mini_transaction_guard mini_transaction(table->file);
thd->lex->promote_select_describe_flag_if_needed();
@@ -595,7 +594,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.select= select;
query_plan.possible_keys= select? select->possible_keys: key_map(0);
-
+ query_plan.using_mini_transaction=
+ can_use_mini_transaction(table_list, select, has_triggers,
+ table->file->referenced_by_foreign_key());
+
/*
Ok, we have generated a query plan for the DELETE.
- if we're running EXPLAIN DELETE, goto produce explain output
@@ -658,52 +660,44 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
/* Direct deleting is supported */
DBUG_PRINT("info", ("Using direct delete"));
THD_STAGE_INFO(thd, stage_updating);
+ if (query_plan.using_mini_transaction)
+ mini_transaction.start();
if (!(error= table->file->ha_direct_delete_rows(&deleted)))
error= -1;
goto terminate_delete;
}
}
}
- table->file->end_operations_batch();
if (query_plan.using_filesort)
{
- {
- if (query_plan.using_batched_ops)
- {
- table->file->start_operations_batch();
- ops_batch_started= true;
- }
- Filesort fsort(order, HA_POS_ERROR, true, select);
- DBUG_ASSERT(query_plan.index == MAX_KEY);
+ Mini_transaction_guard row_search_batch(table->file);
+ if (query_plan.using_mini_transaction)
+ row_search_batch.start();
+ Filesort fsort(order, HA_POS_ERROR, true, select);
+ DBUG_ASSERT(query_plan.index == MAX_KEY);
- Filesort_tracker *fs_tracker=
+ Filesort_tracker *fs_tracker=
thd->lex->explain->get_upd_del_plan()->filesort_tracker;
- if (!(file_sort= filesort(thd, table, &fsort, fs_tracker)))
- goto got_error;
+ if (!(file_sort= filesort(thd, table, &fsort, fs_tracker)))
+ goto got_error;
- thd->inc_examined_row_count(file_sort->examined_rows);
- /*
- Filesort has already found and selected the rows we want to delete,
- so we don't need the where clause
- */
- delete select;
+ thd->inc_examined_row_count(file_sort->examined_rows);
+ /*
+ Filesort has already found and selected the rows we want to delete,
+ so we don't need the where clause
+ */
+ delete select;
- /*
- If we are not in DELETE ... RETURNING, we can free subqueries. (in
- DELETE ... RETURNING we can't, because the RETURNING part may have
- a subquery in it)
- */
- if (!returning)
- free_underlaid_joins(thd, select_lex);
- select= 0;
- if (ops_batch_started)
- {
- table->file->end_operations_batch();
- ops_batch_started= false;
- }
- }
+ /*
+ If we are not in DELETE ... RETURNING, we can free subqueries. (in
+ DELETE ... RETURNING we can't, because the RETURNING part may have
+ a subquery in it)
+ */
+ if (!returning)
+ free_underlaid_joins(thd, select_lex);
+ select= 0;
}
/* If quick select is used, initialize it before retrieving rows. */
@@ -816,13 +810,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
THD_STAGE_INFO(thd, stage_updating);
fix_rownum_pointers(thd, thd->lex->current_select, &deleted);
-
- if (query_plan.using_batched_ops)
- {
- table->file->start_operations_batch();
- ops_batch_started= true;
- }
-
+ if (query_plan.using_mini_transaction)
+ mini_transaction.start();
thd->get_stmt_da()->reset_current_row_for_warning(0);
while (likely(!(error=info.read_record())) && likely(!thd->killed) &&
likely(!thd->is_error()))
@@ -904,12 +893,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
break;
}
- if (ops_batch_started)
- {
- table->file->end_operations_batch();
- ops_batch_started= false;
- }
-
thd->get_stmt_da()->reset_current_row_for_warning(1);
terminate_delete:
@@ -1032,12 +1015,6 @@ send_nothing_and_leave:
DBUG_RETURN((return_error || thd->is_error() || thd->killed) ? 1 : 0);
got_error:
- if (ops_batch_started)
- {
- table->file->end_operations_batch();
- ops_batch_started= false;
- }
-
return_error= 1;
goto send_nothing_and_leave;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d5f4676204b..e1195cf5399 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3004,7 +3004,7 @@ public:
bool using_filesort;
bool using_io_buffer;
- bool using_batched_ops;
+ bool using_mini_transaction;
/* Set this plan to be a plan to do nothing because of impossible WHERE */
void set_impossible_where() { impossible_where= true; }
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e4f9660f649..31d9671ea85 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -21183,14 +21183,12 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if (pfs_batch_update)
join_tab->table->file->start_psi_batch_mode();
-
- bool ops_batch_started= false;
/*
A crude check to employ the optimization only if this is a one-table
select.
Check the list of open tables. It must have one table open (2), but just
one table (3).
- */
+
if (join_tab->next_select == end_send &&
join->thd->open_tables && // (2)
!join->thd->open_tables->next) // (3)
@@ -21198,7 +21196,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
join_tab->table->file->start_operations_batch();
ops_batch_started= true;
}
-
+*/
if (rc != NESTED_LOOP_NO_MORE_ROWS)
{
@@ -21247,9 +21245,6 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
rc= evaluate_join_record(join, join_tab, error);
}
- if (ops_batch_started)
- join_tab->table->file->end_operations_batch();
-
if (rc == NESTED_LOOP_NO_MORE_ROWS &&
join_tab->last_inner && !join_tab->found)
rc= evaluate_null_complemented_join_record(join, join_tab);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 260f31c5822..40bef5caaca 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -2483,6 +2483,52 @@ void propagate_new_equalities(THD *thd, Item *cond,
bool *is_simplifiable_cond);
bool dbug_user_var_equals_str(THD *thd, const char *name, const char *value);
-bool can_use_operations_batch(TABLE_LIST *query_tables);
+bool can_use_mini_transaction(const TABLE_LIST *query_tables,
+ const SQL_SELECT *select,
+ bool has_triggers,
+ bool is_referenced_by_foreign_keys);
+
+/*
+ This class provides automatic call of handler::end_mini_transaction()
+ on destruction (going out of scope), so one doesn't have to track all the
+ execution paths to call end_mini_transaction() explicitly.
+
+ Example of usage:
+
+ {
+ Mini_transaction_guard mini_trx(table->file);
+ mini_trx.start(); // start_mini_transaction() is called
+ ...
+ if (cond)
+ goto label1; // end_mini_transaction() is called on mini_trx going out
+ // of scope and destruction
+ ...
+ } // end_mini_transaction() is called on mini_trx going out
+ // of scope and destruction
+*/
+class Mini_transaction_guard
+{
+public:
+ explicit Mini_transaction_guard(handler *h) : hnd(h)
+ {}
+
+ Mini_transaction_guard()= delete;
+
+ void start()
+ {
+ hnd->start_mini_transaction();
+ started= true;
+ }
+
+ ~Mini_transaction_guard()
+ {
+ if (started)
+ hnd->end_mini_transaction();
+ }
+
+private:
+ handler *hnd= nullptr;
+ bool started= false;
+};
#endif /* SQL_SELECT_INCLUDED */
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 89f875d430e..044671f37e1 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -339,10 +339,16 @@ int cut_fields_for_portion_of_time(THD *thd, TABLE *table,
return res;
}
-
-bool can_use_operations_batch(TABLE_LIST *query_tables)
+bool can_use_mini_transaction(const TABLE_LIST *query_tables,
+ const SQL_SELECT *select,
+ bool has_triggers,
+ bool is_referenced_by_foreign_keys)
{
- return (query_tables->next_global==NULL);
+ return
+ !(query_tables->next_global != nullptr /* more than one table involved */
+ || has_triggers || is_referenced_by_foreign_keys ||
+ (select && select->quick &&
+ !select->quick->are_mini_transactions_applicable()));
}
/*
Process usual UPDATE
@@ -405,7 +411,6 @@ int mysql_update(THD *thd,
TABLE_LIST *update_source_table;
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
- bool ops_batch_started= false;
// For System Versioning (may need to insert new fields to a table).
ha_rows rows_inserted= 0;
@@ -457,14 +462,14 @@ int mysql_update(THD *thd,
DBUG_RETURN(1);
table= table_list->table;
+ Mini_transaction_guard mini_transaction(table->file);
if (!table_list->single_table_updatable())
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE");
DBUG_RETURN(1);
}
-
- query_plan.using_batched_ops= can_use_operations_batch(table_list);
+
/* Calculate "table->covering_keys" based on the WHERE */
table->covering_keys= table->s->keys_in_use;
table->opt_range_keys.clear_all();
@@ -680,14 +685,31 @@ int mysql_update(THD *thd,
}
}
- /*
+ /*
Query optimization is finished at this point.
- Save the decisions in the query plan
- if we're running EXPLAIN UPDATE, get out
*/
query_plan.select= select;
query_plan.possible_keys= select? select->possible_keys: key_map(0);
-
+ has_triggers= (table->triggers &&
+ (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_BEFORE) ||
+ table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER)));
+
+ if (table_list->has_period())
+ has_triggers= table->triggers &&
+ (table->triggers->has_triggers(TRG_EVENT_INSERT,
+ TRG_ACTION_BEFORE)
+ || table->triggers->has_triggers(TRG_EVENT_INSERT,
+ TRG_ACTION_AFTER)
+ || has_triggers);
+ DBUG_PRINT("info", ("has_triggers: %s", has_triggers ? "TRUE" : "FALSE"));
+ query_plan.using_mini_transaction=
+ can_use_mini_transaction(table_list, select, has_triggers,
+ table->file->referenced_by_foreign_key());
+
if (used_key_is_modified || order ||
partition_key_modified(table, table->write_set))
{
@@ -699,7 +721,7 @@ int mysql_update(THD *thd,
/*
Ok, we have generated a query plan for the UPDATE.
- - if we're running EXPLAIN UPDATE, goto produce explain output
+ - if we're running EXPLAIN UPDATE, goto produce explain output
- otherwise, execute the query plan
*/
if (thd->lex->describe)
@@ -709,23 +731,9 @@ int mysql_update(THD *thd,
ANALYZE_START_TRACKING(thd, &explain->command_tracker);
- DBUG_EXECUTE_IF("show_explain_probe_update_exec_start",
+ DBUG_EXECUTE_IF("show_explain_probe_update_exec_start",
dbug_serve_apcs(thd, 1););
- has_triggers= (table->triggers &&
- (table->triggers->has_triggers(TRG_EVENT_UPDATE,
- TRG_ACTION_BEFORE) ||
- table->triggers->has_triggers(TRG_EVENT_UPDATE,
- TRG_ACTION_AFTER)));
-
- if (table_list->has_period())
- has_triggers= table->triggers &&
- (table->triggers->has_triggers(TRG_EVENT_INSERT,
- TRG_ACTION_BEFORE)
- || table->triggers->has_triggers(TRG_EVENT_INSERT,
- TRG_ACTION_AFTER)
- || has_triggers);
- DBUG_PRINT("info", ("has_triggers: %s", has_triggers ? "TRUE" : "FALSE"));
binlog_is_row= thd->is_current_stmt_binlog_format_row();
DBUG_PRINT("info", ("binlog_is_row: %s", binlog_is_row ? "TRUE" : "FALSE"));
@@ -802,11 +810,9 @@ int mysql_update(THD *thd,
note: We avoid sorting if we sort on the used index
*/
- if (query_plan.using_batched_ops)
- {
- table->file->start_operations_batch();
- ops_batch_started= true;
- }
+ Mini_transaction_guard row_search_mini_trx(table->file);
+ if (query_plan.using_mini_transaction)
+ row_search_mini_trx.start();
if (query_plan.using_filesort)
{
/*
@@ -957,14 +963,12 @@ int mysql_update(THD *thd,
table->file->ha_end_keyread();
table->column_bitmaps_set(save_read_set, save_write_set);
}
- if (ops_batch_started)
- {
- table->file->end_operations_batch();
- ops_batch_started= false;
- }
}
update_begin:
+ if (query_plan.using_mini_transaction)
+ mini_transaction.start();
+
if (ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -1029,12 +1033,6 @@ update_begin:
fix_rownum_pointers(thd, thd->lex->current_select, &updated_or_same);
thd->get_stmt_da()->reset_current_row_for_warning(1);
- if (query_plan.using_batched_ops)
- {
- table->file->start_operations_batch();
- ops_batch_started= true;
- }
-
while (!(error=info.read_record()) && !thd->killed)
{
explain->tracker.on_record_read();
@@ -1248,12 +1246,6 @@ error:
break;
}
}
-
- if (ops_batch_started)
- {
- table->file->end_operations_batch();
- ops_batch_started= false;
- }
ANALYZE_STOP_TRACKING(thd, &explain->command_tracker);
table->auto_increment_field_not_null= FALSE;
@@ -1298,6 +1290,7 @@ error:
table->file->end_bulk_update();
update_end:
+
table->file->try_semi_consistent_read(0);
if (!transactional_table && updated > 0)
@@ -1396,12 +1389,9 @@ update_end:
if (unlikely(thd->lex->analyze_stmt))
goto emit_explain_and_leave;
-
DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0);
err:
- if (ops_batch_started)
- table->file->end_operations_batch();
delete select;
delete file_sort;
free_underlaid_joins(thd, select_lex);