Skip to content

Commit 074bf59

Browse files
Refactor data dictionary transaction isolation setting (#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: #1316 Differential Revision: D46470667 fbshipit-source-id: 3332363
1 parent 63b8aae commit 074bf59

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.
@@ -1043,9 +1045,10 @@ class Dictionary_client {
10431045

10441046
/**
10451047
Fetch Object ids of all the views referencing base table/ view/ stored
1046-
function name specified in "schema"."name". The views are retrieved
1047-
using READ_UNCOMMITTED reads as the views could be changed by the same
1048-
statement (e.g. multi-table/-view RENAME TABLE).
1048+
function name specified in "schema"."name". The views are retrieved using
1049+
READ_UNCOMMITTED reads if InnoDB is the DD storage engine as the views could
1050+
be changed by the same statement (e.g. multi-table/-view RENAME TABLE).
1051+
Under MyRocks, READ_COMMITTED is used.
10491052
10501053
@tparam T Type of the object (View_table/View_routine)
10511054
to retrieve view names for.
@@ -1069,7 +1072,8 @@ class Dictionary_client {
10691072
@param parent_schema Schema name of parent table.
10701073
@param parent_name Table name of parent table.
10711074
@param parent_engine Storage engine of parent table.
1072-
@param uncommitted Use READ_UNCOMMITTED isolation.
1075+
@param uncommitted Use READ_UNCOMMITTED isolation if DD SE is
1076+
InnoDB.
10731077
@param[out] children_schemas Schema names of child tables.
10741078
@param[out] children_names Table names of child tables.
10751079

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;
@@ -63,6 +65,21 @@ size_t normalize_string(const CHARSET_INFO *cs, const String_type &src,
6365
*/
6466
bool check_if_server_ddse_readonly(THD *thd, const char *schema_name);
6567

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

6885
} // namespace dd

sql/dd/impl/cache/dictionary_client.cc

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "mysqld_error.h"
3838
#include "sql/dd/cache/multi_map_base.h"
3939
#include "sql/dd/dd_schema.h" // dd::Schema_MDL_locker
40+
#include "sql/dd/dd_utility.h"
4041
#include "sql/dd/impl/bootstrap/bootstrap_ctx.h" // bootstrap_stage
4142
#include "sql/dd/impl/cache/shared_dictionary_cache.h" // get(), release(), ...
4243
#include "sql/dd/impl/cache/storage_adapter.h" // store(), drop(), ...
@@ -1223,11 +1224,9 @@ bool Dictionary_client::acquire_uncached_uncommitted_impl(Object_id id,
12231224
return false;
12241225
}
12251226

1226-
// Read the uncached dictionary object using ISO_READ_UNCOMMITTED
1227-
// isolation level.
12281227
const typename T::Cache_partition *stored_object = nullptr;
12291228
bool error = Shared_dictionary_cache::instance()->get_uncached(
1230-
m_thd, key, ISO_READ_UNCOMMITTED, &stored_object);
1229+
m_thd, key, get_dd_isolation_level(), &stored_object);
12311230
if (!error) {
12321231
// Here, stored_object is a newly created instance, so we do not need to
12331232
// clone() it, but we must delete it if dynamic cast fails.
@@ -1644,11 +1643,7 @@ static bool get_index_statistics_entries(
16441643
THD *thd, const String_type &schema_name, const String_type &table_name,
16451644
std::vector<String_type> &index_names,
16461645
std::vector<String_type> &column_names) {
1647-
/*
1648-
Use READ UNCOMMITTED isolation, so this method works correctly when
1649-
called from the middle of atomic ALTER TABLE statement.
1650-
*/
1651-
dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
1646+
dd::Transaction_ro trx(thd, get_dd_isolation_level());
16521647

16531648
// Open the DD tables holding dynamic table statistics.
16541649
trx.otx.register_tables<dd::Table_stat>();
@@ -1721,11 +1716,7 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17211716
tables::Index_stats::create_object_key(schema_name, table_name,
17221717
*it_idxs, *it_cols));
17231718

1724-
/*
1725-
Use READ UNCOMMITTED isolation, so this method works correctly when
1726-
called from the middle of atomic ALTER TABLE statement.
1727-
*/
1728-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1719+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17291720
&idx_stat)) {
17301721
assert(m_thd->is_error() || m_thd->killed);
17311722
return true;
@@ -1754,12 +1745,8 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17541745
std::unique_ptr<Table_stat::Name_key> key(
17551746
tables::Table_stats::create_object_key(schema_name, table_name));
17561747

1757-
/*
1758-
Use READ UNCOMMITTED isolation, so this method works correctly when
1759-
called from the middle of atomic ALTER TABLE statement.
1760-
*/
17611748
const Table_stat *tab_stat = nullptr;
1762-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1749+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17631750
&tab_stat)) {
17641751
assert(m_thd->is_error() || m_thd->killed);
17651752
return true;
@@ -2282,12 +2269,7 @@ template <typename T>
22822269
bool Dictionary_client::fetch_referencing_views_object_id(
22832270
const char *schema, const char *tbl_or_sf_name,
22842271
std::vector<Object_id> *view_ids) const {
2285-
/*
2286-
Use READ UNCOMMITTED isolation, so this method works correctly when
2287-
called from the middle of atomic DROP TABLE/DATABASE or
2288-
RENAME TABLE statements.
2289-
*/
2290-
dd::Transaction_ro trx(m_thd, ISO_READ_UNCOMMITTED);
2272+
dd::Transaction_ro trx(m_thd, get_dd_isolation_level());
22912273

22922274
// Register View_table_usage/View_routine_usage.
22932275
trx.otx.register_tables<T>();
@@ -2331,7 +2313,7 @@ bool Dictionary_client::fetch_fk_children_uncached(
23312313
std::vector<String_type> *children_schemas,
23322314
std::vector<String_type> *children_names) {
23332315
dd::Transaction_ro trx(
2334-
m_thd, uncommitted ? ISO_READ_UNCOMMITTED : ISO_READ_COMMITTED);
2316+
m_thd, uncommitted ? get_dd_isolation_level() : ISO_READ_COMMITTED);
23352317

23362318
trx.otx.register_tables<Foreign_key>();
23372319
Raw_table *foreign_keys_table = trx.otx.get_table<Foreign_key>();
@@ -2810,7 +2792,7 @@ void Dictionary_client::remove_uncommitted_objects(
28102792
DBUG_EVALUATE_IF("skip_dd_table_access_check", false, true)) {
28112793
const typename T::Cache_partition *stored_object = nullptr;
28122794
if (!Shared_dictionary_cache::instance()->get_uncached(
2813-
m_thd, id_key, ISO_READ_UNCOMMITTED, &stored_object))
2795+
m_thd, id_key, get_dd_isolation_level(), &stored_object))
28142796
assert(stored_object == nullptr);
28152797
}
28162798

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"
@@ -117,12 +118,7 @@ bool DD_properties::init_cached_properties(THD *thd) {
117118
// Early exit in case the properties are already initialized.
118119
if (!m_properties.empty()) return false;
119120

120-
/*
121-
Start a DD transaction to get the properties. Please note that we
122-
must do this read using isolation level ISO_READ_UNCOMMITTED
123-
because the SE undo logs may not yet be available.
124-
*/
125-
Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
121+
Transaction_ro trx(thd, get_dd_isolation_level());
126122
trx.otx.add_table<DD_properties>();
127123

128124
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)