Commit e9f6906d authored by Marko Mäkelä's avatar Marko Mäkelä

Enable instant ADD COLUMN

We must split the creation of table or index metadata from the
creation of the dictionary table records and the creation of
the data. In this way, we can transform a table-rebuilding operation
into an instant ADD COLUMN operation. Dictionary objects will only
be added to cache when table rebuilding or index creation is needed.
The ctx->instant_table will never be added to cache.

innodb_update_n_cols(): Renamed from innobase_update_n_virtual().
Call my_error() if an error occurs.

innobase_add_instant_try(): Call my_error() if an error occurs.

create_index_dict(): Replaces row_merge_create_index_graph().

prepare_inplace_alter_table_dict(): First create the ctx->new_table,
and only then decide if the table really needs to be rebuilt.
parent ebf539dd
--- instant_alter.result
+++ instant_alter,4k.result.instant_add_disabled
+++ instant_alter,4k.result
@@ -181,7 +181,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2';
clust_index_size
-1
+7
+6
connection default;
ROLLBACK;
connection analyze;
......@@ -14,7 +14,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
BEGIN;
UPDATE t2 SET d1 = repeat(id, 200);
......@@ -23,7 +23,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ROLLBACK;
connection analyze;
......@@ -32,7 +32,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ALTER TABLE t2 DROP p;
affected rows: 0
......@@ -50,7 +50,7 @@
WHERE name = 'test/big';
clust_index_size
-7
+27
+28
connection default;
ROLLBACK;
CHECKSUM TABLE big;
......@@ -68,7 +68,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+7
+6
connection default;
ROLLBACK;
connection analyze;
......@@ -77,7 +77,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
BEGIN;
UPDATE t2 SET d1 = repeat(id, 200);
......@@ -86,7 +86,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ROLLBACK;
connection analyze;
......@@ -95,7 +95,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ALTER TABLE t2 DROP p;
affected rows: 0
......@@ -113,7 +113,7 @@
WHERE name = 'test/big';
clust_index_size
-7
+27
+23
connection default;
ROLLBACK;
CHECKSUM TABLE big;
......@@ -122,7 +122,7 @@
WHERE name = 'test/big';
clust_index_size
-3
+8
+7
connection default;
DROP TABLE big;
CREATE TABLE t1
......@@ -131,7 +131,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+7
+6
connection default;
ROLLBACK;
connection analyze;
......@@ -140,7 +140,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
BEGIN;
UPDATE t2 SET d1 = repeat(id, 200);
......@@ -149,7 +149,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ROLLBACK;
connection analyze;
......@@ -158,7 +158,7 @@
WHERE name = 'test/t2';
clust_index_size
-1
+5
+4
connection default;
ALTER TABLE t2 DROP p;
affected rows: 0
......@@ -176,7 +176,7 @@
WHERE name = 'test/big';
clust_index_size
-7
+27
+23
connection default;
ROLLBACK;
CHECKSUM TABLE big;
......@@ -185,7 +185,7 @@
WHERE name = 'test/big';
clust_index_size
-3
+8
+7
connection default;
DROP TABLE big;
disconnect analyze;
--- instant_alter.result
+++ instant_alter,8k.result.instant_add_disabled
+++ instant_alter,8k.result
@@ -181,7 +181,7 @@
SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t2';
......@@ -59,7 +59,7 @@
WHERE name = 'test/big';
clust_index_size
-3
+4
+5
connection default;
DROP TABLE big;
CREATE TABLE t1
......@@ -113,7 +113,7 @@
WHERE name = 'test/big';
clust_index_size
-7
+12
+13
connection default;
ROLLBACK;
CHECKSUM TABLE big;
......@@ -122,7 +122,7 @@
WHERE name = 'test/big';
clust_index_size
-3
+4
+5
connection default;
DROP TABLE big;
CREATE TABLE t1
......@@ -176,7 +176,7 @@
WHERE name = 'test/big';
clust_index_size
-7
+12
+13
connection default;
ROLLBACK;
CHECKSUM TABLE big;
......@@ -185,7 +185,7 @@
WHERE name = 'test/big';
clust_index_size
-3
+4
+5
connection default;
DROP TABLE big;
disconnect analyze;
......@@ -1328,30 +1328,6 @@ dict_table_t::add_to_cache()
ut_ad(dict_lru_validate());
}
/** When engaging instant ALTER TABLE, remove a table stub
from the data dictionary cache. */
void dict_table_t::remove_stub_from_cache()
{
ut_ad(mutex_own(&dict_sys->mutex));
HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
ut_fold_string(name.m_name), this);
HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
ut_fold_ull(id), this);
if (can_be_evicted) {
ut_ad(dict_lru_find_table(this));
UT_LIST_REMOVE(dict_sys->table_LRU, this);
can_be_evicted = false;
} else {
ut_ad(dict_non_lru_find_table(this));
UT_LIST_REMOVE(dict_sys->table_non_LRU, this);
}
ut_ad(dict_lru_validate());
}
/**********************************************************************//**
Test whether a table can be evicted from the LRU cache.
@return TRUE if table can be evicted. */
......
This diff is collapsed.
......@@ -1516,9 +1516,6 @@ struct dict_table_t {
/** Add the table definition to the data dictionary cache */
void add_to_cache();
/** When engaging instant ALTER TABLE, remove a table stub
from the data dictionary cache. */
void remove_stub_from_cache();
/** Id of the table. */
table_id_t id;
......
......@@ -263,7 +263,6 @@ row_merge_rename_index_to_drop(
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/** Create the index and load in to the dictionary.
@param[in,out] trx trx (sets error_state)
@param[in,out] table the index is on this table
@param[in] index_def the index definition
@param[in] add_v new virtual columns added along with add
......@@ -273,7 +272,6 @@ row_merge_rename_index_to_drop(
@return index, or NULL on error */
dict_index_t*
row_merge_create_index(
trx_t* trx,
dict_table_t* table,
const index_def_t* index_def,
const dict_add_v_col_t* add_v,
......
......@@ -4396,52 +4396,7 @@ row_merge_rename_tables_dict(
return(err);
}
/** Create and execute a query graph for creating an index.
@param[in,out] trx trx
@param[in,out] table table
@param[in,out] index index
@param[in] add_v new virtual columns added along with add index call
@return DB_SUCCESS or error code */
MY_ATTRIBUTE((nonnull(1,2,3), warn_unused_result))
static
dberr_t
row_merge_create_index_graph(
trx_t* trx,
dict_table_t* table,
dict_index_t* index,
const dict_add_v_col_t* add_v)
{
ind_node_t* node; /*!< Index creation node */
mem_heap_t* heap; /*!< Memory heap */
que_thr_t* thr; /*!< Query thread */
dberr_t err;
DBUG_ENTER("row_merge_create_index_graph");
ut_ad(trx);
ut_ad(table);
ut_ad(index);
heap = mem_heap_create(512);
index->table = table;
node = ind_create_graph_create(index, heap, add_v);
thr = pars_complete_graph_for_exec(node, trx, heap, NULL);
ut_a(thr == que_fork_start_command(
static_cast<que_fork_t*>(que_node_get_parent(thr))));
que_run_threads(thr);
err = trx->error_state;
que_graph_free((que_t*) que_node_get_parent(thr));
DBUG_RETURN(err);
}
/** Create the index and load in to the dictionary.
@param[in,out] trx trx (sets error_state)
@param[in,out] table the index is on this table
@param[in] index_def the index definition
@param[in] add_v new virtual columns added along with add
......@@ -4451,17 +4406,14 @@ row_merge_create_index_graph(
@return index, or NULL on error */
dict_index_t*
row_merge_create_index(
trx_t* trx,
dict_table_t* table,
const index_def_t* index_def,
const dict_add_v_col_t* add_v,
const char** col_names)
{
dict_index_t* index;
dberr_t err;
ulint n_fields = index_def->n_fields;
ulint i;
bool has_new_v_col = false;
DBUG_ENTER("row_merge_create_index");
......@@ -4474,8 +4426,7 @@ row_merge_create_index(
index = dict_mem_index_create(table->name.m_name, index_def->name,
0, index_def->ind_type, n_fields);
ut_a(index);
index->table = table;
index->set_committed(index_def->rebuild);
for (i = 0; i < n_fields; i++) {
......@@ -4489,7 +4440,7 @@ row_merge_create_index(
ut_ad(ifield->col_no >= table->n_v_def);
name = add_v->v_col_name[
ifield->col_no - table->n_v_def];
has_new_v_col = true;
index->has_new_v_col = true;
} else {
name = dict_table_get_v_col_name(
table, ifield->col_no);
......@@ -4514,27 +4465,6 @@ row_merge_create_index(
dict_mem_index_add_field(index, name, ifield->prefix_len);
}
/* Add the index to SYS_INDEXES, using the index prototype. */
err = row_merge_create_index_graph(trx, table, index, add_v);
if (err == DB_SUCCESS) {
index = dict_table_get_index_on_name(table, index_def->name,
index_def->rebuild);
ut_a(index);
index->parser = index_def->parser;
index->has_new_v_col = has_new_v_col;
/* Note the id of the transaction that created this
index, we use it to restrict readers from accessing
this index, to ensure read consistency. */
ut_ad(index->trx_id == trx->id);
} else {
index = NULL;
}
DBUG_RETURN(index);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment