Skip to content

Commit a508024

Browse files
laurynas-biveinisinikep
authored andcommitted
Refactor data dictionary transaction isolation setting (facebook#1316)
Summary: InnoDB uses READ UNCOMMITTED, which is not supported with MyRocks. Instead of hardcoding READ UNCOMMITTED at several locations, introduce a helper function that returns the desired DD transaction isolation level, based on the default DD engine. No functional changes if the default DD engine is InnoDB. Pull Request resolved: facebook#1316 Differential Revision: D46470667
1 parent c5b01ad commit a508024

File tree

5 files changed

+43
-47
lines changed

5 files changed

+43
-47
lines changed

sql/dd/cache/dictionary_client.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,9 @@ class Dictionary_client {
592592
not known by the object registry.
593593
594594
When the object is read from the persistent tables, the transaction
595-
isolation level is READ UNCOMMITTED. This is necessary to be able to
596-
read uncommitted data from an earlier stage of the same session.
595+
isolation level is READ UNCOMMITTED if the DD is stored in InnoDB. This is
596+
necessary to be able to read uncommitted data from an earlier stage of the
597+
same session. Under MyRocks, READ COMMITTED is used.
597598
598599
@tparam T Dictionary object type.
599600
@param id Object id to retrieve.
@@ -614,8 +615,9 @@ class Dictionary_client {
614615
dictionary client methods since it is not known by the object registry.
615616
616617
When the object is read from the persistent tables, the transaction
617-
isolation level is READ UNCOMMITTED. This is necessary to be able to
618-
read uncommitted data from an earlier stage of the same session.
618+
isolation level is READ UNCOMMITTED if the DD is stored in InnoDB. This is
619+
necessary to be able to read uncommitted data from an earlier stage of the
620+
same session. Under MyRocks, READ COMMITTED is used.
619621
620622
@tparam T Dictionary object type.
621623
@param id Object id to retrieve.
@@ -1046,9 +1048,10 @@ class Dictionary_client {
10461048

10471049
/**
10481050
Fetch Object ids of all the views referencing base table/ view/ stored
1049-
function name specified in "schema"."name". The views are retrieved
1050-
using READ_UNCOMMITTED reads as the views could be changed by the same
1051-
statement (e.g. multi-table/-view RENAME TABLE).
1051+
function name specified in "schema"."name". The views are retrieved using
1052+
READ_UNCOMMITTED reads if InnoDB is the DD storage engine as the views could
1053+
be changed by the same statement (e.g. multi-table/-view RENAME TABLE).
1054+
Under MyRocks, READ_COMMITTED is used.
10521055
10531056
@tparam T Type of the object (View_table/View_routine)
10541057
to retrieve view names for.
@@ -1072,7 +1075,8 @@ class Dictionary_client {
10721075
@param parent_schema Schema name of parent table.
10731076
@param parent_name Table name of parent table.
10741077
@param parent_engine Storage engine of parent table.
1075-
@param uncommitted Use READ_UNCOMMITTED isolation.
1078+
@param uncommitted Use READ_UNCOMMITTED isolation if DD SE is
1079+
InnoDB.
10761080
@param[out] children_schemas Schema names of child tables.
10771081
@param[out] children_names Table names of child tables.
10781082

sql/dd/dd_utility.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#define DD__UTILITY_INCLUDED
2525

2626
#include "sql/dd/string_type.h" // dd::String_type
27+
#include "sql/handler.h" // enum_tx_isolation
28+
#include "sql/mysqld.h"
2729

2830
struct CHARSET_INFO;
2931
class THD;
@@ -64,6 +66,21 @@ size_t normalize_string(const CHARSET_INFO *cs, const String_type &src,
6466
*/
6567
bool check_if_server_ddse_readonly(THD *thd, const char *schema_name = nullptr);
6668

69+
/**
70+
Get the isolation level for a data dictionary transaction. InnoDB uses READ
71+
UNCOMMITTED to work correctly in the following cases:
72+
- when called in the middle of an atomic DDL statement;
73+
- wehn called during the server startup when the undo logs have not been
74+
initialized yet.
75+
@return isolation level
76+
*/
77+
inline enum_tx_isolation get_dd_isolation_level() {
78+
assert(default_dd_storage_engine == DEFAULT_DD_ROCKSDB ||
79+
default_dd_storage_engine == DEFAULT_DD_INNODB);
80+
return default_dd_storage_engine == DEFAULT_DD_ROCKSDB ? ISO_READ_COMMITTED
81+
: ISO_READ_UNCOMMITTED;
82+
}
83+
6784
///////////////////////////////////////////////////////////////////////////
6885

6986
} // namespace dd

sql/dd/impl/cache/dictionary_client.cc

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "mysqld_error.h"
4040
#include "sql/dd/cache/multi_map_base.h"
4141
#include "sql/dd/dd_schema.h" // dd::Schema_MDL_locker
42+
#include "sql/dd/dd_utility.h"
4243
#include "sql/dd/impl/bootstrap/bootstrap_ctx.h" // bootstrap_stage
4344
#include "sql/dd/impl/cache/shared_dictionary_cache.h" // get(), release(), ...
4445
#include "sql/dd/impl/cache/storage_adapter.h" // store(), drop(), ...
@@ -1230,11 +1231,9 @@ bool Dictionary_client::acquire_uncached_uncommitted_impl(Object_id id,
12301231
return false;
12311232
}
12321233

1233-
// Read the uncached dictionary object using ISO_READ_UNCOMMITTED
1234-
// isolation level.
12351234
const typename T::Cache_partition *stored_object = nullptr;
12361235
bool error = Shared_dictionary_cache::instance()->get_uncached(
1237-
m_thd, key, ISO_READ_UNCOMMITTED, &stored_object);
1236+
m_thd, key, get_dd_isolation_level(), &stored_object);
12381237
if (!error) {
12391238
// Here, stored_object is a newly created instance, so we do not need to
12401239
// clone() it, but we must delete it if dynamic cast fails.
@@ -1661,11 +1660,7 @@ static bool get_index_statistics_entries(
16611660
THD *thd, const String_type &schema_name, const String_type &table_name,
16621661
std::vector<String_type> &index_names,
16631662
std::vector<String_type> &column_names) {
1664-
/*
1665-
Use READ UNCOMMITTED isolation, so this method works correctly when
1666-
called from the middle of atomic ALTER TABLE statement.
1667-
*/
1668-
dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
1663+
dd::Transaction_ro trx(thd, get_dd_isolation_level());
16691664

16701665
// Open the DD tables holding dynamic table statistics.
16711666
trx.otx.register_tables<dd::Table_stat>();
@@ -1738,11 +1733,7 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17381733
tables::Index_stats::create_object_key(schema_name, table_name,
17391734
*it_idxs, *it_cols));
17401735

1741-
/*
1742-
Use READ UNCOMMITTED isolation, so this method works correctly when
1743-
called from the middle of atomic ALTER TABLE statement.
1744-
*/
1745-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1736+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17461737
&idx_stat)) {
17471738
assert(m_thd->is_error() || m_thd->killed);
17481739
return true;
@@ -1771,12 +1762,8 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17711762
std::unique_ptr<Table_stat::Name_key> key(
17721763
tables::Table_stats::create_object_key(schema_name, table_name));
17731764

1774-
/*
1775-
Use READ UNCOMMITTED isolation, so this method works correctly when
1776-
called from the middle of atomic ALTER TABLE statement.
1777-
*/
17781765
const Table_stat *tab_stat = nullptr;
1779-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1766+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17801767
&tab_stat)) {
17811768
assert(m_thd->is_error() || m_thd->killed);
17821769
return true;
@@ -2299,12 +2286,7 @@ template <typename T>
22992286
bool Dictionary_client::fetch_referencing_views_object_id(
23002287
const char *schema, const char *tbl_or_sf_name,
23012288
std::vector<Object_id> *view_ids) const {
2302-
/*
2303-
Use READ UNCOMMITTED isolation, so this method works correctly when
2304-
called from the middle of atomic DROP TABLE/DATABASE or
2305-
RENAME TABLE statements.
2306-
*/
2307-
dd::Transaction_ro trx(m_thd, ISO_READ_UNCOMMITTED);
2289+
dd::Transaction_ro trx(m_thd, get_dd_isolation_level());
23082290

23092291
// Register View_table_usage/View_routine_usage.
23102292
trx.otx.register_tables<T>();
@@ -2348,7 +2330,7 @@ bool Dictionary_client::fetch_fk_children_uncached(
23482330
std::vector<String_type> *children_schemas,
23492331
std::vector<String_type> *children_names) {
23502332
dd::Transaction_ro trx(
2351-
m_thd, uncommitted ? ISO_READ_UNCOMMITTED : ISO_READ_COMMITTED);
2333+
m_thd, uncommitted ? get_dd_isolation_level() : ISO_READ_COMMITTED);
23522334

23532335
trx.otx.register_tables<Foreign_key>();
23542336
Raw_table *foreign_keys_table = trx.otx.get_table<Foreign_key>();
@@ -2827,7 +2809,7 @@ void Dictionary_client::remove_uncommitted_objects(
28272809
DBUG_EVALUATE_IF("skip_dd_table_access_check", false, true)) {
28282810
const typename T::Cache_partition *stored_object = nullptr;
28292811
if (!Shared_dictionary_cache::instance()->get_uncached(
2830-
m_thd, id_key, ISO_READ_UNCOMMITTED, &stored_object))
2812+
m_thd, id_key, get_dd_isolation_level(), &stored_object))
28312813
assert(stored_object == nullptr);
28322814
}
28332815

