Commit df780de6 authored by marko@hundin.mysql.fi's avatar marko@hundin.mysql.fi

InnoDB: Make CHECK TABLE killable. (Bug #9730)

parent e360eaed
...@@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri ...@@ -20,6 +20,7 @@ Created 6/2/1994 Heikki Tuuri
#include "rem0cmp.h" #include "rem0cmp.h"
#include "lock0lock.h" #include "lock0lock.h"
#include "ibuf0ibuf.h" #include "ibuf0ibuf.h"
#include "trx0trx.h"
/* /*
Latching strategy of the InnoDB B-tree Latching strategy of the InnoDB B-tree
...@@ -2274,6 +2275,7 @@ btr_discard_page( ...@@ -2274,6 +2275,7 @@ btr_discard_page(
ut_ad(btr_check_node_ptr(tree, merge_page, mtr)); ut_ad(btr_check_node_ptr(tree, merge_page, mtr));
} }
#ifdef UNIV_BTR_PRINT
/***************************************************************** /*****************************************************************
Prints size info of a B-tree. */ Prints size info of a B-tree. */
...@@ -2407,8 +2409,9 @@ btr_print_tree( ...@@ -2407,8 +2409,9 @@ btr_print_tree(
mtr_commit(&mtr); mtr_commit(&mtr);
btr_validate_tree(tree); btr_validate_tree(tree, NULL);
} }
#endif /* UNIV_BTR_PRINT */
/**************************************************************** /****************************************************************
Checks that the node pointer to a page is appropriate. */ Checks that the node pointer to a page is appropriate. */
...@@ -2649,6 +2652,7 @@ btr_validate_level( ...@@ -2649,6 +2652,7 @@ btr_validate_level(
/*===============*/ /*===============*/
/* out: TRUE if ok */ /* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */ dict_tree_t* tree, /* in: index tree */
trx_t* trx, /* in: transaction or NULL */
ulint level) /* in: level number */ ulint level) /* in: level number */
{ {
ulint space; ulint space;
...@@ -2696,6 +2700,11 @@ btr_validate_level( ...@@ -2696,6 +2700,11 @@ btr_validate_level(
/* Now we are on the desired level. Loop through the pages on that /* Now we are on the desired level. Loop through the pages on that
level. */ level. */
loop: loop:
if (trx_is_interrupted(trx)) {
mtr_commit(&mtr);
mem_heap_free(heap);
return(ret);
}
mem_heap_empty(heap); mem_heap_empty(heap);
offsets = offsets2 = NULL; offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr);
...@@ -2941,7 +2950,8 @@ ibool ...@@ -2941,7 +2950,8 @@ ibool
btr_validate_tree( btr_validate_tree(
/*==============*/ /*==============*/
/* out: TRUE if ok */ /* out: TRUE if ok */
dict_tree_t* tree) /* in: tree */ dict_tree_t* tree, /* in: tree */
trx_t* trx) /* in: transaction or NULL */
{ {
mtr_t mtr; mtr_t mtr;
page_t* root; page_t* root;
...@@ -2954,9 +2964,8 @@ btr_validate_tree( ...@@ -2954,9 +2964,8 @@ btr_validate_tree(
root = btr_root_get(tree, &mtr); root = btr_root_get(tree, &mtr);
n = btr_page_get_level(root, &mtr); n = btr_page_get_level(root, &mtr);
for (i = 0; i <= n; i++) { for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
if (!btr_validate_level(tree, trx, n - i)) {
if (!btr_validate_level(tree, n - i)) {
mtr_commit(&mtr); mtr_commit(&mtr);
......
...@@ -2969,7 +2969,9 @@ ibuf_delete_rec( ...@@ -2969,7 +2969,9 @@ ibuf_delete_rec(
btr_pcur_commit_specify_mtr(pcur, mtr); btr_pcur_commit_specify_mtr(pcur, mtr);
fputs("InnoDB: Validating insert buffer tree:\n", stderr); fputs("InnoDB: Validating insert buffer tree:\n", stderr);
ut_a(btr_validate_tree(ibuf_data->index->tree)); if (!btr_validate_tree(ibuf_data->index->tree, NULL)) {
ut_error;
}
fprintf(stderr, "InnoDB: ibuf tree ok\n"); fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr); fflush(stderr);
......
...@@ -398,6 +398,7 @@ btr_page_free_low( ...@@ -398,6 +398,7 @@ btr_page_free_low(
page_t* page, /* in: page to be freed, x-latched */ page_t* page, /* in: page to be freed, x-latched */
ulint level, /* in: page level */ ulint level, /* in: page level */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
#ifdef UNIV_BTR_PRINT
/***************************************************************** /*****************************************************************
Prints size info of a B-tree. */ Prints size info of a B-tree. */
...@@ -414,6 +415,7 @@ btr_print_tree( ...@@ -414,6 +415,7 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */ dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start ulint width); /* in: print this many entries from start
and end */ and end */
#endif /* UNIV_BTR_PRINT */
/**************************************************************** /****************************************************************
Checks the size and number of fields in a record based on the definition of Checks the size and number of fields in a record based on the definition of
the index. */ the index. */
...@@ -434,7 +436,8 @@ ibool ...@@ -434,7 +436,8 @@ ibool
btr_validate_tree( btr_validate_tree(
/*==============*/ /*==============*/
/* out: TRUE if ok */ /* out: TRUE if ok */
dict_tree_t* tree); /* in: tree */ dict_tree_t* tree, /* in: tree */
trx_t* trx); /* in: transaction or NULL */
#define BTR_N_LEAF_PAGES 1 #define BTR_N_LEAF_PAGES 1
#define BTR_TOTAL_SIZE 2 #define BTR_TOTAL_SIZE 2
......
...@@ -312,6 +312,19 @@ trx_print( ...@@ -312,6 +312,19 @@ trx_print(
FILE* f, /* in: output stream */ FILE* f, /* in: output stream */
trx_t* trx); /* in: transaction */ trx_t* trx); /* in: transaction */
#ifndef UNIV_HOTBACKUP
/**************************************************************************
Determines if the currently running transaction has been interrupted. */
ibool
trx_is_interrupted(
/*===============*/
/* out: TRUE if interrupted */
trx_t* trx); /* in: transaction */
#else /* !UNIV_HOTBACKUP */
#define trx_is_interrupted(trx) FALSE
#endif /* !UNIV_HOTBACKUP */
/* Signal to a transaction */ /* Signal to a transaction */
struct trx_sig_struct{ struct trx_sig_struct{
......
...@@ -3880,6 +3880,7 @@ row_scan_and_check_index( ...@@ -3880,6 +3880,7 @@ row_scan_and_check_index(
int cmp; int cmp;
ibool contains_null; ibool contains_null;
ulint i; ulint i;
ulint cnt;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_; ulint* offsets = offsets_;
...@@ -3902,11 +3903,19 @@ row_scan_and_check_index( ...@@ -3902,11 +3903,19 @@ row_scan_and_check_index(
dtuple_set_n_fields(prebuilt->search_tuple, 0); dtuple_set_n_fields(prebuilt->search_tuple, 0);
prebuilt->select_lock_type = LOCK_NONE; prebuilt->select_lock_type = LOCK_NONE;
cnt = 1000;
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0); ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
loop: loop:
/* Check thd->killed every 1,000 scanned rows */
if (--cnt == 0) {
if (trx_is_interrupted(prebuilt->trx)) {
goto func_exit;
}
cnt = 1000;
}
if (ret != DB_SUCCESS) { if (ret != DB_SUCCESS) {
func_exit:
mem_free(buf); mem_free(buf);
mem_heap_free(heap); mem_heap_free(heap);
...@@ -4033,7 +4042,7 @@ row_check_table_for_mysql( ...@@ -4033,7 +4042,7 @@ row_check_table_for_mysql(
ut_print_name(stderr, index->name); ut_print_name(stderr, index->name);
putc('\n', stderr); */ putc('\n', stderr); */
if (!btr_validate_tree(index->tree)) { if (!btr_validate_tree(index->tree, prebuilt->trx)) {
ret = DB_ERROR; ret = DB_ERROR;
} else { } else {
if (!row_scan_and_check_index(prebuilt, if (!row_scan_and_check_index(prebuilt,
...@@ -4041,6 +4050,10 @@ row_check_table_for_mysql( ...@@ -4041,6 +4050,10 @@ row_check_table_for_mysql(
ret = DB_ERROR; ret = DB_ERROR;
} }
if (trx_is_interrupted(prebuilt->trx)) {
break;
}
/* fprintf(stderr, "%lu entries in index %s\n", n_rows, /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
index->name); */ index->name); */
......
...@@ -996,6 +996,23 @@ mysql_get_identifier_quote_char( ...@@ -996,6 +996,23 @@ mysql_get_identifier_quote_char(
name, namelen)); name, namelen));
} }
/**************************************************************************
Determines if the currently running transaction has been interrupted. */
extern "C"
ibool
trx_is_interrupted(
/*===============*/
/* out: TRUE if interrupted */
trx_t* trx) /* in: transaction */
{
fprintf(stderr,
"trx_is_interrupted: %p %p %d\n",
trx, trx ? trx->mysql_thd : 0,
trx && trx->mysql_thd ? ((THD*) trx->mysql_thd)->killed : -1);
return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
}
/************************************************************************** /**************************************************************************
Obtain a pointer to the MySQL THD object, as in current_thd(). This Obtain a pointer to the MySQL THD object, as in current_thd(). This
definition must match the one in sql/ha_innodb.cc! */ definition must match the one in sql/ha_innodb.cc! */
......
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