Skip to content

Commit e2d3dd1

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 fc7b66c commit e2d3dd1

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
@@ -38,6 +38,7 @@
3838
#include "mysqld_error.h"
3939
#include "sql/dd/cache/multi_map_base.h"
4040
#include "sql/dd/dd_schema.h" // dd::Schema_MDL_locker
41+
#include "sql/dd/dd_utility.h"
4142
#include "sql/dd/impl/bootstrap/bootstrap_ctx.h" // bootstrap_stage
4243
#include "sql/dd/impl/cache/shared_dictionary_cache.h" // get(), release(), ...
4344
#include "sql/dd/impl/cache/storage_adapter.h" // store(), drop(), ...
@@ -1226,11 +1227,9 @@ bool Dictionary_client::acquire_uncached_uncommitted_impl(Object_id id,
12261227
return false;
12271228
}
12281229

1229-
// Read the uncached dictionary object using ISO_READ_UNCOMMITTED
1230-
// isolation level.
12311230
const typename T::Cache_partition *stored_object = nullptr;
12321231
bool error = Shared_dictionary_cache::instance()->get_uncached(
1233-
m_thd, key, ISO_READ_UNCOMMITTED, &stored_object);
1232+
m_thd, key, get_dd_isolation_level(), &stored_object);
12341233
if (!error) {
12351234
// Here, stored_object is a newly created instance, so we do not need to
12361235
// clone() it, but we must delete it if dynamic cast fails.
@@ -1657,11 +1656,7 @@ static bool get_index_statistics_entries(
16571656
THD *thd, const String_type &schema_name, const String_type &table_name,
16581657
std::vector<String_type> &index_names,
16591658
std::vector<String_type> &column_names) {
1660-
/*
1661-
Use READ UNCOMMITTED isolation, so this method works correctly when
1662-
called from the middle of atomic ALTER TABLE statement.
1663-
*/
1664-
dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
1659+
dd::Transaction_ro trx(thd, get_dd_isolation_level());
16651660

16661661
// Open the DD tables holding dynamic table statistics.
16671662
trx.otx.register_tables<dd::Table_stat>();
@@ -1734,11 +1729,7 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17341729
tables::Index_stats::create_object_key(schema_name, table_name,
17351730
*it_idxs, *it_cols));
17361731

1737-
/*
1738-
Use READ UNCOMMITTED isolation, so this method works correctly when
1739-
called from the middle of atomic ALTER TABLE statement.
1740-
*/
1741-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1732+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17421733
&idx_stat)) {
17431734
assert(m_thd->is_error() || m_thd->killed);
17441735
return true;
@@ -1767,12 +1758,8 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17671758
std::unique_ptr<Table_stat::Name_key> key(
17681759
tables::Table_stats::create_object_key(schema_name, table_name));
17691760

1770-
/*
1771-
Use READ UNCOMMITTED isolation, so this method works correctly when
1772-
called from the middle of atomic ALTER TABLE statement.
1773-
*/
17741761
const Table_stat *tab_stat = nullptr;
1775-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1762+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17761763
&tab_stat)) {
17771764
assert(m_thd->is_error() || m_thd->killed);
17781765
return true;
@@ -2295,12 +2282,7 @@ template <typename T>
22952282
bool Dictionary_client::fetch_referencing_views_object_id(
22962283
const char *schema, const char *tbl_or_sf_name,
22972284
std::vector<Object_id> *view_ids) const {
2298-
/*
2299-
Use READ UNCOMMITTED isolation, so this method works correctly when
2300-
called from the middle of atomic DROP TABLE/DATABASE or
2301-
RENAME TABLE statements.
2302-
*/
2303-
dd::Transaction_ro trx(m_thd, ISO_READ_UNCOMMITTED);
2285+
dd::Transaction_ro trx(m_thd, get_dd_isolation_level());
23042286

23052287
// Register View_table_usage/View_routine_usage.
23062288
trx.otx.register_tables<T>();
@@ -2344,7 +2326,7 @@ bool Dictionary_client::fetch_fk_children_uncached(
23442326
std::vector<String_type> *children_schemas,
23452327
std::vector<String_type> *children_names) {
23462328
dd::Transaction_ro trx(
2347-
m_thd, uncommitted ? ISO_READ_UNCOMMITTED : ISO_READ_COMMITTED);
2329+
m_thd, uncommitted ? get_dd_isolation_level() : ISO_READ_COMMITTED);
23482330

23492331
trx.otx.register_tables<Foreign_key>();
23502332
Raw_table *foreign_keys_table = trx.otx.get_table<Foreign_key>();
@@ -2823,7 +2805,7 @@ void Dictionary_client::remove_uncommitted_objects(
28232805
DBUG_EVALUATE_IF("skip_dd_table_access_check", false, true)) {
28242806
const typename T::Cache_partition *stored_object = nullptr;
28252807
if (!Shared_dictionary_cache::instance()->get_uncached(
2826-
m_thd, id_key, ISO_READ_UNCOMMITTED, &stored_object))
2808+
m_thd, id_key, get_dd_isolation_level(), &stored_object))
28272809
assert(stored_object == nullptr);
28282810
}
28292811

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
@@ -36,8 +36,9 @@
3636
#include "m_string.h"
3737

3838
#include "my_sys.h"
39-
#include "mysqld_error.h" // ER_*
40-
#include "sql/current_thd.h" // current_thd
39+
#include "mysqld_error.h" // ER_*
40+
#include "sql/current_thd.h" // current_thd
41+
#include "sql/dd/dd_utility.h"
4142
#include "sql/dd/impl/bootstrap/bootstrap_ctx.h" // dd::bootstrap::DD_bootstrap_ctx
4243
#include "sql/dd/impl/dictionary_impl.h" // Dictionary_impl
4344
#include "sql/dd/impl/properties_impl.h" // Properties_impl
@@ -226,11 +227,7 @@ bool Table_impl::load_foreign_key_parents(Open_dictionary_tables_ctx *otx) {
226227
///////////////////////////////////////////////////////////////////////////
227228

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

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

0 commit comments

Comments
 (0)