mirror of
https://github.com/MariaDB/server.git
synced 2025-05-29 21:42:28 +03:00
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-group_concat-4.1
This commit is contained in:
commit
1318470a96
@ -426,7 +426,8 @@ btr_page_free_for_ibuf(
|
||||
flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
|
||||
|
||||
ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
|
||||
ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
mtr));
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -776,8 +776,8 @@ btr_search_guess_on_hash(
|
||||
goto failure;
|
||||
}
|
||||
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(page_rec_is_user_rec(rec));
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(page_rec_is_user_rec(rec));
|
||||
|
||||
btr_cur_position(index, rec, cursor);
|
||||
|
||||
|
@ -468,6 +468,11 @@ buf_block_init(
|
||||
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
|
||||
block->in_free_list = FALSE;
|
||||
block->in_LRU_list = FALSE;
|
||||
|
||||
block->n_pointers = 0;
|
||||
|
||||
rw_lock_create(&(block->lock));
|
||||
ut_ad(rw_lock_validate(&(block->lock)));
|
||||
|
||||
@ -687,6 +692,7 @@ buf_pool_init(
|
||||
}
|
||||
|
||||
UT_LIST_ADD_LAST(free, buf_pool->free, block);
|
||||
block->in_free_list = TRUE;
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
@ -830,7 +836,7 @@ buf_page_make_young(
|
||||
|
||||
block = buf_block_align(frame);
|
||||
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
buf_LRU_make_block_young(block);
|
||||
|
||||
@ -845,7 +851,7 @@ buf_block_free(
|
||||
/*===========*/
|
||||
buf_block_t* block) /* in, own: block to be freed */
|
||||
{
|
||||
ut_ad(block->state != BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
@ -1109,6 +1115,8 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
must_read = FALSE;
|
||||
|
||||
if (block->io_fix == BUF_IO_READ) {
|
||||
@ -1407,6 +1415,8 @@ buf_page_get_known_nowait(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
buf_block_buf_fix_inc_debug(block, file, line);
|
||||
#else
|
||||
@ -1517,7 +1527,7 @@ buf_page_init(
|
||||
buf_block_t* block) /* in: block to init */
|
||||
{
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(block->state == BUF_BLOCK_READY_FOR_USE);
|
||||
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
/* Set the state of the block */
|
||||
block->magic_n = BUF_BLOCK_MAGIC_N;
|
||||
@ -1533,6 +1543,18 @@ buf_page_init(
|
||||
|
||||
/* Insert into the hash table of file pages */
|
||||
|
||||
if (buf_page_hash_get(space, offset)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page %lu %lu already found from the hash table\n", space,
|
||||
offset);
|
||||
buf_print();
|
||||
buf_LRU_print();
|
||||
buf_validate();
|
||||
buf_LRU_validate();
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
HASH_INSERT(buf_block_t, hash, buf_pool->page_hash,
|
||||
buf_page_address_fold(space, offset), block);
|
||||
|
||||
@ -1605,7 +1627,7 @@ buf_page_init_for_read(
|
||||
|
||||
block = buf_block_alloc();
|
||||
|
||||
ut_ad(block);
|
||||
ut_a(block);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
@ -1769,6 +1791,8 @@ buf_page_io_complete(
|
||||
|
||||
ut_ad(block);
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
io_type = block->io_fix;
|
||||
|
||||
if (io_type == BUF_IO_READ) {
|
||||
|
@ -50,6 +50,8 @@ buf_flush_insert_into_flush_list(
|
||||
{
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
|
||||
|| (ut_dulint_cmp(
|
||||
(UT_LIST_GET_FIRST(buf_pool->flush_list))
|
||||
@ -131,7 +133,7 @@ buf_flush_ready_for_flush(
|
||||
ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
|
||||
{
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
|
||||
&& (block->io_fix == 0)) {
|
||||
@ -163,6 +165,8 @@ buf_flush_write_complete(
|
||||
ut_ad(block);
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
block->oldest_modification = ut_dulint_zero;
|
||||
|
||||
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block);
|
||||
@ -282,6 +286,8 @@ buf_flush_buffered_writes(void)
|
||||
for (i = 0; i < trx_doublewrite->first_free; i++) {
|
||||
block = trx_doublewrite->buf_block_arr[i];
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
|
||||
(void*)block->frame, (void*)block);
|
||||
@ -321,6 +327,8 @@ buf_flush_post_to_doublewrite_buf(
|
||||
try_again:
|
||||
mutex_enter(&(trx_doublewrite->mutex));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if (trx_doublewrite->first_free
|
||||
>= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
|
||||
mutex_exit(&(trx_doublewrite->mutex));
|
||||
@ -395,6 +403,8 @@ buf_flush_write_block_low(
|
||||
/*======================*/
|
||||
buf_block_t* block) /* in: buffer block to write */
|
||||
{
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a(ibuf_count_get(block->space, block->offset) == 0);
|
||||
#endif
|
||||
@ -443,7 +453,7 @@ buf_flush_try_page(
|
||||
|
||||
block = buf_page_hash_get(space, offset);
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if (flush_type == BUF_FLUSH_LIST
|
||||
&& block && buf_flush_ready_for_flush(block, flush_type)) {
|
||||
@ -635,6 +645,7 @@ buf_flush_try_neighbors(
|
||||
for (i = low; i < high; i++) {
|
||||
|
||||
block = buf_page_hash_get(space, i);
|
||||
ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if (block && flush_type == BUF_FLUSH_LRU && i != offset
|
||||
&& !block->old) {
|
||||
@ -703,10 +714,10 @@ buf_flush_batch(
|
||||
ulint offset;
|
||||
ibool found;
|
||||
|
||||
ut_ad((flush_type == BUF_FLUSH_LRU) || (flush_type == BUF_FLUSH_LIST));
|
||||
ut_ad((flush_type != BUF_FLUSH_LIST) ||
|
||||
sync_thread_levels_empty_gen(TRUE));
|
||||
|
||||
ut_ad((flush_type == BUF_FLUSH_LRU)
|
||||
|| (flush_type == BUF_FLUSH_LIST));
|
||||
ut_ad((flush_type != BUF_FLUSH_LIST)
|
||||
|| sync_thread_levels_empty_gen(TRUE));
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
if ((buf_pool->n_flush[flush_type] > 0)
|
||||
@ -737,7 +748,6 @@ buf_flush_batch(
|
||||
ut_ad(flush_type == BUF_FLUSH_LIST);
|
||||
|
||||
block = UT_LIST_GET_LAST(buf_pool->flush_list);
|
||||
|
||||
if (!block
|
||||
|| (ut_dulint_cmp(block->oldest_modification,
|
||||
lsn_limit) >= 0)) {
|
||||
@ -756,6 +766,7 @@ buf_flush_batch(
|
||||
function a pointer to a block in the list! */
|
||||
|
||||
while ((block != NULL) && !found) {
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if (buf_flush_ready_for_flush(block, flush_type)) {
|
||||
|
||||
@ -781,7 +792,6 @@ buf_flush_batch(
|
||||
} else if (flush_type == BUF_FLUSH_LRU) {
|
||||
|
||||
block = UT_LIST_GET_PREV(LRU, block);
|
||||
|
||||
} else {
|
||||
ut_ad(flush_type == BUF_FLUSH_LIST);
|
||||
|
||||
|
@ -82,6 +82,8 @@ scan_again:
|
||||
block = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
|
||||
while (block != NULL) {
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
if (block->space == id
|
||||
&& (block->buf_fix_count > 0 || block->io_fix != 0)) {
|
||||
|
||||
@ -199,19 +201,16 @@ buf_LRU_search_and_free_block(
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
freed = FALSE;
|
||||
|
||||
block = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
|
||||
while (block != NULL) {
|
||||
|
||||
ut_a(block->in_LRU_list);
|
||||
if (buf_flush_ready_for_replace(block)) {
|
||||
|
||||
if (buf_debug_prints) {
|
||||
printf(
|
||||
"Putting space %lu page %lu to free list\n",
|
||||
block->space, block->offset);
|
||||
}
|
||||
|
||||
buf_LRU_block_remove_hashed_page(block);
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
@ -223,25 +222,21 @@ buf_LRU_search_and_free_block(
|
||||
if (block->frame) {
|
||||
btr_search_drop_page_hash_index(block->frame);
|
||||
}
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
ut_a(block->buf_fix_count == 0);
|
||||
|
||||
buf_LRU_block_free_hashed_page(block);
|
||||
|
||||
freed = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
block = UT_LIST_GET_PREV(LRU, block);
|
||||
distance++;
|
||||
|
||||
if (!freed && n_iterations <= 10
|
||||
&& distance > 100 + (n_iterations * buf_pool->curr_size)
|
||||
/ 10) {
|
||||
|
||||
buf_pool->LRU_flush_ended = 0;
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
@ -249,15 +244,12 @@ buf_LRU_search_and_free_block(
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_pool->LRU_flush_ended > 0) {
|
||||
buf_pool->LRU_flush_ended--;
|
||||
}
|
||||
|
||||
if (!freed) {
|
||||
if (!freed) {
|
||||
buf_pool->LRU_flush_ended = 0;
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
return(freed);
|
||||
@ -355,7 +347,11 @@ loop:
|
||||
if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
|
||||
|
||||
block = UT_LIST_GET_FIRST(buf_pool->free);
|
||||
ut_a(block->in_free_list);
|
||||
UT_LIST_REMOVE(free, buf_pool->free, block);
|
||||
block->in_free_list = FALSE;
|
||||
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(!block->in_LRU_list);
|
||||
|
||||
if (srv_use_awe) {
|
||||
if (block->frame) {
|
||||
@ -466,7 +462,7 @@ buf_LRU_old_adjust_len(void)
|
||||
ulint old_len;
|
||||
ulint new_len;
|
||||
|
||||
ut_ad(buf_pool->LRU_old);
|
||||
ut_a(buf_pool->LRU_old);
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5);
|
||||
|
||||
@ -474,6 +470,8 @@ buf_LRU_old_adjust_len(void)
|
||||
old_len = buf_pool->LRU_old_len;
|
||||
new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
|
||||
|
||||
ut_a(buf_pool->LRU_old->in_LRU_list);
|
||||
|
||||
/* Update the LRU_old pointer if necessary */
|
||||
|
||||
if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) {
|
||||
@ -490,7 +488,7 @@ buf_LRU_old_adjust_len(void)
|
||||
buf_pool->LRU_old);
|
||||
buf_pool->LRU_old_len--;
|
||||
} else {
|
||||
ut_ad(buf_pool->LRU_old); /* Check that we did not
|
||||
ut_a(buf_pool->LRU_old); /* Check that we did not
|
||||
fall out of the LRU list */
|
||||
return;
|
||||
}
|
||||
@ -498,9 +496,8 @@ buf_LRU_old_adjust_len(void)
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Initializes the old blocks pointer in the LRU list.
|
||||
This function should be called when the LRU list grows to
|
||||
BUF_LRU_OLD_MIN_LEN length. */
|
||||
Initializes the old blocks pointer in the LRU list. This function should be
|
||||
called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */
|
||||
static
|
||||
void
|
||||
buf_LRU_old_init(void)
|
||||
@ -508,7 +505,7 @@ buf_LRU_old_init(void)
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
|
||||
ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
|
||||
|
||||
/* We first initialize all blocks in the LRU list as old and then use
|
||||
the adjust function to move the LRU_old pointer to the right
|
||||
@ -517,6 +514,8 @@ buf_LRU_old_init(void)
|
||||
block = UT_LIST_GET_FIRST(buf_pool->LRU);
|
||||
|
||||
while (block != NULL) {
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->in_LRU_list);
|
||||
block->old = TRUE;
|
||||
block = UT_LIST_GET_NEXT(LRU, block);
|
||||
}
|
||||
@ -539,6 +538,9 @@ buf_LRU_remove_block(
|
||||
ut_ad(block);
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->in_LRU_list);
|
||||
|
||||
/* If the LRU_old pointer is defined and points to just this block,
|
||||
move it backward one step */
|
||||
|
||||
@ -552,11 +554,12 @@ buf_LRU_remove_block(
|
||||
(buf_pool->LRU_old)->old = TRUE;
|
||||
|
||||
buf_pool->LRU_old_len++;
|
||||
ut_ad(buf_pool->LRU_old);
|
||||
ut_a(buf_pool->LRU_old);
|
||||
}
|
||||
|
||||
/* Remove the block from the LRU list */
|
||||
UT_LIST_REMOVE(LRU, buf_pool->LRU, block);
|
||||
block->in_LRU_list = FALSE;
|
||||
|
||||
if (srv_use_awe && block->frame) {
|
||||
/* Remove from the list of mapped pages */
|
||||
@ -599,6 +602,8 @@ buf_LRU_add_block_to_end_low(
|
||||
ut_ad(block);
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
block->old = TRUE;
|
||||
|
||||
last_block = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
@ -609,7 +614,9 @@ buf_LRU_add_block_to_end_low(
|
||||
block->LRU_position = buf_pool_clock_tic();
|
||||
}
|
||||
|
||||
ut_a(!block->in_LRU_list);
|
||||
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
|
||||
block->in_LRU_list = TRUE;
|
||||
|
||||
if (srv_use_awe && block->frame) {
|
||||
/* Add to the list of mapped pages */
|
||||
@ -658,6 +665,9 @@ buf_LRU_add_block_low(
|
||||
ut_ad(block);
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(!block->in_LRU_list);
|
||||
|
||||
block->old = old;
|
||||
cl = buf_pool_clock_tic();
|
||||
|
||||
@ -687,6 +697,8 @@ buf_LRU_add_block_low(
|
||||
block->LRU_position = (buf_pool->LRU_old)->LRU_position;
|
||||
}
|
||||
|
||||
block->in_LRU_list = TRUE;
|
||||
|
||||
if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
|
||||
|
||||
ut_ad(buf_pool->LRU_old);
|
||||
@ -755,9 +767,12 @@ buf_LRU_block_free_non_file_page(
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(block);
|
||||
|
||||
ut_ad((block->state == BUF_BLOCK_MEMORY)
|
||||
ut_a((block->state == BUF_BLOCK_MEMORY)
|
||||
|| (block->state == BUF_BLOCK_READY_FOR_USE));
|
||||
|
||||
ut_a(block->n_pointers == 0);
|
||||
ut_a(!block->in_free_list);
|
||||
|
||||
block->state = BUF_BLOCK_NOT_USED;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
@ -765,6 +780,7 @@ buf_LRU_block_free_non_file_page(
|
||||
memset(block->frame, '\0', UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
UT_LIST_ADD_FIRST(free, buf_pool->free, block);
|
||||
block->in_free_list = TRUE;
|
||||
|
||||
if (srv_use_awe && block->frame) {
|
||||
/* Add to the list of mapped pages */
|
||||
@ -788,8 +804,7 @@ buf_LRU_block_remove_hashed_page(
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(block);
|
||||
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->io_fix == 0);
|
||||
ut_a(block->buf_fix_count == 0);
|
||||
ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0);
|
||||
@ -802,6 +817,28 @@ buf_LRU_block_remove_hashed_page(
|
||||
|
||||
buf_block_modify_clock_inc(block);
|
||||
|
||||
if (block != buf_page_hash_get(block->space, block->offset)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page %lu %lu not found from the hash table\n",
|
||||
block->space,
|
||||
block->offset);
|
||||
if (buf_page_hash_get(block->space, block->offset)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: From hash table we find block %lx of %lu %lu which is not %lx\n",
|
||||
(ulint)buf_page_hash_get(block->space, block->offset),
|
||||
buf_page_hash_get(block->space, block->offset)->space,
|
||||
buf_page_hash_get(block->space, block->offset)->offset,
|
||||
(ulint)block);
|
||||
}
|
||||
|
||||
buf_print();
|
||||
buf_LRU_print();
|
||||
buf_validate();
|
||||
buf_LRU_validate();
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
|
||||
buf_page_address_fold(block->space, block->offset),
|
||||
block);
|
||||
@ -819,7 +856,7 @@ buf_LRU_block_free_hashed_page(
|
||||
be in a state where it can be freed */
|
||||
{
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
ut_ad(block->state == BUF_BLOCK_REMOVE_HASH);
|
||||
ut_a(block->state == BUF_BLOCK_REMOVE_HASH);
|
||||
|
||||
block->state = BUF_BLOCK_MEMORY;
|
||||
|
||||
|
@ -129,6 +129,8 @@ buf_read_page_low(
|
||||
offset, sync);
|
||||
}
|
||||
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
*err = fil_io(OS_FILE_READ | wake_later,
|
||||
sync, space,
|
||||
offset, 0, UNIV_PAGE_SIZE,
|
||||
@ -604,7 +606,6 @@ buf_read_ibuf_merge_pages(
|
||||
}
|
||||
|
||||
for (i = 0; i < n_stored; i++) {
|
||||
|
||||
if ((i + 1 == n_stored) && sync) {
|
||||
buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE,
|
||||
space_ids[i], space_versions[i], page_nos[i]);
|
||||
|
@ -1517,8 +1517,8 @@ try_again:
|
||||
if (space == NULL) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: cannot delete tablespace %lu because it is not found\n"
|
||||
"InnoDB: in the tablespace memory cache.\n", id);
|
||||
" InnoDB: Error: cannot delete tablespace %lu\n"
|
||||
"InnoDB: because it is not found in the tablespace memory cache.\n", id);
|
||||
|
||||
mutex_exit(&(system->mutex));
|
||||
|
||||
@ -2426,19 +2426,24 @@ fil_space_for_table_exists_in_mem(
|
||||
if (namespace == NULL) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n"
|
||||
"InnoDB: id %lu, but tablespace with that id or name does not exist. Have\n"
|
||||
"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n",
|
||||
name, id, name);
|
||||
" InnoDB: Error: table %s\n"
|
||||
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
|
||||
"InnoDB: but tablespace with that id or name does not exist. Have\n"
|
||||
"InnoDB: you deleted or moved .ibd files?\n",
|
||||
name, id);
|
||||
} else {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n"
|
||||
"InnoDB: id %lu, but tablespace with that id does not exist. There is\n"
|
||||
" InnoDB: Error: table %s\n"
|
||||
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
|
||||
"InnoDB: but tablespace with that id does not exist. There is\n"
|
||||
"InnoDB: a tablespace of name %s and id %lu, though. Have\n"
|
||||
"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n",
|
||||
name, id, namespace->name, namespace->id, name);
|
||||
"InnoDB: you deleted or moved .ibd files?\n",
|
||||
name, id, namespace->name, namespace->id);
|
||||
}
|
||||
fprintf(stderr,
|
||||
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
|
||||
"InnoDB: how to resolve the issue.\n");
|
||||
|
||||
mutex_exit(&(system->mutex));
|
||||
|
||||
@ -2448,16 +2453,20 @@ fil_space_for_table_exists_in_mem(
|
||||
if (0 != strcmp(space->name, path)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n"
|
||||
"InnoDB: id %lu, but tablespace with that id has name %s. Have you\n"
|
||||
"InnoDB: deleted or moved .ibd files? We cannot open table %s now.\n",
|
||||
name, id, space->name, name);
|
||||
" InnoDB: Error: table %s\n"
|
||||
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
|
||||
"InnoDB: but tablespace with that id has name %s.\n"
|
||||
"InnoDB: Have you deleted or moved .ibd files?", name, id, space->name);
|
||||
if (namespace != NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: There is a tablespace with the right name %s, but its id is %lu.\n",
|
||||
namespace->name, namespace->id);
|
||||
"InnoDB: There is a tablespace with the right name\n"
|
||||
"InnoDB: %s, but its id is %lu.\n", namespace->name, namespace->id);
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
|
||||
"InnoDB: how to resolve the issue.\n");
|
||||
|
||||
mutex_exit(&(system->mutex));
|
||||
|
||||
return(FALSE);
|
||||
|
@ -34,6 +34,12 @@ ha_create(
|
||||
|
||||
table = hash_create(n);
|
||||
|
||||
if (in_btr_search) {
|
||||
table->adaptive = TRUE;
|
||||
} else {
|
||||
table->adaptive = FALSE;
|
||||
}
|
||||
|
||||
if (n_mutexes == 0) {
|
||||
if (in_btr_search) {
|
||||
table->heap = mem_heap_create_in_btr_search(4096);
|
||||
@ -106,6 +112,7 @@ ha_insert_for_fold(
|
||||
hash_cell_t* cell;
|
||||
ha_node_t* node;
|
||||
ha_node_t* prev_node;
|
||||
buf_block_t* prev_block;
|
||||
ulint hash;
|
||||
|
||||
ut_ad(table && data);
|
||||
@ -119,6 +126,12 @@ ha_insert_for_fold(
|
||||
|
||||
while (prev_node != NULL) {
|
||||
if (prev_node->fold == fold) {
|
||||
if (table->adaptive) {
|
||||
prev_block = buf_block_align(prev_node->data);
|
||||
ut_a(prev_block->n_pointers > 0);
|
||||
prev_block->n_pointers--;
|
||||
buf_block_align(data)->n_pointers++;
|
||||
}
|
||||
|
||||
prev_node->data = data;
|
||||
|
||||
@ -142,6 +155,11 @@ ha_insert_for_fold(
|
||||
}
|
||||
|
||||
ha_node_set_data(node, data);
|
||||
|
||||
if (table->adaptive) {
|
||||
buf_block_align(data)->n_pointers++;
|
||||
}
|
||||
|
||||
node->fold = fold;
|
||||
|
||||
node->next = NULL;
|
||||
@ -174,6 +192,11 @@ ha_delete_hash_node(
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ha_node_t* del_node) /* in: node to be deleted */
|
||||
{
|
||||
if (table->adaptive) {
|
||||
ut_a(buf_block_align(del_node->data)->n_pointers > 0);
|
||||
buf_block_align(del_node->data)->n_pointers--;
|
||||
}
|
||||
|
||||
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
|
||||
}
|
||||
|
||||
@ -199,6 +222,35 @@ ha_delete(
|
||||
ha_delete_hash_node(table, node);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Looks for an element when we know the pointer to the data, and updates
|
||||
the pointer to data, if found. */
|
||||
|
||||
void
|
||||
ha_search_and_update_if_found(
|
||||
/*==========================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: folded value of the searched data */
|
||||
void* data, /* in: pointer to the data */
|
||||
void* new_data)/* in: new pointer to the data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
||||
if (node) {
|
||||
if (table->adaptive) {
|
||||
ut_a(buf_block_align(node->data)->n_pointers > 0);
|
||||
buf_block_align(node->data)->n_pointers--;
|
||||
buf_block_align(new_data)->n_pointers++;
|
||||
}
|
||||
|
||||
node->data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Removes from the chain determined by fold all nodes whose data pointer
|
||||
points to the page given. */
|
||||
@ -229,10 +281,10 @@ ha_remove_all_nodes_to_page(
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
} else {
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Check that all nodes really got deleted */
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
@ -240,8 +292,9 @@ ha_remove_all_nodes_to_page(
|
||||
while (node) {
|
||||
ut_a(buf_frame_align(ha_node_get_data(node)) != page);
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@ -293,12 +346,10 @@ ha_print_info(
|
||||
hash_table_t* table) /* in: hash table */
|
||||
{
|
||||
hash_cell_t* cell;
|
||||
/*
|
||||
ha_node_t* node;
|
||||
ulint len = 0;
|
||||
ulint max_len = 0;
|
||||
ulint nodes = 0;
|
||||
*/
|
||||
/* ha_node_t* node;
|
||||
ulint nodes = 0;
|
||||
ulint len = 0;
|
||||
ulint max_len = 0; */
|
||||
ulint cells = 0;
|
||||
ulint n_bufs;
|
||||
ulint i;
|
||||
|
@ -91,6 +91,7 @@ hash_create(
|
||||
|
||||
array = ut_malloc(sizeof(hash_cell_t) * prime);
|
||||
|
||||
table->adaptive = FALSE;
|
||||
table->array = array;
|
||||
table->n_cells = prime;
|
||||
table->n_mutexes = 0;
|
||||
|
@ -755,12 +755,16 @@ struct buf_block_struct{
|
||||
|
||||
UT_LIST_NODE_T(buf_block_t) free;
|
||||
/* node of the free block list */
|
||||
ibool in_free_list; /* TRUE if in the free list; used in
|
||||
debugging */
|
||||
UT_LIST_NODE_T(buf_block_t) LRU;
|
||||
/* node of the LRU list */
|
||||
UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped;
|
||||
/* in the AWE version node in the
|
||||
list of free and LRU blocks which are
|
||||
mapped to a frame */
|
||||
ibool in_LRU_list; /* TRUE of the page is in the LRU list;
|
||||
used in debugging */
|
||||
ulint LRU_position; /* value which monotonically
|
||||
decreases (or may stay constant if
|
||||
the block is in the old blocks) toward
|
||||
@ -821,6 +825,9 @@ struct buf_block_struct{
|
||||
complete, though: there may have been
|
||||
hash collisions, record deletions,
|
||||
etc. */
|
||||
ulint n_pointers; /* used in debugging: the number of
|
||||
pointers in the adaptive hash index
|
||||
pointing to this frame */
|
||||
ulint curr_n_fields; /* prefix length for hash indexing:
|
||||
number of full fields */
|
||||
ulint curr_n_bytes; /* number of bytes in hash indexing */
|
||||
|
@ -28,7 +28,6 @@ buf_block_peek_if_too_old(
|
||||
{
|
||||
if (buf_pool->freed_page_clock >= block->freed_page_clock
|
||||
+ 1 + (buf_pool->curr_size / 1024)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
@ -169,7 +168,7 @@ buf_block_get_space(
|
||||
ut_ad(block);
|
||||
ut_ad(block >= buf_pool->blocks);
|
||||
ut_ad(block < buf_pool->blocks + buf_pool->max_size);
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->buf_fix_count > 0);
|
||||
|
||||
return(block->space);
|
||||
@ -187,7 +186,7 @@ buf_block_get_page_no(
|
||||
ut_ad(block);
|
||||
ut_ad(block >= buf_pool->blocks);
|
||||
ut_ad(block < buf_pool->blocks + buf_pool->max_size);
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->buf_fix_count > 0);
|
||||
|
||||
return(block->offset);
|
||||
@ -550,6 +549,8 @@ buf_page_hash_get(
|
||||
|
||||
HASH_SEARCH(hash, buf_pool->page_hash, fold, block,
|
||||
(block->space == space) && (block->offset == offset));
|
||||
ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
@ -617,8 +618,8 @@ buf_page_release(
|
||||
|
||||
mutex_enter_fast(&(buf_pool->mutex));
|
||||
|
||||
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->buf_fix_count > 0);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_a(block->buf_fix_count > 0);
|
||||
|
||||
if (rw_latch == RW_X_LATCH && mtr->modifications) {
|
||||
|
||||
|
@ -28,7 +28,7 @@ ha_search_and_get_data(
|
||||
/*************************************************************
|
||||
Looks for an element when we know the pointer to the data and updates
|
||||
the pointer to data if found. */
|
||||
UNIV_INLINE
|
||||
|
||||
void
|
||||
ha_search_and_update_if_found(
|
||||
/*==========================*/
|
||||
|
@ -49,7 +49,6 @@ ha_node_t*
|
||||
ha_chain_get_next(
|
||||
/*==============*/
|
||||
/* out: next node, NULL if none */
|
||||
hash_table_t* table __attribute__((unused)), /* in: hash table */
|
||||
ha_node_t* node) /* in: hash chain node */
|
||||
{
|
||||
ut_ad(table);
|
||||
@ -94,7 +93,7 @@ ha_search(
|
||||
return(node);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
@ -124,7 +123,7 @@ ha_search_and_get_data(
|
||||
return(node->data);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
@ -139,7 +138,6 @@ ha_next(
|
||||
/* out: pointer to the next hash table node
|
||||
in chain with the fold value, NULL if not
|
||||
found */
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ha_node_t* node) /* in: hash table node */
|
||||
{
|
||||
ulint fold;
|
||||
@ -148,7 +146,7 @@ ha_next(
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
|
||||
while (node) {
|
||||
if (node->fold == fold) {
|
||||
@ -156,7 +154,7 @@ ha_next(
|
||||
return(node);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
@ -186,35 +184,12 @@ ha_search_with_data(
|
||||
return(node);
|
||||
}
|
||||
|
||||
node = ha_chain_get_next(table, node);
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Looks for an element when we know the pointer to the data, and updates
|
||||
the pointer to data, if found. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
ha_search_and_update_if_found(
|
||||
/*==========================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: folded value of the searched data */
|
||||
void* data, /* in: pointer to the data */
|
||||
void* new_data)/* in: new pointer to the data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
||||
if (node) {
|
||||
node->data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Looks for an element when we know the pointer to the data, and deletes
|
||||
it from the hash table, if found. */
|
||||
|
@ -100,7 +100,7 @@ Deletes a struct from a hash table. */
|
||||
\
|
||||
while (struct3333->NAME != DATA) {\
|
||||
\
|
||||
ut_ad(struct3333)\
|
||||
ut_a(struct3333)\
|
||||
struct3333 = struct3333->NAME;\
|
||||
}\
|
||||
\
|
||||
@ -322,6 +322,8 @@ struct hash_cell_struct{
|
||||
|
||||
/* The hash table structure */
|
||||
struct hash_table_struct {
|
||||
ibool adaptive;/* TRUE if this is the hash table of the
|
||||
adaptive hash index */
|
||||
ulint n_cells;/* number of cells in the hash table */
|
||||
hash_cell_t* array; /* pointer to cell array */
|
||||
ulint n_mutexes;/* if mutexes != NULL, then the number of
|
||||
|
@ -218,7 +218,7 @@ ibuf_update_free_bits_if_full(
|
||||
}
|
||||
|
||||
if (after == 0) {
|
||||
/* We move the page to front of the buffer pool LRU list:
|
||||
/* We move the page to the front of the buffer pool LRU list:
|
||||
the purpose of this is to prevent those pages to which we
|
||||
cannot make inserts using the insert buffer from slipping
|
||||
out of the buffer pool */
|
||||
|
@ -339,6 +339,45 @@ row_drop_table_for_mysql(
|
||||
char* name, /* in: table name */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/*************************************************************************
|
||||
Discards the tablespace of a table which stored in an .ibd file. Discarding
|
||||
means that this function deletes the .ibd file and assigns a new table id for
|
||||
the table. Also the flag table->ibd_file_missing is set TRUE.
|
||||
|
||||
How do we prevent crashes caused by ongoing operations on the table? Old
|
||||
operations could try to access non-existent pages.
|
||||
|
||||
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock
|
||||
on the table before we can do DISCARD TABLESPACE. Then there are no running
|
||||
queries on the table.
|
||||
2) Purge and rollback: we assign a new table id for the table. Since purge and
|
||||
rollback look for the table based on the table id, they see the table as
|
||||
'dropped' and discard their operations.
|
||||
3) Insert buffer: we remove all entries for the tablespace in the insert
|
||||
buffer tree; as long as the tablespace mem object does not exist, ongoing
|
||||
insert buffer page merges are discarded in buf0rea.c. If we recreate the
|
||||
tablespace mem object with IMPORT TABLESPACE later, then the tablespace will
|
||||
have the same id, but the tablespace_version field in the mem object is
|
||||
different, and ongoing old insert buffer page merges get discarded.
|
||||
4) Linear readahead and random readahead: we use the same method as in 3) to
|
||||
discard ongoing operations. */
|
||||
|
||||
int
|
||||
row_discard_tablespace_for_mysql(
|
||||
/*=============================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
char* name, /* in: table name */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/*********************************************************************
|
||||
Imports a tablespace. The space id in the .ibd file must match the space id
|
||||
of the table in the data dictionary. */
|
||||
|
||||
int
|
||||
row_import_tablespace_for_mysql(
|
||||
/*============================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
char* name, /* in: table name */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/*************************************************************************
|
||||
Drops a database for MySQL. */
|
||||
|
||||
int
|
||||
|
@ -582,7 +582,8 @@ byte*
|
||||
page_parse_delete_rec_list(
|
||||
/*=======================*/
|
||||
/* out: end of log record or NULL */
|
||||
byte type, /* in: MLOG_LIST_END_DELETE or MLOG_LIST_START_DELETE */
|
||||
byte type, /* in: MLOG_LIST_END_DELETE or
|
||||
MLOG_LIST_START_DELETE */
|
||||
byte* ptr, /* in: buffer */
|
||||
byte* end_ptr,/* in: buffer end */
|
||||
page_t* page, /* in: page or NULL */
|
||||
|
@ -2007,9 +2007,6 @@ row_import_tablespace_for_mysql(
|
||||
|
||||
success = fil_open_single_table_tablespace(table->space, table->name);
|
||||
|
||||
printf(
|
||||
"Remember to stop purge + undo if table->ibd_file_is_missing!!!\n");
|
||||
|
||||
if (success) {
|
||||
table->ibd_file_missing = FALSE;
|
||||
table->tablespace_discarded = FALSE;
|
||||
|
@ -529,6 +529,14 @@ row_purge_parse_undo_rec(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (node->table->ibd_file_missing) {
|
||||
/* We skip purge of missing .ibd files */
|
||||
|
||||
node->table = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
if (clust_index == NULL) {
|
||||
|
@ -258,6 +258,13 @@ row_undo_ins_parse_undo_rec(
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->table->ibd_file_missing) {
|
||||
/* We skip undo operations to missing .ibd files */
|
||||
node->table = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
|
||||
|
@ -620,6 +620,13 @@ row_undo_mod_parse_undo_rec(
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->table->ibd_file_missing) {
|
||||
/* We skip undo operations to missing .ibd files */
|
||||
node->table = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clust_index = dict_table_get_first_index(node->table);
|
||||
|
||||
ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr,
|
||||
|
@ -1451,7 +1451,7 @@ ha_innobase::open(
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (ib_table->ibd_file_missing) {
|
||||
if (ib_table->ibd_file_missing && !current_thd->tablespace_op) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB error:\n"
|
||||
"MySQL is trying to open a table handle but the .ibd file for\n"
|
||||
@ -3628,6 +3628,42 @@ ha_innobase::create(
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Discards or imports an InnoDB tablespace. */
|
||||
|
||||
int
|
||||
ha_innobase::discard_or_import_tablespace(
|
||||
/*======================================*/
|
||||
/* out: 0 == success, -1 == error */
|
||||
my_bool discard) /* in: TRUE if discard, else import */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
dict_table_t* table;
|
||||
trx_t* trx;
|
||||
int err;
|
||||
|
||||
DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
|
||||
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
ut_a(prebuilt->trx ==
|
||||
(trx_t*) current_thd->transaction.all.innobase_tid);
|
||||
|
||||
table = prebuilt->table;
|
||||
trx = prebuilt->trx;
|
||||
|
||||
if (discard) {
|
||||
err = row_discard_tablespace_for_mysql(table->name, trx);
|
||||
} else {
|
||||
err = row_import_tablespace_for_mysql(table->name, trx);
|
||||
}
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Drops a table from an InnoDB database. Before calling this function,
|
||||
MySQL calls innobase_commit to commit the transaction of the current user.
|
||||
@ -3647,7 +3683,7 @@ ha_innobase::delete_table(
|
||||
trx_t* trx;
|
||||
char norm_name[1000];
|
||||
|
||||
DBUG_ENTER("ha_innobase::delete_table");
|
||||
DBUG_ENTER("ha_innobase::delete_table");
|
||||
|
||||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
@ -4536,7 +4572,8 @@ ha_innobase::external_lock(
|
||||
|
||||
update_thd(thd);
|
||||
|
||||
if (lock_type != F_UNLCK && prebuilt->table->ibd_file_missing) {
|
||||
if (lock_type != F_UNLCK && prebuilt->table->ibd_file_missing
|
||||
&& !current_thd->tablespace_op) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB error:\n"
|
||||
"MySQL is trying to use a table handle but the .ibd file for\n"
|
||||
@ -4546,6 +4583,7 @@ ha_innobase::external_lock(
|
||||
"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
|
||||
"how you can resolve the problem.\n",
|
||||
prebuilt->table->name);
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
trx = prebuilt->trx;
|
||||
@ -4793,11 +4831,12 @@ ha_innobase::store_lock(
|
||||
|
||||
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
|
||||
|
||||
/* If we are not doing a LOCK TABLE, then allow multiple
|
||||
writers */
|
||||
/* If we are not doing a LOCK TABLE or DISCARD/IMPORT
|
||||
TABLESPACE, then allow multiple writers */
|
||||
|
||||
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
|
||||
lock_type <= TL_WRITE) && !thd->in_lock_tables) {
|
||||
lock_type <= TL_WRITE) && !thd->in_lock_tables
|
||||
&& !thd->tablespace_op) {
|
||||
|
||||
lock_type = TL_WRITE_ALLOW_WRITE;
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ class ha_innobase: public handler
|
||||
void info(uint);
|
||||
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int discard_or_import_tablespace(my_bool discard);
|
||||
int extra(enum ha_extra_function operation);
|
||||
int reset(void);
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
|
@ -317,6 +317,7 @@ public:
|
||||
virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; }
|
||||
virtual void deactivate_non_unique_index(ha_rows rows) {}
|
||||
virtual bool activate_all_index(THD *thd) {return 0;}
|
||||
virtual int discard_or_import_tablespace(my_bool discard) {return -1;}
|
||||
// not implemented by default
|
||||
virtual int net_read_dump(NET* net)
|
||||
{ return ER_DUMP_NOT_IMPLEMENTED; }
|
||||
|
@ -130,6 +130,7 @@ static SYMBOL symbols[] = {
|
||||
{ "DESCRIBE", SYM(DESCRIBE),0,0},
|
||||
{ "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
|
||||
{ "DISABLE", SYM(DISABLE_SYM),0,0},
|
||||
{ "DISCARD", SYM(DISCARD),0,0},
|
||||
{ "DISTINCT", SYM(DISTINCT),0,0},
|
||||
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
|
||||
{ "DIV", SYM(DIV_SYM),0,0},
|
||||
@ -200,6 +201,7 @@ static SYMBOL symbols[] = {
|
||||
{ "INNER", SYM(INNER_SYM),0,0},
|
||||
{ "INNOBASE", SYM(INNOBASE_SYM),0,0},
|
||||
{ "INNODB", SYM(INNOBASE_SYM),0,0},
|
||||
{ "IMPORT", SYM(IMPORT),0,0},
|
||||
{ "INSERT", SYM(INSERT),0,0},
|
||||
{ "INSERT_METHOD", SYM(INSERT_METHOD),0,0},
|
||||
{ "INT", SYM(INT_SYM),0,0},
|
||||
@ -387,6 +389,7 @@ static SYMBOL symbols[] = {
|
||||
{ "SUPER", SYM(SUPER_SYM),0,0},
|
||||
{ "TABLE", SYM(TABLE_SYM),0,0},
|
||||
{ "TABLES", SYM(TABLES),0,0},
|
||||
{ "TABLESPACE", SYM(TABLESPACE),0,0},
|
||||
{ "TEMPORARY", SYM(TEMPORARY),0,0},
|
||||
{ "TERMINATED", SYM(TERMINATED),0,0},
|
||||
{ "TEXT", SYM(TEXT_SYM),0,0},
|
||||
|
@ -486,6 +486,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
||||
bool drop_primary,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
|
||||
enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
|
||||
bool simple_alter=0);
|
||||
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
|
@ -173,6 +173,7 @@ THD::THD():user_time(0), is_fatal_error(0),
|
||||
protocol_simple.init(this);
|
||||
protocol_prep.init(this);
|
||||
|
||||
tablespace_op=FALSE;
|
||||
#ifdef USING_TRANSACTIONS
|
||||
bzero((char*) &transaction,sizeof(transaction));
|
||||
if (opt_using_transactions)
|
||||
|
@ -502,6 +502,7 @@ public:
|
||||
time_t connect_time,thr_create_time; // track down slow pthread_create
|
||||
thr_lock_type update_lock_default;
|
||||
delayed_insert *di;
|
||||
my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
|
||||
struct st_transactions {
|
||||
IO_CACHE trans_log;
|
||||
THD_TRANS all; // Trans since BEGIN WORK
|
||||
|
@ -110,6 +110,11 @@ enum olap_type
|
||||
UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
|
||||
};
|
||||
|
||||
enum tablespace_op_type
|
||||
{
|
||||
NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE
|
||||
};
|
||||
|
||||
/*
|
||||
The state of the lex parsing for selects
|
||||
|
||||
@ -530,6 +535,7 @@ typedef struct st_lex
|
||||
enum ha_rkey_function ha_rkey_mode;
|
||||
enum enum_enable_or_disable alter_keys_onoff;
|
||||
enum enum_var_type option_type;
|
||||
enum tablespace_op_type tablespace_op;
|
||||
uint uint_geom_type;
|
||||
uint grant, grant_tot_col, which_columns;
|
||||
uint fk_delete_opt, fk_update_opt, fk_match_option;
|
||||
|
@ -2207,7 +2207,9 @@ mysql_execute_command(THD *thd)
|
||||
select_lex->order_list.elements,
|
||||
(ORDER *) select_lex->order_list.first,
|
||||
lex->drop_primary, lex->duplicates,
|
||||
lex->alter_keys_onoff, lex->simple_alter);
|
||||
lex->alter_keys_onoff,
|
||||
lex->tablespace_op,
|
||||
lex->simple_alter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1748,6 +1748,70 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
|
||||
&handler::check));
|
||||
}
|
||||
|
||||
/* table_list should contain just one table */
|
||||
int mysql_discard_or_import_tablespace(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
enum tablespace_op_type tablespace_op)
|
||||
{
|
||||
TABLE *table;
|
||||
my_bool discard;
|
||||
int error;
|
||||
DBUG_ENTER("mysql_discard_or_import_tablespace");
|
||||
|
||||
/* Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
|
||||
ALTER TABLE */
|
||||
|
||||
thd->proc_info="discard_or_import_tablespace";
|
||||
|
||||
if (tablespace_op == DISCARD_TABLESPACE)
|
||||
discard = TRUE;
|
||||
else
|
||||
discard = FALSE;
|
||||
|
||||
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
|
||||
and ::external_lock() do not complain when we
|
||||
lock the table */
|
||||
mysql_ha_closeall(thd, table_list);
|
||||
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
|
||||
{
|
||||
thd->tablespace_op=FALSE;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
thd->tablespace_op=FALSE;
|
||||
|
||||
error=table->file->discard_or_import_tablespace(discard);
|
||||
|
||||
thd->proc_info="end";
|
||||
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
/* The 0 in the call below means 'not in a transaction', which means
|
||||
immediate invalidation; that is probably what we wish here */
|
||||
query_cache_invalidate3(thd, table_list, 0);
|
||||
|
||||
/* The ALTER TABLE is always in its own transaction */
|
||||
error = ha_commit_stmt(thd);
|
||||
if (ha_commit(thd))
|
||||
error=1;
|
||||
if (error)
|
||||
goto err;
|
||||
mysql_update_log.write(thd, thd->query,thd->query_length);
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
err:
|
||||
close_thread_tables(thd);
|
||||
if (error == 0) {
|
||||
send_ok(thd);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
HA_CREATE_INFO *create_info,
|
||||
@ -1759,6 +1823,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
bool drop_primary,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
enum enum_enable_or_disable keys_onoff,
|
||||
enum tablespace_op_type tablespace_op,
|
||||
bool simple_alter)
|
||||
{
|
||||
TABLE *table,*new_table;
|
||||
@ -1771,6 +1836,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
ulonglong next_insert_id;
|
||||
uint save_time_stamp,db_create_options, used_fields;
|
||||
enum db_type old_db_type,new_db_type;
|
||||
thr_lock_type lock_type;
|
||||
DBUG_ENTER("mysql_alter_table");
|
||||
|
||||
thd->proc_info="init";
|
||||
@ -1781,6 +1847,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
used_fields=create_info->used_fields;
|
||||
|
||||
mysql_ha_closeall(thd, table_list);
|
||||
|
||||
if (tablespace_op != NO_TABLESPACE_OP)
|
||||
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
|
||||
tablespace_op));
|
||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
@ -1834,8 +1904,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
if (create_info->row_type == ROW_TYPE_NOT_USED)
|
||||
create_info->row_type=table->row_type;
|
||||
|
||||
/* In some simple cases we need not to recreate the table */
|
||||
|
||||
thd->proc_info="setup";
|
||||
if (simple_alter && !table->tmp_table)
|
||||
{
|
||||
@ -1860,6 +1928,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
switch (keys_onoff) {
|
||||
@ -2395,8 +2464,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* The ALTER TABLE is always in it's own transaction */
|
||||
/* The ALTER TABLE is always in its own transaction */
|
||||
error = ha_commit_stmt(thd);
|
||||
if (ha_commit(thd))
|
||||
error=1;
|
||||
@ -2695,4 +2763,3 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
|
||||
table->table=0;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
|
@ -211,6 +211,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||
%token DESCRIBE
|
||||
%token DES_KEY_FILE
|
||||
%token DISABLE_SYM
|
||||
%token DISCARD
|
||||
%token DISTINCT
|
||||
%token DUPLICATE_SYM
|
||||
%token DYNAMIC_SYM
|
||||
@ -244,6 +245,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||
%token HOSTS_SYM
|
||||
%token IDENT
|
||||
%token IGNORE_SYM
|
||||
%token IMPORT
|
||||
%token INDEX
|
||||
%token INDEXES
|
||||
%token INFILE
|
||||
@ -360,6 +362,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||
%token SUBJECT_SYM
|
||||
%token TABLES
|
||||
%token TABLE_SYM
|
||||
%token TABLESPACE
|
||||
%token TEMPORARY
|
||||
%token TERMINATED
|
||||
%token TEXT_STRING
|
||||
@ -1635,6 +1638,7 @@ alter:
|
||||
lex->create_info.table_charset= thd->variables.collation_database;
|
||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
lex->alter_keys_onoff=LEAVE_AS_IS;
|
||||
lex->tablespace_op=NO_TABLESPACE_OP;
|
||||
lex->simple_alter=1;
|
||||
}
|
||||
alter_list
|
||||
@ -1648,6 +1652,8 @@ alter:
|
||||
|
||||
|
||||
alter_list:
|
||||
| DISCARD TABLESPACE { Lex->tablespace_op=DISCARD_TABLESPACE; }
|
||||
| IMPORT TABLESPACE { Lex->tablespace_op=IMPORT_TABLESPACE; }
|
||||
| alter_list_item
|
||||
| alter_list ',' alter_list_item;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user