Commit d753d3e8 authored by marko's avatar marko

branches/zip: Make TRUNCATE TABLE recreate single-table tablespaces.

dict_truncate_index_tree(): Add the parameter space for specifying the
new tablespace identifier of a single-table tablespace that has been
recreated.  When SYS_INDEXES.PAGE_NO == FIL_NULL, do not abort but
create the index tree.

fil_discard_tablespace(): Pass the return code from fil_delete_tablespace().

row_truncate_table_for_mysql(): Attempt to discard and recreate
single-table tablespaces.  Reassign the tablespace identifier both in
the data dictionary (SYS_TABLES and SYS_INDEXES) and in the data
dictionary cache.
parent dc2e9160
......@@ -705,6 +705,9 @@ dict_truncate_index_tree(
/* out: new root page number, or
FIL_NULL on failure */
dict_table_t* table, /* in: the table the index belongs to */
ulint space, /* in: 0=truncate,
nonzero=create the index tree in the
given tablespace */
btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
record in the clustered index of
SYS_INDEXES table. The cursor may be
......@@ -714,14 +717,13 @@ dict_truncate_index_tree(
committed and restarted in this call. */
{
ulint root_page_no;
ulint space;
ibool drop = !space;
ulint zip_size;
ulint type;
dulint index_id;
rec_t* rec;
const byte* ptr;
ulint len;
ulint comp;
dict_index_t* index;
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -733,13 +735,13 @@ dict_truncate_index_tree(
root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
if (root_page_no == FIL_NULL) {
if (drop && root_page_no == FIL_NULL) {
/* The tree has been freed. */
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
" a missing index of table %s!\n", table->name);
return(FIL_NULL);
drop = FALSE;
}
ptr = rec_get_nth_field_old(rec,
......@@ -747,7 +749,10 @@ dict_truncate_index_tree(
ut_ad(len == 4);
if (drop) {
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
}
zip_size = fil_space_get_zip_size(space);
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
......@@ -769,6 +774,11 @@ dict_truncate_index_tree(
ut_ad(len == 8);
index_id = mach_read_from_8(ptr);
if (!drop) {
goto create;
}
/* We free all the pages but the root page first; this operation
may span several mini-transactions */
......@@ -779,10 +789,10 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
comp = page_is_comp(btr_page_get(space, zip_size, root_page_no,
RW_X_LATCH, mtr));
btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:
/* We will temporarily write FIL_NULL to the PAGE_NO field
in SYS_INDEXES, so that the database will not get into an
inconsistent state in case it crashes between the mtr_commit()
......
......@@ -2293,7 +2293,7 @@ fil_discard_tablespace(
ibuf_delete_for_discarded_space(id);
return(TRUE);
return(success);
}
/***********************************************************************
......
......@@ -62,6 +62,9 @@ dict_truncate_index_tree(
/* out: new root page number, or
FIL_NULL on failure */
dict_table_t* table, /* in: the table the index belongs to */
ulint space, /* in: 0=truncate,
nonzero=create the index tree in the
given tablespace */
btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
record in the clustered index of
SYS_INDEXES table. The cursor may be
......
......@@ -2665,6 +2665,7 @@ row_truncate_table_for_mysql(
btr_pcur_t pcur;
mtr_t mtr;
dulint new_id;
ulint recreate_space = 0;
pars_info_t* info = NULL;
/* How do we prevent crashes caused by ongoing operations on
......@@ -2689,17 +2690,23 @@ row_truncate_table_for_mysql(
reallocated, the allocator will remove the ibuf entries for
it.
TODO: when we truncate *.ibd files (analogous to DISCARD
TABLESPACE), we will have to remove we remove all entries for
the table in the insert buffer tree!
When we truncate *.ibd files by recreating them (analogous to
DISCARD TABLESPACE), we remove all entries for the table in the
insert buffer tree. This is not strictly necessary, because
in 6) we will assign a new tablespace identifier, but we can
free up some space in the system tablespace.
4) Linear readahead and random readahead: we use the same
method as in 3) to discard ongoing operations. (This will only
be relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
method as in 3) to discard ongoing operations. (This is only
relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
5) FOREIGN KEY operations: if
table->n_foreign_key_checks_running > 0, we do not allow the
TRUNCATE. We also reserve the data dictionary latch. */
TRUNCATE. We also reserve the data dictionary latch.
6) Crash recovery: To prevent the application of pre-truncation
redo log records on the truncated tablespace, we will assign
a new tablespace identifier to the truncated tablespace. */
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_ad(table);
......@@ -2790,6 +2797,51 @@ row_truncate_table_for_mysql(
trx->table_id = table->id;
if (table->space && !table->dir_path_of_temp_table) {
/* Discard and create the single-table tablespace. */
ulint space = table->space;
ulint zip_size= fil_space_get_zip_size(space);
if (zip_size != ULINT_UNDEFINED
&& fil_discard_tablespace(space)) {
dict_index_t* index;
space = 0;
if (fil_create_new_single_table_tablespace(
&space, table->name, FALSE, zip_size,
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: TRUNCATE TABLE %s failed to"
" create a new tablespace\n",
table->name);
table->ibd_file_missing = 1;
err = DB_ERROR;
goto funct_exit;
}
recreate_space = space;
/* Replace the space_id in the data dictionary cache.
The persisent data dictionary (SYS_TABLES.SPACE
and SYS_INDEXES.SPACE) are updated later in this
function. */
table->space = space;
index = dict_table_get_first_index(table);
do {
index->space = space;
index = dict_table_get_next_index(index);
} while (index);
mtr_start(&mtr);
fsp_header_init(space,
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
mtr_commit(&mtr);
}
}
/* scan SYS_INDEXES for all indexes of the table */
heap = mem_heap_create(800);
......@@ -2834,7 +2886,8 @@ row_truncate_table_for_mysql(
/* This call may commit and restart mtr
and reposition pcur. */
root_page_no = dict_truncate_index_tree(table, &pcur, &mtr);
root_page_no = dict_truncate_index_tree(table, recreate_space,
&pcur, &mtr);
rec = btr_pcur_get_rec(&pcur);
......@@ -2866,17 +2919,20 @@ row_truncate_table_for_mysql(
info = pars_info_create();
pars_info_add_int4_literal(info, "space", (lint) table->space);
pars_info_add_dulint_literal(info, "old_id", table->id);
pars_info_add_dulint_literal(info, "new_id", new_id);
err = que_eval_sql(info,
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
"BEGIN\n"
"UPDATE SYS_TABLES SET ID = :new_id\n"
"UPDATE SYS_TABLES"
" SET ID = :new_id, SPACE = :space\n"
" WHERE ID = :old_id;\n"
"UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
" WHERE TABLE_ID = :old_id;\n"
"UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
"UPDATE SYS_INDEXES"
" SET TABLE_ID = :new_id, SPACE = :space\n"
" WHERE TABLE_ID = :old_id;\n"
"COMMIT WORK;\n"
"END;\n"
......
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