Commit e1e958d4 authored by marko's avatar marko

branches/zip: Fast index creation: Release locks on system tables before

creating indexes.  Lock the user table inside the user transaction.

enum trx_dict_op: Remove TRX_OP_INDEX_MAY_WAIT.

ha_innobase::add_index(): Lock the user tables within prebuilt->trx.
Commit the data dictionary transaction before creating indexes.

ha_innobase::final_drop_index(): Lock the user table within prebuilt->trx.
parent 0a63ed9c
......@@ -657,6 +657,7 @@ ha_innobase::add_index(
trx_start_if_not_started(trx);
trans_register_ha(user_thd, FALSE, ht);
prebuilt->trx->active_trans = 1;
trx->mysql_thd = user_thd;
trx->mysql_query_str = thd_query(user_thd);
......@@ -694,14 +695,11 @@ err_exit:
heap, num_of_idx * sizeof *index);
/* Flag this transaction as a dictionary operation, so that
the data dictionary will be locked in crash recovery. Prevent
warnings if row_merge_lock_table() results in a lock wait,
i.e., when another transaction is holding a conflicting lock
on the table, e.g., because of SELECT ... FOR UPDATE. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX_MAY_WAIT);
the data dictionary will be locked in crash recovery. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
/* Acquire a lock on the table before creating any indexes. */
error = row_merge_lock_table(trx, innodb_table,
error = row_merge_lock_table(prebuilt->trx, innodb_table,
new_primary ? LOCK_X : LOCK_S);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
......@@ -709,8 +707,6 @@ err_exit:
goto error_handling;
}
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
/* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during an index create operation. */
......@@ -772,6 +768,13 @@ err_exit:
ut_ad(error == DB_SUCCESS);
/* Commit the data dictionary transaction in order to release
the table locks on the system tables. Unfortunately, this
means that if MySQL crashes while creating a new primary key
inside row_merge_build_indexes(), indexed_table will not be
dropped on crash recovery. Thus, it will become orphaned. */
trx_commit_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
dict_locked = FALSE;
......@@ -783,7 +786,8 @@ err_exit:
table lock also on the table that is being created. */
ut_ad(indexed_table != innodb_table);
error = row_merge_lock_table(trx, indexed_table, LOCK_X);
error = row_merge_lock_table(prebuilt->trx, indexed_table,
LOCK_X);
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
......@@ -793,7 +797,8 @@ err_exit:
/* Read the clustered index of the table and build indexes
based on this information using temporary files and merge sort. */
error = row_merge_build_indexes(trx, innodb_table, indexed_table,
error = row_merge_build_indexes(prebuilt->trx,
innodb_table, indexed_table,
index, num_of_idx, table);
error_handling:
......@@ -861,6 +866,7 @@ error_handling:
break;
}
trx_commit_for_mysql(prebuilt->trx);
row_prebuilt_free(prebuilt, TRUE);
prebuilt = row_create_prebuilt(indexed_table);
......@@ -878,7 +884,6 @@ error_handling:
case DB_DUPLICATE_KEY:
error:
prebuilt->trx->error_info = NULL;
prebuilt->trx->error_key_num = trx->error_key_num;
/* fall through */
default:
if (new_primary) {
......@@ -894,6 +899,9 @@ convert_error:
mem_heap_free(heap);
trx_commit_for_mysql(trx);
if (prebuilt->trx) {
trx_commit_for_mysql(prebuilt->trx);
}
if (dict_locked) {
row_mysql_unlock_data_dictionary(trx);
......@@ -1096,21 +1104,19 @@ ha_innobase::final_drop_index(
trx_start_if_not_started(trx);
trans_register_ha(user_thd, FALSE, ht);
prebuilt->trx->active_trans = 1;
trx->mysql_thd = user_thd;
trx->mysql_query_str = thd_query(user_thd);
/* Flag this transaction as a dictionary operation, so that
the data dictionary will be locked in crash recovery. Prevent
warnings if row_merge_lock_table() results in a lock wait,
i.e., when another transaction is holding a conflicting lock
on the table, e.g., because of SELECT ... FOR UPDATE. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX_MAY_WAIT);
the data dictionary will be locked in crash recovery. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
/* Lock the table exclusively, to ensure that no active
transaction depends on an index that is being dropped. */
err = convert_error_code_to_mysql(
row_merge_lock_table(trx, prebuilt->table, LOCK_X),
row_merge_lock_table(prebuilt->trx, prebuilt->table, LOCK_X),
user_thd);
if (UNIV_UNLIKELY(err)) {
......@@ -1128,8 +1134,6 @@ ha_innobase::final_drop_index(
goto func_exit;
}
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
/* Drop indexes marked to be dropped */
row_mysql_lock_data_dictionary(trx);
......@@ -1162,6 +1166,7 @@ ha_innobase::final_drop_index(
func_exit:
trx_commit_for_mysql(trx);
trx_commit_for_mysql(prebuilt->trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
......
......@@ -369,12 +369,7 @@ enum trx_dict_op {
/** The transaction is creating or dropping an index in an
existing table. In crash recovery, the the data dictionary
must be locked, but the table must not be dropped. */
TRX_DICT_OP_INDEX = 2,
/** The transaction is creating or dropping an index in an
existing table. In crash recovery, the the data dictionary
must be locked, but the table must not be dropped. A lock
wait timeout is allowed to occur. */
TRX_DICT_OP_INDEX_MAY_WAIT = 3
TRX_DICT_OP_INDEX = 2
};
/**************************************************************************
......
......@@ -162,7 +162,6 @@ trx_get_dict_operation(
case TRX_DICT_OP_NONE:
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
case TRX_DICT_OP_INDEX_MAY_WAIT:
return(op);
}
ut_error;
......@@ -192,18 +191,11 @@ trx_set_dict_operation(
case TRX_DICT_OP_INDEX:
case TRX_DICT_OP_TABLE:
goto ok;
case TRX_DICT_OP_INDEX_MAY_WAIT:
break;
}
ut_error;
break;
case TRX_DICT_OP_INDEX:
ut_ad(old_op == TRX_DICT_OP_NONE
|| old_op == TRX_DICT_OP_INDEX_MAY_WAIT);
break;
case TRX_DICT_OP_INDEX_MAY_WAIT:
ut_ad(old_op == TRX_DICT_OP_NONE
|| old_op == TRX_DICT_OP_INDEX);
ut_ad(old_op == TRX_DICT_OP_NONE);
break;
}
ok:
......
......@@ -1758,7 +1758,6 @@ lock_rec_enqueue_waiting(
switch (trx_get_dict_operation(trx)) {
case TRX_DICT_OP_NONE:
case TRX_DICT_OP_INDEX_MAY_WAIT:
break;
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
......@@ -3621,7 +3620,6 @@ lock_table_enqueue_waiting(
switch (trx_get_dict_operation(trx)) {
case TRX_DICT_OP_NONE:
case TRX_DICT_OP_INDEX_MAY_WAIT:
break;
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
......
......@@ -1679,7 +1679,6 @@ trx_undo_mark_as_dict_operation(
switch (trx_get_dict_operation(trx)) {
case TRX_DICT_OP_NONE:
case TRX_DICT_OP_INDEX_MAY_WAIT:
ut_error;
case TRX_DICT_OP_INDEX:
/* Do not discard the table on recovery. */
......
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