sql/dd/impl/tables/dd_properties.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "mysql/udf_registration_types.h"
3535
#include "mysqld_error.h"
3636
#include "sql/auth/sql_security_ctx.h"
37+
#include "sql/dd/dd_utility.h"
3738
#include "sql/dd/dd_version.h" // dd::DD_VERSION
3839
#include "sql/dd/impl/raw/raw_table.h"
3940
#include "sql/dd/impl/transaction_impl.h"
@@ -130,12 +131,7 @@ bool DD_properties::init_cached_properties(THD *thd) {
130131
// Early exit in case the properties are already initialized.
131132
if (!m_properties.empty()) return false;
132133

133-
/*
134-
Start a DD transaction to get the properties. Please note that we
135-
must do this read using isolation level ISO_READ_UNCOMMITTED
136-
because the SE undo logs may not yet be available.
137-
*/
138-
Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
134+
Transaction_ro trx(thd, get_dd_isolation_level());
139135
trx.otx.add_table<DD_properties>();
140136

141137
if (trx.otx.open_tables()) {

sql/dd/impl/types/table_impl.cc

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@
3838

3939
#include "my_sys.h"
4040
#include "mysql/strings/m_ctype.h"
41-
#include "mysqld_error.h" // ER_*
42-
#include "sql/current_thd.h" // current_thd
41+
#include "mysqld_error.h" // ER_*
42+
#include "sql/current_thd.h" // current_thd
43+
#include "sql/dd/dd_utility.h"
4344
#include "sql/dd/impl/bootstrap/bootstrap_ctx.h" // dd::bootstrap::DD_bootstrap_ctx
4445
#include "sql/dd/impl/dictionary_impl.h" // Dictionary_impl
4546
#include "sql/dd/impl/properties_impl.h" // Properties_impl
@@ -228,11 +229,7 @@ bool Table_impl::load_foreign_key_parents(Open_dictionary_tables_ctx *otx) {
228229
///////////////////////////////////////////////////////////////////////////
229230

230231
bool Table_impl::reload_foreign_key_parents(THD *thd) {
231-
/*
232-
Use READ UNCOMMITTED isolation, so this method works correctly when
233-
called from the middle of atomic DDL statements.
234-
*/
235-
dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
232+
dd::Transaction_ro trx(thd, get_dd_isolation_level());
236233

237234
// Register and open tables.
238235
trx.otx.register_tables<dd::Table>();

0 commit comments

Comments
 (0)