mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
After review fixes. Fix bugs in TRUNCATE.
This commit is contained in:
parent
d184e93a9f
commit
7252e44bf5
6 changed files with 71 additions and 13 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() */
|
||||
|
|
Loading…
Add table
Reference in a new issue