mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
Applying InnoDB snapshot
Detailed revision comments: r6610 | marko | 2010-02-09 13:53:59 +0200 (Tue, 09 Feb 2010) | 17 lines branches/zip: When dropping temporary indexes and tables at startup, first load them to the data dictionary cache and use the normal routines for dropping tables or indexes. This should reduce the risk of bugs and also make the code compatible with the upcoming TablespaceDictionary implementation. DICT_SYS_INDEXES_NAME_FIELD: The clustered index position of SYS_INDEXES.NAME. row_merge_drop_temp_indexes(): Scan SYS_INDEXES for tables containing temporary indexes, and load the tables as needed. Invoke row_merge_drop_index() to drop the indexes. row_mysql_drop_temp_tables(): Scan SYS_TABLES for temporary tables, load them with dict_load_table() and drop them with row_drop_table_for_mysql(). rb://251, not yet reviewed
This commit is contained in:
parent
a9b1a67b29
commit
cb10d756b4
4 changed files with 134 additions and 98 deletions
|
@ -358,7 +358,7 @@ dict_boot(void)
|
||||||
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
||||||
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
|
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
|
||||||
|
|
||||||
/* The '+ 2' below comes from the 2 system fields */
|
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
|
||||||
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
|
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
|
||||||
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
|
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
|
||||||
#endif
|
#endif
|
||||||
|
@ -367,6 +367,9 @@ dict_boot(void)
|
||||||
#endif
|
#endif
|
||||||
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
|
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
|
||||||
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
|
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
|
||||||
|
#endif
|
||||||
|
#if DICT_SYS_INDEXES_NAME_FIELD != 1 + 2
|
||||||
|
#error "DICT_SYS_INDEXES_NAME_FIELD != 1 + 2"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
table->id = DICT_INDEXES_ID;
|
table->id = DICT_INDEXES_ID;
|
||||||
|
|
|
@ -137,6 +137,7 @@ clustered index */
|
||||||
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
|
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
|
||||||
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
|
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
|
||||||
#define DICT_SYS_INDEXES_TYPE_FIELD 6
|
#define DICT_SYS_INDEXES_TYPE_FIELD 6
|
||||||
|
#define DICT_SYS_INDEXES_NAME_FIELD 3
|
||||||
|
|
||||||
/* When a row id which is zero modulo this number (which must be a power of
|
/* When a row id which is zero modulo this number (which must be a power of
|
||||||
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
|
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
|
||||||
|
|
|
@ -2031,38 +2031,79 @@ row_merge_drop_temp_indexes(void)
|
||||||
/*=============================*/
|
/*=============================*/
|
||||||
{
|
{
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
ulint err;
|
btr_pcur_t pcur;
|
||||||
|
mtr_t mtr;
|
||||||
/* We use the private SQL parser of Innobase to generate the
|
|
||||||
query graphs needed in deleting the dictionary data from system
|
|
||||||
tables in Innobase. Deleting a row from SYS_INDEXES table also
|
|
||||||
frees the file segments of the B-tree associated with the index. */
|
|
||||||
static const char drop_temp_indexes[] =
|
|
||||||
"PROCEDURE DROP_TEMP_INDEXES_PROC () IS\n"
|
|
||||||
"indexid CHAR;\n"
|
|
||||||
"DECLARE CURSOR c IS SELECT ID FROM SYS_INDEXES\n"
|
|
||||||
"WHERE SUBSTR(NAME,0,1)='" TEMP_INDEX_PREFIX_STR "';\n"
|
|
||||||
"BEGIN\n"
|
|
||||||
"\tOPEN c;\n"
|
|
||||||
"\tWHILE 1=1 LOOP\n"
|
|
||||||
"\t\tFETCH c INTO indexid;\n"
|
|
||||||
"\t\tIF (SQL % NOTFOUND) THEN\n"
|
|
||||||
"\t\t\tEXIT;\n"
|
|
||||||
"\t\tEND IF;\n"
|
|
||||||
"\t\tDELETE FROM SYS_FIELDS WHERE INDEX_ID = indexid;\n"
|
|
||||||
"\t\tDELETE FROM SYS_INDEXES WHERE ID = indexid;\n"
|
|
||||||
"\tEND LOOP;\n"
|
|
||||||
"\tCLOSE c;\n"
|
|
||||||
"\tCOMMIT WORK;\n"
|
|
||||||
"END;\n";
|
|
||||||
|
|
||||||
|
/* Load the table definitions that contain partially defined
|
||||||
|
indexes, so that the data dictionary information can be checked
|
||||||
|
when accessing the tablename.ibd files. */
|
||||||
trx = trx_allocate_for_background();
|
trx = trx_allocate_for_background();
|
||||||
trx->op_info = "dropping partially created indexes";
|
trx->op_info = "dropping partially created indexes";
|
||||||
row_mysql_lock_data_dictionary(trx);
|
row_mysql_lock_data_dictionary(trx);
|
||||||
|
|
||||||
err = que_eval_sql(NULL, drop_temp_indexes, FALSE, trx);
|
mtr_start(&mtr);
|
||||||
ut_a(err == DB_SUCCESS);
|
|
||||||
|
|
||||||
|
btr_pcur_open_at_index_side(
|
||||||
|
TRUE,
|
||||||
|
dict_table_get_first_index(dict_sys->sys_indexes),
|
||||||
|
BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
const rec_t* rec;
|
||||||
|
const byte* field;
|
||||||
|
ulint len;
|
||||||
|
dulint table_id;
|
||||||
|
dict_table_t* table;
|
||||||
|
|
||||||
|
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||||
|
|
||||||
|
if (!btr_pcur_is_on_user_rec(&pcur)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec = btr_pcur_get_rec(&pcur);
|
||||||
|
field = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_NAME_FIELD,
|
||||||
|
&len);
|
||||||
|
if (len == UNIV_SQL_NULL || len == 0
|
||||||
|
|| mach_read_from_1(field) != (ulint) TEMP_INDEX_PREFIX) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a temporary index. */
|
||||||
|
|
||||||
|
field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
|
||||||
|
if (len != 8) {
|
||||||
|
/* Corrupted TABLE_ID */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_id = mach_read_from_8(field);
|
||||||
|
|
||||||
|
btr_pcur_store_position(&pcur, &mtr);
|
||||||
|
btr_pcur_commit_specify_mtr(&pcur, &mtr);
|
||||||
|
|
||||||
|
table = dict_load_table_on_id(table_id);
|
||||||
|
|
||||||
|
if (table) {
|
||||||
|
dict_index_t* index;
|
||||||
|
|
||||||
|
for (index = dict_table_get_first_index(table);
|
||||||
|
index; index = dict_table_get_next_index(index)) {
|
||||||
|
|
||||||
|
if (*index->name == TEMP_INDEX_PREFIX) {
|
||||||
|
row_merge_drop_index(index, table, trx);
|
||||||
|
trx_commit_for_mysql(trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr_start(&mtr);
|
||||||
|
btr_pcur_restore_position(BTR_SEARCH_LEAF,
|
||||||
|
&pcur, &mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
btr_pcur_close(&pcur);
|
||||||
|
mtr_commit(&mtr);
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3370,88 +3370,79 @@ void
|
||||||
row_mysql_drop_temp_tables(void)
|
row_mysql_drop_temp_tables(void)
|
||||||
/*============================*/
|
/*============================*/
|
||||||
{
|
{
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
ulint err;
|
btr_pcur_t pcur;
|
||||||
|
mtr_t mtr;
|
||||||
|
mem_heap_t* heap;
|
||||||
|
|
||||||
trx = trx_allocate_for_background();
|
trx = trx_allocate_for_background();
|
||||||
trx->op_info = "dropping temporary tables";
|
trx->op_info = "dropping temporary tables";
|
||||||
row_mysql_lock_data_dictionary(trx);
|
row_mysql_lock_data_dictionary(trx);
|
||||||
|
|
||||||
err = que_eval_sql(
|
heap = mem_heap_create(200);
|
||||||
NULL,
|
|
||||||
"PROCEDURE DROP_TEMP_TABLES_PROC () IS\n"
|
|
||||||
"table_name CHAR;\n"
|
|
||||||
"table_id CHAR;\n"
|
|
||||||
"foreign_id CHAR;\n"
|
|
||||||
"index_id CHAR;\n"
|
|
||||||
"DECLARE CURSOR c IS SELECT NAME,ID FROM SYS_TABLES\n"
|
|
||||||
"WHERE N_COLS > 2147483647\n"
|
|
||||||
/* N_COLS>>31 is set unless ROW_FORMAT=REDUNDANT,
|
|
||||||
and MIX_LEN may be garbage for those tables */
|
|
||||||
"AND MIX_LEN=(MIX_LEN/2*2+1);\n"
|
|
||||||
/* MIX_LEN & 1 is set for temporary tables */
|
|
||||||
#if DICT_TF2_TEMPORARY != 1
|
|
||||||
# error "DICT_TF2_TEMPORARY != 1"
|
|
||||||
#endif
|
|
||||||
"BEGIN\n"
|
|
||||||
"OPEN c;\n"
|
|
||||||
"WHILE 1=1 LOOP\n"
|
|
||||||
" FETCH c INTO table_name, table_id;\n"
|
|
||||||
" IF (SQL % NOTFOUND) THEN\n"
|
|
||||||
" EXIT;\n"
|
|
||||||
" END IF;\n"
|
|
||||||
" WHILE 1=1 LOOP\n"
|
|
||||||
" SELECT ID INTO index_id\n"
|
|
||||||
" FROM SYS_INDEXES\n"
|
|
||||||
" WHERE TABLE_ID = table_id\n"
|
|
||||||
" LOCK IN SHARE MODE;\n"
|
|
||||||
" IF (SQL % NOTFOUND) THEN\n"
|
|
||||||
" EXIT;\n"
|
|
||||||
" END IF;\n"
|
|
||||||
|
|
||||||
/* Do not drop tables for which there exist
|
mtr_start(&mtr);
|
||||||
foreign key constraints. */
|
|
||||||
" SELECT ID INTO foreign_id\n"
|
|
||||||
" FROM SYS_FOREIGN\n"
|
|
||||||
" WHERE FOR_NAME = table_name\n"
|
|
||||||
" AND TO_BINARY(FOR_NAME)\n"
|
|
||||||
" = TO_BINARY(table_name)\n;"
|
|
||||||
" IF NOT (SQL % NOTFOUND) THEN\n"
|
|
||||||
" EXIT;\n"
|
|
||||||
" END IF;\n"
|
|
||||||
|
|
||||||
" SELECT ID INTO foreign_id\n"
|
btr_pcur_open_at_index_side(
|
||||||
" FROM SYS_FOREIGN\n"
|
TRUE,
|
||||||
" WHERE REF_NAME = table_name\n"
|
dict_table_get_first_index(dict_sys->sys_tables),
|
||||||
" AND TO_BINARY(REF_NAME)\n"
|
BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
|
||||||
" = TO_BINARY(table_name)\n;"
|
|
||||||
" IF NOT (SQL % NOTFOUND) THEN\n"
|
|
||||||
" EXIT;\n"
|
|
||||||
" END IF;\n"
|
|
||||||
|
|
||||||
" DELETE FROM SYS_FIELDS\n"
|
for (;;) {
|
||||||
" WHERE INDEX_ID = index_id;\n"
|
const rec_t* rec;
|
||||||
" DELETE FROM SYS_INDEXES\n"
|
const byte* field;
|
||||||
" WHERE ID = index_id\n"
|
ulint len;
|
||||||
" AND TABLE_ID = table_id;\n"
|
const char* table_name;
|
||||||
" END LOOP;\n"
|
dict_table_t* table;
|
||||||
" DELETE FROM SYS_COLUMNS\n"
|
|
||||||
" WHERE TABLE_ID = table_id;\n"
|
|
||||||
" DELETE FROM SYS_TABLES\n"
|
|
||||||
" WHERE ID = table_id;\n"
|
|
||||||
"END LOOP;\n"
|
|
||||||
"COMMIT WORK;\n"
|
|
||||||
"END;\n"
|
|
||||||
, FALSE, trx);
|
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||||
ut_print_timestamp(stderr);
|
|
||||||
fprintf(stderr,
|
if (!btr_pcur_is_on_user_rec(&pcur)) {
|
||||||
" InnoDB: Failed to drop temporary tables:"
|
break;
|
||||||
" error %lu occurred\n",
|
}
|
||||||
(ulong) err);
|
|
||||||
|
rec = btr_pcur_get_rec(&pcur);
|
||||||
|
field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
|
||||||
|
if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Because this is not a ROW_FORMAT=REDUNDANT table,
|
||||||
|
the is_temp flag is valid. Examine it. */
|
||||||
|
|
||||||
|
field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
|
||||||
|
if (len != 4
|
||||||
|
|| !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a temporary table. */
|
||||||
|
field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
|
||||||
|
if (len == UNIV_SQL_NULL || len == 0) {
|
||||||
|
/* Corrupted SYS_TABLES.NAME */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_name = mem_heap_strdupl(heap, (const char*) field, len);
|
||||||
|
|
||||||
|
btr_pcur_store_position(&pcur, &mtr);
|
||||||
|
btr_pcur_commit_specify_mtr(&pcur, &mtr);
|
||||||
|
|
||||||
|
table = dict_load_table(table_name);
|
||||||
|
|
||||||
|
if (table) {
|
||||||
|
row_drop_table_for_mysql(table_name, trx, FALSE);
|
||||||
|
trx_commit_for_mysql(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr_start(&mtr);
|
||||||
|
btr_pcur_restore_position(BTR_SEARCH_LEAF,
|
||||||
|
&pcur, &mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btr_pcur_close(&pcur);
|
||||||
|
mtr_commit(&mtr);
|
||||||
|
mem_heap_free(heap);
|
||||||
row_mysql_unlock_data_dictionary(trx);
|
row_mysql_unlock_data_dictionary(trx);
|
||||||
trx_free_for_background(trx);
|
trx_free_for_background(trx);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue