Commit 99d17803 authored by aivanov@mysql.com's avatar aivanov@mysql.com

Applied innodb-5.0-ss368 snapshot

  Fixed bugs:
  #16814: SHOW INNODB STATUS format error in LATEST FOREIGN KEY ERROR section
    dict_foreign_key_error_report(): Always print a newline after invoking
    dict_print_info_on_foreign_key_in_create_format().
  #16827: Better InnoDB error message if ibdata files omitted from my.cnf.
  #17126: CHECK TABLE on InnoDB causes a short hang during check of adaptive hash.
    CHECK TABLE blocking other queries, by releasing the btr_search_latch
    periodically during the adaptive hash table validation.
  #17405: Valgrind: conditional jump or move depends on uninitialised valuesw.
    buf_block_init(): Reset magic_n, buf_fix_count, and io_fix to avoid testing
    uninitialised variables.
  #18077: InnoDB uses full explicit table locks in stored FUNCTION.
  #18238: When locks exhaust the buffer pool, InnoDB does not roll back the trx.
    Check in pessimistic insert and update if the buffer pool is exhausted by locks.
  #18252: Disk space leaks in updates of InnoDB BLOB rows.
    btr_cur_pessimistic_update(): Invoke rec_get_offset() after rec_set_field_extern_bits().
    btr_store_big_rec_extern_fields(): Note that offsets will no longer be valid
    after calling this function.
  #18283: When InnoDB returns error 'lock table full', MySQL can write to binlog too much.
  #18384: InnoDB memory leak on duplicate key errors if row has many columns.
    row_ins_duplicate_error_in_clust(): Call mem_heap_free(heap) at func_exit if needed.
  #18350: Use consistent read in CREATE ... SELECT .. if innodb_locks_unsafe_for_binlog is used.
