Skip to content

Commit a9fde68

Browse files
laurynas-biveinisHerman Lee
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 c417a54 commit a9fde68

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
@@ -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.
@@ -1651,11 +1650,7 @@ static bool get_index_statistics_entries(
16511650
THD *thd, const String_type &schema_name, const String_type &table_name,
16521651
std::vector<String_type> &index_names,
16531652
std::vector<String_type> &column_names) {
1654-
/*
1655-
Use READ UNCOMMITTED isolation, so this method works correctly when
1656-
called from the middle of atomic ALTER TABLE statement.
1657-
*/
1658-
dd::Transaction_ro trx(thd, ISO_READ_UNCOMMITTED);
1653+
dd::Transaction_ro trx(thd, get_dd_isolation_level());
16591654

16601655
// Open the DD tables holding dynamic table statistics.
16611656
trx.otx.register_tables<dd::Table_stat>();
@@ -1728,11 +1723,7 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17281723
tables::Index_stats::create_object_key(schema_name, table_name,
17291724
*it_idxs, *it_cols));
17301725

1731-
/*
1732-
Use READ UNCOMMITTED isolation, so this method works correctly when
1733-
called from the middle of atomic ALTER TABLE statement.
1734-
*/
1735-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1726+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17361727
&idx_stat)) {
17371728
assert(m_thd->is_error() || m_thd->killed);
17381729
return true;
@@ -1761,12 +1752,8 @@ bool Dictionary_client::remove_table_dynamic_statistics(
17611752
std::unique_ptr<Table_stat::Name_key> key(
17621753
tables::Table_stats::create_object_key(schema_name, table_name));
17631754

1764-
/*
1765-
Use READ UNCOMMITTED isolation, so this method works correctly when
1766-
called from the middle of atomic ALTER TABLE statement.
1767-
*/
17681755
const Table_stat *tab_stat = nullptr;
1769-
if (Storage_adapter::get(m_thd, *key, ISO_READ_UNCOMMITTED, false,
1756+
if (Storage_adapter::get(m_thd, *key, get_dd_isolation_level(), false,
17701757
&tab_stat)) {
17711758
assert(m_thd->is_error() || m_thd->killed);
17721759
return true;
@@ -2289,12 +2276,7 @@ template <typename T>
22892276
bool Dictionary_client::fetch_referencing_views_object_id(
22902277
const char *schema, const char *tbl_or_sf_name,
22912278
std::vector<Object_id> *view_ids) const {
2292-
/*
2293-
Use READ UNCOMMITTED isolation, so this method works correctly when
2294-
called from the middle of atomic DROP TABLE/DATABASE or
2295-
RENAME TABLE statements.
2296-
*/
2297-
dd::Transaction_ro trx(m_thd, ISO_READ_UNCOMMITTED);
2279+
dd::Transaction_ro trx(m_thd, get_dd_isolation_level());
22982280

22992281
// Register View_table_usage/View_routine_usage.
23002282
trx.otx.register_tables<T>();
@@ -2338,7 +2320,7 @@ bool Dictionary_client::fetch_fk_children_uncached(
23382320
std::vector<String_type> *children_schemas,
23392321
std::vector<String_type> *children_names) {
23402322
dd::Transaction_ro trx(
2341-
m_thd, uncommitted ? ISO_READ_UNCOMMITTED : ISO_READ_COMMITTED);
2323+
m_thd, uncommitted ? get_dd_isolation_level() : ISO_READ_COMMITTED);
23422324

23432325
trx.otx.register_tables<Foreign_key>();
23442326
Raw_table *foreign_keys_table = trx.otx.get_table<Foreign_key>();
@@ -2817,7 +2799,7 @@ void Dictionary_client::remove_uncommitted_objects(
28172799
DBUG_EVALUATE_IF("skip_dd_table_access_check", false, true)) {
28182800
const typename T::Cache_partition *stored_object = nullptr;
28192801
if (!Shared_dictionary_cache::instance()->get_uncached(
2820-
m_thd, id_key, ISO_READ_UNCOMMITTED, &stored_object))
2802+
m_thd, id_key, get_dd_isolation_level(), &stored_object))
28212803
assert(stored_object == nullptr);
28222804
}
28232805

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)