After review fixes. Fix bugs in TRUNCATE.

This commit is contained in:
marko@hundin.mysql.fi 2005-03-01 19:42:59 +02:00
parent d184e93a9f
commit 7252e44bf5
6 changed files with 71 additions and 13 deletions

View file

@ -729,14 +729,17 @@ dict_drop_index_tree(
/***********************************************************************
Truncates the index tree associated with a row in SYS_INDEXES table. */
void
ulint
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 */
rec_t* rec, /* in: record in the clustered index of
SYS_INDEXES table */
mtr_t* mtr) /* in: mtr having the latch
on the record page */
on the record page. The mtr may be
committed and restarted in this call. */
{
ulint root_page_no;
ulint space;
@ -761,7 +764,10 @@ dict_truncate_index_tree(
if (root_page_no == FIL_NULL) {
/* The tree has been freed. */
return;
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
" a missing index of table %s!\n", table->name);
return(FIL_NULL);
}
ptr = rec_get_nth_field_old(rec,
@ -775,7 +781,10 @@ dict_truncate_index_tree(
/* It is a single table tablespace and the .ibd file is
missing: do nothing */
return;
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Trying to TRUNCATE"
" a missing .ibd file of table %s!\n", table->name);
return(FIL_NULL);
}
ptr = rec_get_nth_field_old(rec,
@ -801,6 +810,20 @@ dict_truncate_index_tree(
space, root_page_no, RW_X_LATCH, mtr));
btr_free_root(space, root_page_no, mtr);
/* 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()
below and the following mtr_commit() call. */
page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
FIL_NULL, mtr);
/* We will need to commit the mini-transaction in order to avoid
deadlocks in the btr_create() call, because otherwise we would
be freeing and allocating pages in the same mini-transaction. */
mtr_commit(mtr);
/* mtr_commit() will invalidate rec. */
rec = NULL;
mtr_start(mtr);
/* Find the index corresponding to this SYS_INDEXES record. */
for (index = UT_LIST_GET_FIRST(table->indexes);
@ -814,11 +837,17 @@ dict_truncate_index_tree(
root_page_no = btr_create(type, space, index_id, comp, mtr);
if (index) {
index->tree->page = root_page_no;
} else {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Index %lu %lu of table %s is missing\n"
"InnoDB: from the data dictionary during TRUNCATE!\n",
ut_dulint_get_high(index_id),
ut_dulint_get_low(index_id),
table->name);
}
page_rec_write_index_page_no(rec,
DICT_SYS_INDEXES_PAGE_NO_FIELD,
root_page_no, mtr);
return(root_page_no);
}
/*************************************************************************

View file

@ -56,14 +56,17 @@ dict_create_index_step(
/***********************************************************************
Truncates the index tree associated with a row in SYS_INDEXES table. */
void
ulint
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 */
rec_t* rec, /* in: record in the clustered index of
SYS_INDEXES table */
mtr_t* mtr); /* in: mtr having the latch
on the record page */
on the record page. The mtr may be
committed and restarted in this call. */
/***********************************************************************
Drops the index tree associated with a row in SYS_INDEXES table. */

View file

@ -788,12 +788,15 @@ page_mem_free(
page_rec_set_next(rec, free);
page_header_set_ptr(page, PAGE_FREE, rec);
#if 0 /* It's better not to destroy the user's data. */
/* Clear the data bytes of the deleted record in order to improve
the compression ratio of the page and to make it easier to read
page dumps in corruption reports. The extra bytes of the record
cannot be cleared, because page_mem_alloc() needs them in order
to determine the size of the deleted record. */
memset(rec, 0, rec_offs_data_size(offsets));
#endif
garbage = page_header_get_field(page, PAGE_GARBAGE);

View file

@ -1435,7 +1435,6 @@ loop:
mutex_exit(&(recv_sys->mutex));
}
#ifdef UNIV_HOTBACKUP
/* This page is allocated from the buffer pool and used in the function
below */
static page_t* recv_backup_application_page = NULL;
@ -1560,7 +1559,6 @@ skip_this_recv_addr:
recv_sys_empty_hash();
}
#endif /* UNIV_HOTBACKUP */
#ifdef notdefined
/***********************************************************************

View file

@ -2615,6 +2615,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
rec_t* rec;
const byte* field;
ulint len;
ulint root_page_no;
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
/* The end of SYS_INDEXES has been reached. */
@ -2633,11 +2634,33 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
if (rec_get_deleted_flag(rec, FALSE)) {
/* The index has been dropped. */
continue;
goto next_rec;
}
dict_truncate_index_tree(table, rec, &mtr);
btr_pcur_store_position(&pcur, &mtr);
/* This call may commit and restart mtr. */
root_page_no = dict_truncate_index_tree(table, rec, &mtr);
btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
rec = btr_pcur_get_rec(&pcur);
if (root_page_no != FIL_NULL) {
page_rec_write_index_page_no(rec,
DICT_SYS_INDEXES_PAGE_NO_FIELD,
root_page_no, &mtr);
/* We will need to commit and restart the
mini-transaction in order to avoid deadlocks.
The dict_truncate_index_tree() call has allocated
a page in this mini-transaction, and the rest of
this loop could latch another index page. */
mtr_commit(&mtr);
mtr_start(&mtr);
btr_pcur_restore_position(BTR_MODIFY_LEAF,
&pcur, &mtr);
}
next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}

View file

@ -4250,6 +4250,8 @@ ha_innobase::delete_all_rows(void)
/* Truncate the table in InnoDB */
trx->active_trans = 1;
error = row_truncate_table_for_mysql(prebuilt->table, trx);
if (error == DB_ERROR) {
/* Cannot truncate; resort to ha_innobase::delete_row() */