parent fc86e304
...@@ -1915,13 +1915,13 @@ btr_cur_pessimistic_update( ...@@ -1915,13 +1915,13 @@ btr_cur_pessimistic_update(
ut_a(rec || optim_err != DB_UNDERFLOW); ut_a(rec || optim_err != DB_UNDERFLOW);
if (rec) { if (rec) {
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
lock_rec_restore_from_page_infimum(rec, page); lock_rec_restore_from_page_infimum(rec, page);
rec_set_field_extern_bits(rec, index, rec_set_field_extern_bits(rec, index,
ext_vect, n_ext_vect, mtr); ext_vect, n_ext_vect, mtr);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally /* The new inserted record owns its possible externally
stored fields */ stored fields */
...@@ -3329,7 +3329,10 @@ btr_store_big_rec_extern_fields( ...@@ -3329,7 +3329,10 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */ MUST be X-latched */
rec_t* rec, /* in: record */ rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */ const ulint* offsets, /* in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */ to be stored externally */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr mtr_t* local_mtr __attribute__((unused))) /* in: mtr
......
...@@ -1600,14 +1600,29 @@ btr_search_validate(void) ...@@ -1600,14 +1600,29 @@ btr_search_validate(void)
ulint n_page_dumps = 0; ulint n_page_dumps = 0;
ibool ok = TRUE; ibool ok = TRUE;
ulint i; ulint i;
ulint cell_count;
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_;
*offsets_ = (sizeof offsets_) / sizeof *offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_;
/* How many cells to check before temporarily releasing
btr_search_latch. */
ulint chunk_size = 10000;
rw_lock_x_lock(&btr_search_latch); rw_lock_x_lock(&btr_search_latch);
for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { cell_count = hash_get_n_cells(btr_search_sys->hash_index);
for (i = 0; i < cell_count; i++) {
/* We release btr_search_latch every once in a while to
give other queries a chance to run. */
if ((i != 0) && ((i % chunk_size) == 0)) {
rw_lock_x_unlock(&btr_search_latch);
os_thread_yield();
rw_lock_x_lock(&btr_search_latch);
}
node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
while (node != NULL) { while (node != NULL) {
...@@ -1660,10 +1675,21 @@ btr_search_validate(void) ...@@ -1660,10 +1675,21 @@ btr_search_validate(void)
node = node->next; node = node->next;
} }
} }
if (!ha_validate(btr_search_sys->hash_index)) {
ok = FALSE; for (i = 0; i < cell_count; i += chunk_size) {
ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1);
/* We release btr_search_latch every once in a while to
give other queries a chance to run. */
if (i != 0) {
rw_lock_x_unlock(&btr_search_latch);
os_thread_yield();
rw_lock_x_lock(&btr_search_latch);
}
if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
ok = FALSE;
}
} }
rw_lock_x_unlock(&btr_search_latch); rw_lock_x_unlock(&btr_search_latch);
......
...@@ -464,12 +464,17 @@ buf_block_init( ...@@ -464,12 +464,17 @@ buf_block_init(
byte* frame) /* in: pointer to buffer frame, or NULL if in byte* frame) /* in: pointer to buffer frame, or NULL if in
the case of AWE there is no frame */ the case of AWE there is no frame */
{ {
block->magic_n = 0;
block->state = BUF_BLOCK_NOT_USED; block->state = BUF_BLOCK_NOT_USED;
block->frame = frame; block->frame = frame;
block->awe_info = NULL; block->awe_info = NULL;
block->buf_fix_count = 0;
block->io_fix = 0;
block->modify_clock = ut_dulint_zero; block->modify_clock = ut_dulint_zero;
block->file_page_was_freed = FALSE; block->file_page_was_freed = FALSE;
......
...@@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void) ...@@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void)
} }
/********************************************************************** /**********************************************************************
Returns TRUE if less than 15 % of the buffer pool is available. This can be Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */ pool for their locks. */
ibool ibool
buf_LRU_buf_pool_running_out(void) buf_LRU_buf_pool_running_out(void)
/*==============================*/ /*==============================*/
/* out: TRUE if less than 15 % of buffer pool /* out: TRUE if less than 25 % of buffer pool
left */ left */
{ {
ibool ret = FALSE; ibool ret = FALSE;
...@@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void) ...@@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void)
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) { + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
ret = TRUE; ret = TRUE;
} }
...@@ -340,11 +340,11 @@ buf_LRU_get_free_block(void) ...@@ -340,11 +340,11 @@ buf_LRU_get_free_block(void)
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) { + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n" " InnoDB: ERROR: over 95 percent of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n" "InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\n" "InnoDB: transactions do not set too many row locks.\n"
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n" "InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
...@@ -356,17 +356,17 @@ buf_LRU_get_free_block(void) ...@@ -356,17 +356,17 @@ buf_LRU_get_free_block(void)
ut_error; ut_error;
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) { + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
if (!buf_lru_switched_on_innodb_mon) { if (!buf_lru_switched_on_innodb_mon) {
/* Over 80 % of the buffer pool is occupied by lock /* Over 67 % of the buffer pool is occupied by lock
heaps or the adaptive hash index. This may be a memory heaps or the adaptive hash index. This may be a memory
leak! */ leak! */
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n" " InnoDB: WARNING: over 67 percent of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n" "InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\n" "InnoDB: transactions do not set too many row locks.\n"
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n" "InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
......
...@@ -252,7 +252,7 @@ dtype_print( ...@@ -252,7 +252,7 @@ dtype_print(
} else if (prtype == DATA_ENGLISH) { } else if (prtype == DATA_ENGLISH) {
fputs("DATA_ENGLISH", stderr); fputs("DATA_ENGLISH", stderr);
} else { } else {
fprintf(stderr, "prtype %lu", (ulong) mtype); fprintf(stderr, "prtype %lu", (ulong) prtype);
} }
} }
......
...@@ -2194,8 +2194,9 @@ dict_foreign_error_report( ...@@ -2194,8 +2194,9 @@ dict_foreign_error_report(
fputs(msg, file); fputs(msg, file);
fputs(" Constraint:\n", file); fputs(" Constraint:\n", file);
dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE);
putc('\n', file);
if (fk->foreign_index) { if (fk->foreign_index) {
fputs("\nThe index in the foreign key in table is ", file); fputs("The index in the foreign key in table is ", file);
ut_print_name(file, NULL, fk->foreign_index->name); ut_print_name(file, NULL, fk->foreign_index->name);
fputs( fputs(
"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" "\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
......
...@@ -3557,6 +3557,7 @@ fil_extend_space_to_desired_size( ...@@ -3557,6 +3557,7 @@ fil_extend_space_to_desired_size(
*actual_size = space->size; *actual_size = space->size;
#ifndef UNIV_HOTBACKUP
if (space_id == 0) { if (space_id == 0) {
ulint pages_per_mb = (1024 * 1024) / UNIV_PAGE_SIZE; ulint pages_per_mb = (1024 * 1024) / UNIV_PAGE_SIZE;
...@@ -3566,6 +3567,7 @@ fil_extend_space_to_desired_size( ...@@ -3566,6 +3567,7 @@ fil_extend_space_to_desired_size(
srv_data_file_sizes[srv_n_data_files - 1] = srv_data_file_sizes[srv_n_data_files - 1] =
(node->size / pages_per_mb) * pages_per_mb; (node->size / pages_per_mb) * pages_per_mb;
} }
#endif /* !UNIV_HOTBACKUP */
/* /*
printf("Extended %s to %lu, actual size %lu pages\n", space->name, printf("Extended %s to %lu, actual size %lu pages\n", space->name,
...@@ -3820,6 +3822,31 @@ fil_node_complete_io( ...@@ -3820,6 +3822,31 @@ fil_node_complete_io(
} }
} }
/************************************************************************
Report information about an invalid page access. */
static
void
fil_report_invalid_page_access(
/*===========================*/
ulint block_offset, /* in: block offset */
ulint space_id, /* in: space id */
const char* space_name, /* in: space name */
ulint byte_offset, /* in: byte offset */
ulint len, /* in: I/O length */
ulint type) /* in: I/O type */
{
fprintf(stderr,
"InnoDB: Error: trying to access page number %lu in space %lu,\n"
"InnoDB: space name %s,\n"
"InnoDB: which is outside the tablespace bounds.\n"
"InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
"InnoDB: If you get this error at mysqld startup, please check that\n"
"InnoDB: your my.cnf matches the ibdata files that you have in the\n"
"InnoDB: MySQL server.\n",
(ulong) block_offset, (ulong) space_id, space_name,
(ulong) byte_offset, (ulong) len, (ulong) type);
}
/************************************************************************ /************************************************************************
Reads or writes data. This operation is asynchronous (aio). */ Reads or writes data. This operation is asynchronous (aio). */
...@@ -3926,14 +3953,8 @@ fil_io( ...@@ -3926,14 +3953,8 @@ fil_io(
for (;;) { for (;;) {
if (node == NULL) { if (node == NULL) {
fprintf(stderr, fil_report_invalid_page_access(block_offset, space_id,
"InnoDB: Error: trying to access page number %lu in space %lu,\n" space->name, byte_offset, len, type);
"InnoDB: space name %s,\n"
"InnoDB: which is outside the tablespace bounds.\n"
"InnoDB: Byte offset %lu, len %lu, i/o type %lu\n",
(ulong) block_offset, (ulong) space_id,
space->name, (ulong) byte_offset, (ulong) len,
(ulong) type);
ut_error; ut_error;
} }
...@@ -3962,15 +3983,10 @@ fil_io( ...@@ -3962,15 +3983,10 @@ fil_io(
if (space->purpose == FIL_TABLESPACE && space->id != 0 if (space->purpose == FIL_TABLESPACE && space->id != 0
&& node->size <= block_offset) { && node->size <= block_offset) {
fprintf(stderr, fil_report_invalid_page_access(block_offset, space_id,
"InnoDB: Error: trying to access page number %lu in space %lu,\n" space->name, byte_offset, len, type);
"InnoDB: space name %s,\n"
"InnoDB: which is outside the tablespace bounds.\n" ut_error;
"InnoDB: Byte offset %lu, len %lu, i/o type %lu\n",
(ulong) block_offset, (ulong) space_id,
space->name, (ulong) byte_offset, (ulong) len,
(ulong) type);
ut_a(0);
} }
/* Now we have made the changes in the data structures of system */ /* Now we have made the changes in the data structures of system */
......
...@@ -276,20 +276,26 @@ ha_remove_all_nodes_to_page( ...@@ -276,20 +276,26 @@ ha_remove_all_nodes_to_page(
} }
/***************************************************************** /*****************************************************************
Validates a hash table. */ Validates a given range of the cells in hash table. */
ibool ibool
ha_validate( ha_validate(
/*========*/ /*========*/
/* out: TRUE if ok */ /* out: TRUE if ok */
hash_table_t* table) /* in: hash table */ hash_table_t* table, /* in: hash table */
ulint start_index, /* in: start index */
ulint end_index) /* in: end index */
{ {
hash_cell_t* cell; hash_cell_t* cell;
ha_node_t* node; ha_node_t* node;
ibool ok = TRUE; ibool ok = TRUE;
ulint i; ulint i;
for (i = 0; i < hash_get_n_cells(table); i++) { ut_a(start_index <= end_index);
ut_a(start_index < hash_get_n_cells(table));
ut_a(end_index < hash_get_n_cells(table));
for (i = start_index; i <= end_index; i++) {
cell = hash_get_nth_cell(table, i); cell = hash_get_nth_cell(table, i);
......
...@@ -459,7 +459,10 @@ btr_store_big_rec_extern_fields( ...@@ -459,7 +459,10 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */ MUST be X-latched */
rec_t* rec, /* in: record */ rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */ const ulint* offsets, /* in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */ to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to mtr_t* local_mtr); /* in: mtr containing the latch to
......
...@@ -26,14 +26,14 @@ void ...@@ -26,14 +26,14 @@ void
buf_LRU_try_free_flushed_blocks(void); buf_LRU_try_free_flushed_blocks(void);
/*==================================*/ /*==================================*/
/********************************************************************** /**********************************************************************
Returns TRUE if less than 15 % of the buffer pool is available. This can be Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */ pool for their locks. */
ibool ibool
buf_LRU_buf_pool_running_out(void); buf_LRU_buf_pool_running_out(void);
/*==============================*/ /*==============================*/
/* out: TRUE if less than 15 % of buffer pool /* out: TRUE if less than 25 % of buffer pool
left */ left */
/*####################################################################### /*#######################################################################
......
...@@ -114,13 +114,15 @@ ha_remove_all_nodes_to_page( ...@@ -114,13 +114,15 @@ ha_remove_all_nodes_to_page(
ulint fold, /* in: fold value */ ulint fold, /* in: fold value */
page_t* page); /* in: buffer page */ page_t* page); /* in: buffer page */
/***************************************************************** /*****************************************************************
Validates a hash table. */ Validates a given range of the cells in hash table. */
ibool ibool
ha_validate( ha_validate(
/*========*/ /*========*/
/* out: TRUE if ok */ /* out: TRUE if ok */
hash_table_t* table); /* in: hash table */ hash_table_t* table, /* in: hash table */
ulint start_index, /* in: start index */
ulint end_index); /* in: end index */
/***************************************************************** /*****************************************************************
Prints info of a hash table. */ Prints info of a hash table. */
......
...@@ -175,19 +175,6 @@ page_rec_is_comp( ...@@ -175,19 +175,6 @@ page_rec_is_comp(
/* out: nonzero if in compact format */ /* out: nonzero if in compact format */
const rec_t* rec) /* in: record */ const rec_t* rec) /* in: record */
{ {
#ifdef UNIV_RELEASE_NOT_YET_STABLE
if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero))
|| UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: trying to read a stray page rec %p\n"
"InnoDB: buf pool start is at %p, end at %p\n",
rec, buf_pool->frame_zero,
buf_pool->high_end);
ut_error;
}
#endif
return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE))); return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
} }
......
...@@ -80,10 +80,6 @@ memory is read outside the allocated blocks. */ ...@@ -80,10 +80,6 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */ /* Make a non-inline debug version */
/* You can remove this define when the release is stable. This define adds
some consistency checks to code. They use a little CPU time. */
#define UNIV_RELEASE_NOT_YET_STABLE
/* /*
#define UNIV_DEBUG #define UNIV_DEBUG
#define UNIV_MEM_DEBUG #define UNIV_MEM_DEBUG
......
...@@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri ...@@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri
#include "eval0eval.h" #include "eval0eval.h"
#include "data0data.h" #include "data0data.h"
#include "usr0sess.h" #include "usr0sess.h"
#include "buf0lru.h"
#define ROW_INS_PREV 1 #define ROW_INS_PREV 1
#define ROW_INS_NEXT 2 #define ROW_INS_NEXT 2
...@@ -278,10 +279,17 @@ row_ins_sec_index_entry_by_modify( ...@@ -278,10 +279,17 @@ row_ins_sec_index_entry_by_modify(
} }
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
}
err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor, err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
&dummy_big_rec, update, 0, thr, mtr); &dummy_big_rec, update, 0, thr, mtr);
} }
func_exit:
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
...@@ -342,10 +350,16 @@ row_ins_clust_index_entry_by_modify( ...@@ -342,10 +350,16 @@ row_ins_clust_index_entry_by_modify(
} }
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
}
err = btr_cur_pessimistic_update(0, cursor, big_rec, update, err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
0, thr, mtr); 0, thr, mtr);
} }
func_exit:
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
...@@ -1860,7 +1874,6 @@ row_ins_duplicate_error_in_clust( ...@@ -1860,7 +1874,6 @@ row_ins_duplicate_error_in_clust(
err = DB_DUPLICATE_KEY; err = DB_DUPLICATE_KEY;
goto func_exit; goto func_exit;
} }
mem_heap_free(heap);
} }
ut_a(!(cursor->index->type & DICT_CLUSTERED)); ut_a(!(cursor->index->type & DICT_CLUSTERED));
...@@ -1869,6 +1882,9 @@ row_ins_duplicate_error_in_clust( ...@@ -1869,6 +1882,9 @@ row_ins_duplicate_error_in_clust(
err = DB_SUCCESS; err = DB_SUCCESS;
func_exit: func_exit:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err); return(err);
#else /* UNIV_HOTBACKUP */ #else /* UNIV_HOTBACKUP */
/* This function depends on MySQL code that is not included in /* This function depends on MySQL code that is not included in
...@@ -2068,6 +2084,12 @@ row_ins_index_entry_low( ...@@ -2068,6 +2084,12 @@ row_ins_index_entry_low(
&insert_rec, &big_rec, thr, &mtr); &insert_rec, &big_rec, thr, &mtr);
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto function_exit;
}
err = btr_cur_pessimistic_insert(0, &cursor, entry, err = btr_cur_pessimistic_insert(0, &cursor, entry,
&insert_rec, &big_rec, thr, &mtr); &insert_rec, &big_rec, thr, &mtr);
} }
......
...@@ -2358,16 +2358,16 @@ row_sel_field_store_in_mysql_format( ...@@ -2358,16 +2358,16 @@ row_sel_field_store_in_mysql_format(
} else if (templ->type == DATA_MYSQL) { } else if (templ->type == DATA_MYSQL) {
memcpy(dest, data, len); memcpy(dest, data, len);
ut_a(templ->mysql_col_len >= len); ut_ad(templ->mysql_col_len >= len);
ut_a(templ->mbmaxlen >= templ->mbminlen); ut_ad(templ->mbmaxlen >= templ->mbminlen);
ut_a(templ->mbmaxlen > templ->mbminlen ut_ad(templ->mbmaxlen > templ->mbminlen
|| templ->mysql_col_len == len); || templ->mysql_col_len == len);
/* The following assertion would fail for old tables /* The following assertion would fail for old tables
containing UTF-8 ENUM columns due to Bug #9526. */ containing UTF-8 ENUM columns due to Bug #9526. */
ut_ad(!templ->mbmaxlen ut_ad(!templ->mbmaxlen
|| !(templ->mysql_col_len % templ->mbmaxlen)); || !(templ->mysql_col_len % templ->mbmaxlen));
ut_a(len * templ->mbmaxlen >= templ->mysql_col_len); ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
if (templ->mbminlen != templ->mbmaxlen) { if (templ->mbminlen != templ->mbmaxlen) {
/* Pad with spaces. This undoes the stripping /* Pad with spaces. This undoes the stripping
...@@ -2377,7 +2377,7 @@ row_sel_field_store_in_mysql_format( ...@@ -2377,7 +2377,7 @@ row_sel_field_store_in_mysql_format(
memset(dest + len, 0x20, templ->mysql_col_len - len); memset(dest + len, 0x20, templ->mysql_col_len - len);
} }
} else { } else {
ut_a(templ->type == DATA_CHAR ut_ad(templ->type == DATA_CHAR
|| templ->type == DATA_FIXBINARY || templ->type == DATA_FIXBINARY
/*|| templ->type == DATA_SYS_CHILD /*|| templ->type == DATA_SYS_CHILD
|| templ->type == DATA_SYS*/ || templ->type == DATA_SYS*/
......
...@@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri ...@@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri
#include "log0log.h" #include "log0log.h"
#include "pars0sym.h" #include "pars0sym.h"
#include "eval0eval.h" #include "eval0eval.h"
#include "buf0lru.h"
/* What kind of latch and lock can we assume when the control comes to /* What kind of latch and lock can we assume when the control comes to
...@@ -1523,6 +1524,10 @@ row_upd_clust_rec( ...@@ -1523,6 +1524,10 @@ row_upd_clust_rec(
return(err); return(err);
} }
if (buf_LRU_buf_pool_running_out()) {
return(DB_LOCK_TABLE_FULL);
}
/* We may have to modify the tree structure: do a pessimistic descent /* We may have to modify the tree structure: do a pessimistic descent
down the index tree */ down the index tree */
......
...@@ -1762,7 +1762,6 @@ commit; ...@@ -1762,7 +1762,6 @@ commit;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1005 -- error 1005
create table t1(a char(10) primary key, b varchar(20)) engine = innodb; create table t1(a char(10) primary key, b varchar(20)) engine = innodb;
set foreign_key_checks=1; set foreign_key_checks=1;
...@@ -1773,7 +1772,6 @@ drop table t2; ...@@ -1773,7 +1772,6 @@ drop table t2;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1005 -- error 1005
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8;
set foreign_key_checks=1; set foreign_key_checks=1;
...@@ -1803,7 +1801,6 @@ drop table t2,t1; ...@@ -1803,7 +1801,6 @@ drop table t2,t1;
set foreign_key_checks=0; set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
--replace_result $MYSQLTEST_VARDIR . master-data/ ''
-- error 1025 -- error 1025
rename table t3 to t1; rename table t3 to t1;
set foreign_key_checks=1; set foreign_key_checks=1;
...@@ -2124,5 +2121,6 @@ drop trigger t2t; ...@@ -2124,5 +2121,6 @@ drop trigger t2t;
drop trigger t3t; drop trigger t3t;
drop trigger t4t; drop trigger t4t;
drop table t1, t2, t3, t4, t5; drop table t1, t2, t3, t4, t5;
connection default;
disconnect a; disconnect a;
disconnect b; disconnect b;
...@@ -513,13 +513,13 @@ convert_error_code_to_mysql( ...@@ -513,13 +513,13 @@ convert_error_code_to_mysql(
return(HA_ERR_NO_SAVEPOINT); return(HA_ERR_NO_SAVEPOINT);
} else if (error == (int) DB_LOCK_TABLE_FULL) { } else if (error == (int) DB_LOCK_TABLE_FULL) {
/* Since we rolled back the whole transaction, we must /* Since we rolled back the whole transaction, we must
tell it also to MySQL so that MySQL knows to empty the tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */ cached binlog for this transaction */
if (thd) { if (thd) {
ha_rollback(thd); ha_rollback(thd);
} }
return(HA_ERR_LOCK_TABLE_FULL); return(HA_ERR_LOCK_TABLE_FULL);
} else { } else {
...@@ -6726,32 +6726,37 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, ...@@ -6726,32 +6726,37 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name) static INNOBASE_SHARE *get_share(const char *table_name)
{ {
INNOBASE_SHARE *share; INNOBASE_SHARE *share;
pthread_mutex_lock(&innobase_share_mutex); pthread_mutex_lock(&innobase_share_mutex);
uint length=(uint) strlen(table_name); uint length=(uint) strlen(table_name);
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
(mysql_byte*) table_name, if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
length))) (mysql_byte*) table_name,
{ length))) {
if ((share=(INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
MYF(MY_WME | MY_ZEROFILL)))) share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
{ MYF(MY_FAE | MY_ZEROFILL));
share->table_name_length=length;
share->table_name=(char*) (share+1); share->table_name_length=length;
strmov(share->table_name,table_name); share->table_name=(char*) (share+1);
if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share)) strmov(share->table_name,table_name);
{
pthread_mutex_unlock(&innobase_share_mutex); if (my_hash_insert(&innobase_open_tables,
my_free((gptr) share,0); (mysql_byte*) share)) {
return 0; pthread_mutex_unlock(&innobase_share_mutex);
} my_free((gptr) share,0);
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); return 0;
} }
}
share->use_count++; thr_lock_init(&share->lock);
pthread_mutex_unlock(&innobase_share_mutex); pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
return share; }
share->use_count++;
pthread_mutex_unlock(&innobase_share_mutex);
return share;
} }
static void free_share(INNOBASE_SHARE *share) static void free_share(INNOBASE_SHARE *share)
...@@ -6825,14 +6830,16 @@ ha_innobase::store_lock( ...@@ -6825,14 +6830,16 @@ ha_innobase::store_lock(
prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE && prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
(lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
(thd->lex->sql_command == SQLCOM_INSERT_SELECT || (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
thd->lex->sql_command == SQLCOM_UPDATE)) { thd->lex->sql_command == SQLCOM_UPDATE ||
thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
/* In case we have innobase_locks_unsafe_for_binlog /* In case we have innobase_locks_unsafe_for_binlog
option set and isolation level of the transaction option set and isolation level of the transaction
is not set to serializable and MySQL is doing is not set to serializable and MySQL is doing
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
without FOR UPDATE or IN SHARE MODE in select, then CREATE ... SELECT... without FOR UPDATE or
we use consistent read for select. */ IN SHARE MODE in select, then we use consistent
read for select. */
prebuilt->select_lock_type = LOCK_NONE; prebuilt->select_lock_type = LOCK_NONE;
prebuilt->stored_select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = LOCK_NONE;
...@@ -6885,14 +6892,15 @@ ha_innobase::store_lock( ...@@ -6885,14 +6892,15 @@ ha_innobase::store_lock(
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
< TL_WRITE_CONCURRENT_INSERT. < TL_WRITE_CONCURRENT_INSERT.
We especially allow multiple writers if MySQL is at the We especially allow multiple writers if MySQL is at the
start of a stored procedure call (SQLCOM_CALL) start of a stored procedure call (SQLCOM_CALL) or a
(MySQL does have thd->in_lock_tables TRUE there). */ stored function call (MySQL does have thd->in_lock_tables
TRUE there). */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
&& lock_type <= TL_WRITE) && lock_type <= TL_WRITE)
&& !(thd->in_lock_tables && !(thd->in_lock_tables
&& thd->lex->sql_command == SQLCOM_LOCK_TABLES) && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
&& !thd->tablespace_op && !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_OPTIMIZE && thd->lex->sql_command != SQLCOM_OPTIMIZE
......
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