Commit f900b658 authored by Michael Widenius's avatar Michael Widenius

Merge of innodb_plugin for MySQL 5.1.53 with xtradb

Fixed compiler warnings in xtradb
Added back resetting of null bitmap but now in row_search_for_mysql()

storage/xtradb/row/row0sel.c:
  Added back resetting of null bitmap but now in row_search_for_mysql()
parent 721a6a6a
......@@ -8,10 +8,8 @@ AC_DEFUN([MY_MAINTAINER_MODE], [
[AS_HELP_STRING([--enable-mysql-maintainer-mode],
[Enable a MySQL maintainer-specific development environment])],
[USE_MYSQL_MAINTAINER_MODE=$enableval],
[USE_MYSQL_MAINTAINER_MODE=no])
# Remove the # from following comments after merge with xtradb for 5.1.53
# [AS_IF([test "$with_debug" != "no"],
# [USE_MYSQL_MAINTAINER_MODE=yes], [USE_MYSQL_MAINTAINER_MODE=no])])
[AS_IF([test "$with_debug" != "no"],
[USE_MYSQL_MAINTAINER_MODE=yes], [USE_MYSQL_MAINTAINER_MODE=no])])
AC_MSG_RESULT([$USE_MYSQL_MAINTAINER_MODE])
])
......
......@@ -77,7 +77,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
unsigned int null_mask= 1U;
for ( ; (field= *p_field) ; p_field++)
{
DBUG_PRINT("debug", ("null_mask=%d; null_ptr=%p; row_data=%p; null_byte_count=%d",
DBUG_PRINT("debug", ("null_mask: %d null_ptr: %p row_data: %p null_byte_count: %d",
null_mask, null_ptr, row_data, null_byte_count));
if (bitmap_is_set(cols, p_field - table->field))
{
......
2010-10-24 The InnoDB Team
* row/row0mysql.c
Fix Bug #57700 Latching order violation in
row_truncate_table_for_mysql()
2010-10-20 The InnoDB Team
* dict/dict0load.c
Fix Bug #57616 Sig 11 in dict_load_table() when failed to load
index or foreign key
2010-10-19 The InnoDB Team
* btr/btr0cur.c, buf/buf0buf.c, buf/buf0flu.c, handler/ha_innodb.cc,
ibuf/ibuf0ibuf.c, include/btr0cur.h, include/buf0flu.h,
include/ibuf0ibuf.h, include/row0mysql.h,
row/row0mysql.c, row/row0sel.c,
innodb_bug56680.test, innodb_bug56680.result:
Fix Bug #56680 InnoDB may return wrong results from a
case-insensitive covering index
2010-10-18 The InnoDB Team
* handler/ha_innodb.cc, handler/ha_innodb.h, innodb_bug57252.result,
innodb_bug57252.test:
Fix Bug#57252 disabling innobase_stats_on_metadata disables ANALYZE
2010-10-14 The InnoDB Team
* handler/ha_innodb.cc, innodb_bug56143.result, innodb_bug56143.test:
Fix Bug#56143 too many foreign keys causes output of show create
table to become invalid
2010-10-14 The InnoDB Team
* srv/srv0start.c:
Fix Bug#57397 io_handler_thread() will never cleanup
2010-10-11 The InnoDB Team
* row/row0sel.c
Fix Bug #57345 btr_pcur_store_position abort for load with
concurrent lock/unlock tables
2010-10-11 The InnoDB Team
* row/row0mysql.c, innodb_bug56947.result, innodb_bug56947.test:
Fix Bug #56947 InnoDB leaks memory when failing to create a table
2010-10-06 The InnoDB Team
* row/row0mysql.c, innodb_bug57255.result, innodb_bug57255.test
Fix Bug #Cascade Delete results in "Got error -1 from storage engine"
Fix Bug #57255 Cascade Delete results in "Got error -1 from
storage engine"
2010-09-27 The InnoDB Team
* row/row0sel.c, innodb_bug56716.result, innodb_bug56716.test:
Fix Bug #56716 InnoDB locks a record gap without locking the table
Fix Bug#56716 InnoDB locks a record gap without locking the table
2010-09-06 The InnoDB Team
* dict/dict0load.c, innodb_bug53756.test innodb_bug53756.result
Fix Bug #53756 ALTER TABLE ADD PRIMARY KEY affects crash recovery
* dict/dict0load.c, innodb_bug53756.test innodb_bug53756.result:
Fix Bug#53756 ALTER TABLE ADD PRIMARY KEY affects crash recovery
2010-08-24 The InnoDB Team
* handler/ha_innodb.c, dict/dict0dict.c:
Fix Bug #55832 selects crash too easily when innodb_force_recovery>3
Fix Bug#55832 selects crash too easily when innodb_force_recovery>3
2010-08-03 The InnoDB Team
......@@ -37,13 +85,13 @@
2010-08-03 The InnoDB Team
* include/ut0mem.h, ut/ut0mem.c:
Fix Bug #55627 segv in ut_free pars_lexer_close innobase_shutdown
Fix Bug#55627 segv in ut_free pars_lexer_close innobase_shutdown
innodb-use-sys-malloc=0
2010-08-01 The InnoDB Team
* handler/ha_innodb.cc
Fix Bug #55382 Assignment with SELECT expressions takes unexpected
* handler/ha_innodb.cc:
Fix Bug#55382 Assignment with SELECT expressions takes unexpected
S locks in READ COMMITTED
2010-07-27 The InnoDB Team
......@@ -65,8 +113,8 @@
2010-06-29 The InnoDB Team
* btr/btr0cur.c, include/btr0cur.h,
include/row0mysql.h, row/row0merge.c, row/row0sel.c:
* btr/btr0cur.c, include/btr0cur.h, include/row0mysql.h,
row/row0merge.c, row/row0sel.c:
Fix Bug#54358 READ UNCOMMITTED access failure of off-page DYNAMIC
or COMPRESSED columns
......
......@@ -1803,7 +1803,7 @@ func_exit:
See if there is enough place in the page modification log to log
an update-in-place.
@return TRUE if enough place */
static
UNIV_INTERN
ibool
btr_cur_update_alloc_zip(
/*=====================*/
......
......@@ -2511,6 +2511,30 @@ wait_until_unfixed:
bytes. */
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
#endif
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if (mode == BUF_GET_IF_IN_POOL && ibuf_debug) {
/* Try to evict the block from the buffer pool, to use the
insert buffer as much as possible. */
if (buf_LRU_free_block(&block->page, TRUE, NULL)
== BUF_LRU_FREED) {
buf_pool_mutex_exit();
mutex_exit(&block->mutex);
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
return(NULL);
} else if (buf_flush_page_try(block)) {
fprintf(stderr,
"innodb_change_buffering_debug flush %u %u\n",
(unsigned) space, (unsigned) offset);
guess = block;
goto loop;
}
/* Failed to evict the page; change it directly */
}
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
buf_block_buf_fix_inc(block, file, line);
......
......@@ -1064,6 +1064,82 @@ buf_flush_write_block_low(
}
}
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: buf_pool_mutex and block->mutex must be held upon entering this
function, and they will be released by this function after flushing.
This is loosely based on buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
ibool
buf_flush_page_try(
/*===============*/
buf_block_t* block) /*!< in/out: buffer control block */
{
ut_ad(buf_pool_mutex_own());
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(mutex_own(&block->mutex));
if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_LRU)) {
return(FALSE);
}
if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0
|| buf_pool->init_flush[BUF_FLUSH_LRU]) {
/* There is already a flush batch of the same type running */
return(FALSE);
}
buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE;
buf_page_set_io_fix(&block->page, BUF_IO_WRITE);
buf_page_set_flush_type(&block->page, BUF_FLUSH_LRU);
if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) {
os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]);
}
/* VERY IMPORTANT:
Because any thread may call the LRU flush, even when owning
locks on pages, to avoid deadlocks, we must make sure that the
s-lock is acquired on the page without waiting: this is
accomplished because buf_flush_ready_for_flush() must hold,
and that requires the page not to be bufferfixed. */
rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE);
/* Note that the s-latch is acquired before releasing the
buf_pool mutex: this ensures that the latch is acquired
immediately. */
mutex_exit(&block->mutex);
buf_pool_mutex_exit();
/* Even though block is not protected by any mutex at this
point, it is safe to access block, because it is io_fixed and
oldest_modification != 0. Thus, it cannot be relocated in the
buffer pool or removed from flush_list or LRU_list. */
buf_flush_write_block_low(&block->page);
buf_pool_mutex_enter();
buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE;
if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) {
/* The running flush batch has ended */
os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]);
}
buf_pool_mutex_exit();
buf_flush_buffered_writes();
return(TRUE);
}
# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: in simulated aio we must call
......
......@@ -1024,13 +1024,13 @@ err_exit:
if (err != DB_SUCCESS) {
dict_table_remove_from_cache(table);
table = NULL;
} else {
table->fk_max_recusive_level = 0;
}
} else if (!srv_force_recovery) {
dict_table_remove_from_cache(table);
table = NULL;
}
table->fk_max_recusive_level = 0;
#if 0
if (err != DB_SUCCESS && table != NULL) {
......
......@@ -4751,17 +4751,18 @@ include_field:
n_requested_fields++;
templ->col_no = i;
templ->clust_rec_field_no = dict_col_get_clust_pos(
&index->table->cols[i], clust_index);
ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED);
if (index == clust_index) {
templ->rec_field_no = dict_col_get_clust_pos(
&index->table->cols[i], index);
templ->rec_field_no = templ->clust_rec_field_no;
} else {
templ->rec_field_no = dict_index_get_nth_col_pos(
index, i);
}
if (templ->rec_field_no == ULINT_UNDEFINED) {
prebuilt->need_to_access_clustered = TRUE;
if (templ->rec_field_no == ULINT_UNDEFINED) {
prebuilt->need_to_access_clustered = TRUE;
}
}
if (field->null_ptr) {
......@@ -4813,9 +4814,7 @@ skip_field:
for (i = 0; i < n_requested_fields; i++) {
templ = prebuilt->mysql_template + i;
templ->rec_field_no = dict_col_get_clust_pos(
&index->table->cols[templ->col_no],
clust_index);
templ->rec_field_no = templ->clust_rec_field_no;
}
}
}
......@@ -6756,8 +6755,8 @@ create_options_are_valid(
? "COMPRESSED"
: "DYNAMIC";
/* These two ROW_FORMATs require
srv_file_per_table and srv_file_format */
/* These two ROW_FORMATs require srv_file_per_table
and srv_file_format > Antelope */
if (!srv_file_per_table) {
push_warning_printf(
thd,
......@@ -6767,7 +6766,6 @@ create_options_are_valid(
" requires innodb_file_per_table.",
row_format_name);
ret = FALSE;
}
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
......@@ -6966,6 +6964,8 @@ ha_innobase::create(
ulint ssize, ksize;
ulint key_block_size = create_info->key_block_size;
/* Set 'flags' to the correct key_block_size.
It will be zero if key_block_size is an invalid number.*/
for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX;
ssize++, ksize <<= 1) {
if (key_block_size == ksize) {
......@@ -7006,10 +7006,10 @@ ha_innobase::create(
row_type = form->s->row_type;
if (flags) {
/* KEY_BLOCK_SIZE was specified. */
if (!(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
/* ROW_FORMAT was not specified;
default to ROW_FORMAT=COMPRESSED */
/* if KEY_BLOCK_SIZE was specified on this statement and
ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/
if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
&& !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
row_type = ROW_TYPE_COMPRESSED;
} else if (row_type != ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT other than COMPRESSED
......@@ -7028,7 +7028,7 @@ ha_innobase::create(
flags = 0;
}
} else {
/* No KEY_BLOCK_SIZE */
/* flags == 0 means no KEY_BLOCK_SIZE.*/
if (row_type == ROW_TYPE_COMPRESSED) {
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
......@@ -7923,9 +7923,12 @@ Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
UNIV_INTERN
int
ha_innobase::info(
/*==============*/
uint flag) /*!< in: what information MySQL requests */
ha_innobase::info_low(
/*==================*/
uint flag, /*!< in: what information MySQL
requests */
bool called_from_analyze) /* in: TRUE if called from
::analyze() */
{
dict_table_t* ib_table;
dict_index_t* index;
......@@ -7956,8 +7959,7 @@ ha_innobase::info(
ib_table = prebuilt->table;
if (flag & HA_STATUS_TIME) {
if ((innobase_stats_on_metadata
|| thd_sql_command(user_thd) == SQLCOM_ANALYZE)
if ((called_from_analyze || innobase_stats_on_metadata)
&& !share->ib_table->is_corrupt) {
/* In sql_show we call with this flag: update
then statistics so that they are up-to-date */
......@@ -8228,6 +8230,18 @@ func_exit:
DBUG_RETURN(0);
}
/*********************************************************************//**
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
UNIV_INTERN
int
ha_innobase::info(
/*==============*/
uint flag) /*!< in: what information MySQL requests */
{
return(info_low(flag, false /* not called from analyze */));
}
/**********************************************************************//**
Updates index cardinalities of the table, based on 8 random dives into
each index tree. This does NOT calculate exact statistics on the table.
......@@ -8244,7 +8258,8 @@ ha_innobase::analyze(
}
/* Simply call ::info() with all the flags */
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
true /* called from analyze */);
if (share->ib_table->is_corrupt) {
return(HA_ADMIN_CORRUPT);
......@@ -8553,8 +8568,6 @@ ha_innobase::get_foreign_key_create_info(void)
flen = ftell(srv_dict_tmpfile);
if (flen < 0) {
flen = 0;
} else if (flen > 64000 - 1) {
flen = 64000 - 1;
}
/* allocate buffer for the string, and
......@@ -9867,7 +9880,11 @@ ha_innobase::innobase_peek_autoinc(void)
auto_inc = dict_table_autoinc_read(innodb_table);
ut_a(auto_inc > 0);
if (auto_inc == 0) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: AUTOINC next value generation "
"is disabled for '%s'\n", innodb_table->name);
}
dict_table_autoinc_unlock(innodb_table);
......@@ -11508,6 +11525,13 @@ static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering,
innodb_change_buffering_validate,
innodb_change_buffering_update, "inserts");
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
PLUGIN_VAR_RQCMDARG,
"Debug flags for InnoDB change buffering (0=none)",
NULL, NULL, 0, 0, 1, 0);
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
PLUGIN_VAR_RQCMDARG,
"Number of pages that must be accessed sequentially for InnoDB to "
......@@ -11717,6 +11741,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(dict_size_limit),
MYSQL_SYSVAR(use_sys_malloc),
MYSQL_SYSVAR(change_buffering),
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
MYSQL_SYSVAR(change_buffering_debug),
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
MYSQL_SYSVAR(read_ahead_threshold),
MYSQL_SYSVAR(io_capacity),
MYSQL_SYSVAR(auto_lru_dump),
......
......@@ -110,6 +110,7 @@ class ha_innobase: public handler
ulint innobase_update_autoinc(ulonglong auto_inc);
void innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr);
int info_low(uint flag, bool called_from_analyze);
/* Init values for the class: */
public:
......
......@@ -49,6 +49,7 @@ Created 7/19/1997 Heikki Tuuri
#include "btr0cur.h"
#include "btr0pcur.h"
#include "btr0btr.h"
#include "row0upd.h"
#include "sync0sync.h"
#include "dict0boot.h"
#include "fut0lst.h"
......@@ -170,6 +171,11 @@ access order rules. */
/** Operations that can currently be buffered. */
UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_INSERT;
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/** Flag to control insert buffer debugging. */
UNIV_INTERN uint ibuf_debug;
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/** The insert buffer control structure */
UNIV_INTERN ibuf_t* ibuf = NULL;
......@@ -2886,9 +2892,80 @@ During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
static
void
ibuf_insert_to_index_page_low(
/*==========================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */
buf_block_t* block, /*!< in/out: index page where the buffered
entry should be placed */
dict_index_t* index, /*!< in: record descriptor */
mtr_t* mtr, /*!< in/out: mtr */
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */
{
const page_t* page;
ulint space;
ulint page_no;
ulint zip_size;
const page_t* bitmap_page;
ulint old_bits;
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
return;
}
/* If the record did not fit, reorganize */
btr_page_reorganize(block, index, mtr);
page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur);
/* This time the record must fit */
if (UNIV_LIKELY
(page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) {
return;
}
page = buf_block_get_frame(block);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: Insert buffer insert fails;"
" page free %lu, dtuple size %lu\n",
(ulong) page_get_max_insert_size(page, 1),
(ulong) rec_get_converted_size(index, entry, 0));
fputs("InnoDB: Cannot insert index record ", stderr);
dtuple_print(stderr, entry);
fputs("\nInnoDB: The table where this index record belongs\n"
"InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
"InnoDB: that table.\n", stderr);
space = page_get_space_id(page);
zip_size = buf_block_get_zip_size(block);
page_no = page_get_page_no(page);
bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
IBUF_BITMAP_FREE, mtr);
fprintf(stderr,
"InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n",
(ulong) space, (ulong) page_no,
(ulong) zip_size, (ulong) old_bits);
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
}
/************************************************************************
During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
static
void
ibuf_insert_to_index_page(
/*======================*/
dtuple_t* entry, /*!< in: buffered entry to insert */
const dtuple_t* entry, /*!< in: buffered entry to insert */
buf_block_t* block, /*!< in/out: index page where the buffered entry
should be placed */
dict_index_t* index, /*!< in: record descriptor */
......@@ -2898,11 +2975,10 @@ ibuf_insert_to_index_page(
ulint low_match;
page_t* page = buf_block_get_frame(block);
rec_t* rec;
page_t* bitmap_page;
ulint old_bits;
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
ut_ad(!buf_block_align(page)->is_hashed);
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
......@@ -2940,71 +3016,86 @@ dump:
low_match = page_cur_search(block, index, entry,
PAGE_CUR_LE, &page_cur);
if (low_match == dtuple_get_n_fields(entry)) {
if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) {
mem_heap_t* heap;
upd_t* update;
ulint* offsets;
page_zip_des_t* page_zip;
rec = page_cur_get_rec(&page_cur);
page_zip = buf_block_get_page_zip(block);
btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr);
} else {
rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
/* This is based on
row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */
ut_ad(rec_get_deleted_flag(rec, page_is_comp(page)));
if (UNIV_LIKELY(rec != NULL)) {
heap = mem_heap_create(1024);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED,
&heap);
update = row_upd_build_sec_rec_difference_binary(
index, entry, rec, NULL, heap);
page_zip = buf_block_get_page_zip(block);
if (update->n_fields == 0) {
/* The records only differ in the delete-mark.
Clear the delete-mark, like we did before
Bug #56680 was fixed. */
btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr);
updated_in_place:
mem_heap_free(heap);
return;
}
/* If the record did not fit, reorganize */
btr_page_reorganize(block, index, mtr);
page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
/* Copy the info bits. Clear the delete-mark. */
update->info_bits = rec_get_info_bits(rec, page_is_comp(page));
update->info_bits &= ~REC_INFO_DELETED_FLAG;
/* We cannot invoke btr_cur_optimistic_update() here,
because we do not have a btr_cur_t or que_thr_t,
as the insert buffer merge occurs at a very low level. */
if (!row_upd_changes_field_size_or_external(index, offsets,
update)
&& (!page_zip || btr_cur_update_alloc_zip(
page_zip, block, index,
rec_offs_size(offsets), FALSE, mtr))) {
/* This is the easy case. Do something similar
to btr_cur_update_in_place(). */
row_upd_rec_in_place(rec, index, offsets,
update, page_zip);
goto updated_in_place;
}
/* This time the record must fit */
if (UNIV_UNLIKELY
(!page_cur_tuple_insert(&page_cur, entry, index,
0, mtr))) {
ulint space;
ulint page_no;
ulint zip_size;
/* A collation may identify values that differ in
storage length.
Some examples (1 or 2 bytes):
utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I
utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S
utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS
ut_print_timestamp(stderr);
latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S
fprintf(stderr,
" InnoDB: Error: Insert buffer insert"
" fails; page free %lu,"
" dtuple size %lu\n",
(ulong) page_get_max_insert_size(
page, 1),
(ulong) rec_get_converted_size(
index, entry, 0));
fputs("InnoDB: Cannot insert index record ",
stderr);
dtuple_print(stderr, entry);
fputs("\nInnoDB: The table where"
" this index record belongs\n"
"InnoDB: is now probably corrupt."
" Please run CHECK TABLE on\n"
"InnoDB: that table.\n", stderr);
Examples of a character (3-byte UTF-8 sequence)
identified with 2 or 4 characters (1-byte UTF-8 sequences):
space = page_get_space_id(page);
zip_size = buf_block_get_zip_size(block);
page_no = page_get_page_no(page);
utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO
utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN
*/
bitmap_page = ibuf_bitmap_get_map_page(
space, page_no, zip_size, mtr);
old_bits = ibuf_bitmap_page_get_bits(
bitmap_page, page_no, zip_size,
IBUF_BITMAP_FREE, mtr);
/* Delete the different-length record, and insert the
buffered one. */
fprintf(stderr,
"InnoDB: space %lu, page %lu,"
" zip_size %lu, bitmap bits %lu\n",
(ulong) space, (ulong) page_no,
(ulong) zip_size, (ulong) old_bits);
lock_rec_store_on_page_infimum(block, rec);
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_move_to_prev(&page_cur);
mem_heap_free(heap);
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
}
ibuf_insert_to_index_page_low(entry, block, index, mtr,
&page_cur);
lock_rec_restore_from_page_infimum(block, rec, block);
} else {
ibuf_insert_to_index_page_low(entry, block, index, mtr,
&page_cur);
}
}
......
......@@ -242,6 +242,22 @@ btr_cur_pessimistic_insert(
que_thr_t* thr, /*!< in: query thread or NULL */
mtr_t* mtr); /*!< in: mtr */
/*************************************************************//**
See if there is enough place in the page modification log to log
an update-in-place.
@return TRUE if enough place */
UNIV_INTERN
ibool
btr_cur_update_alloc_zip(
/*=====================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
buf_block_t* block, /*!< in/out: buffer page */
dict_index_t* index, /*!< in: the index corresponding to the block */
ulint length, /*!< in: size needed */
ibool create, /*!< in: TRUE=delete-and-insert,
FALSE=update-in-place */
mtr_t* mtr) /*!< in: mini-transaction */
__attribute__((nonnull, warn_unused_result));
/*************************************************************//**
Updates a record when the update causes no size changes in its fields.
@return DB_SUCCESS or error number */
UNIV_INTERN
......
......@@ -76,6 +76,20 @@ buf_flush_init_for_writing(
ib_uint64_t newest_lsn); /*!< in: newest modification lsn
to the page */
#ifndef UNIV_HOTBACKUP
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
Writes a flushable page asynchronously from the buffer pool to a file.
NOTE: buf_pool_mutex and block->mutex must be held upon entering this
function, and they will be released by this function after flushing.
This is loosely based on buf_flush_batch() and buf_flush_page().
@return TRUE if the page was flushed and the mutexes released */
UNIV_INTERN
ibool
buf_flush_page_try(
/*===============*/
buf_block_t* block) /*!< in/out: buffer control block */
__attribute__((nonnull, warn_unused_result));
# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/*******************************************************************//**
This utility flushes dirty blocks from the end of the LRU list or flush_list.
NOTE 1: in the case of an LRU flush the calling thread may own latches to
......
......@@ -48,6 +48,11 @@ typedef enum {
/** Operations that can currently be buffered. */
extern ibuf_use_t ibuf_use;
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/** Flag to control insert buffer debugging. */
extern uint ibuf_debug;
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/** The insert buffer control structure */
extern ibuf_t* ibuf;
......
......@@ -535,6 +535,10 @@ struct mysql_row_templ_struct {
Innobase record in the current index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
ulint clust_rec_field_no; /*!< field number of the column in an
Innobase record in the clustered index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
ulint mysql_col_offset; /*!< offset of the column in the MySQL
row format */
ulint mysql_col_len; /*!< length of the column in the MySQL
......
......@@ -167,8 +167,11 @@ row_upd_changes_field_size_or_external(
const upd_t* update);/*!< in: update vector */
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Replaces the new column values stored in the update vector to the record
given. No field size changes are allowed. */
Replaces the new column values stored in the update vector to the
record given. No field size changes are allowed. This function is
usually invoked on a clustered index. The only use case for a
secondary index is row_ins_sec_index_entry_by_modify() or its
counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
......
......@@ -1222,10 +1222,12 @@ UNIV_INTERN
void
os_file_set_nocache(
/*================*/
int fd, /*!< in: file descriptor to alter */
const char* file_name, /*!< in: file name, used in the
diagnostic message */
const char* operation_name) /*!< in: "open" or "create"; used in the
int fd /*!< in: file descriptor to alter */
__attribute__((unused)),
const char* file_name /*!< in: used in the diagnostic message */
__attribute__((unused)),
const char* operation_name __attribute__((unused)))
/*!< in: "open" or "create"; used in the
diagnostic message */
{
/* some versions of Solaris may not have DIRECTIO_ON */
......@@ -2355,7 +2357,10 @@ _os_file_read(
ulint i;
#endif /* !UNIV_HOTBACKUP */
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
no more than 32 bits. */
ut_a((offset & 0xFFFFFFFFUL) == offset);
ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_reads++;
os_bytes_read_since_printout += n;
......@@ -2479,7 +2484,10 @@ os_file_read_no_error_handling(
ulint i;
#endif /* !UNIV_HOTBACKUP */
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
no more than 32 bits. */
ut_a((offset & 0xFFFFFFFFUL) == offset);
ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_reads++;
os_bytes_read_since_printout += n;
......@@ -2609,7 +2617,10 @@ os_file_write(
ulint i;
#endif /* !UNIV_HOTBACKUP */
ut_a((offset & 0xFFFFFFFF) == offset);
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
no more than 32 bits. */
ut_a((offset & 0xFFFFFFFFUL) == offset);
ut_a((n & 0xFFFFFFFFUL) == n);
os_n_file_writes++;
......@@ -3379,16 +3390,17 @@ os_aio_array_reserve_slot(
offset */
ulint offset_high, /*!< in: most significant 32 bits of
offset */
ulint len, /*!< in: length of the block to read or write */
trx_t* trx)
ulint len) /*!< in: length of the block to read or write */
{
os_aio_slot_t* slot;
#ifdef WIN_ASYNC_IO
OVERLAPPED* control;
#endif
ulint i;
ulint slots_per_seg;
ulint local_seg;
#ifdef WIN_ASYNC_IO
OVERLAPPED* control;
ut_a((len & 0xFFFFFFFFUL) == len);
#endif
/* No need of a mutex. Only reading constant fields */
slots_per_seg = array->n_slots / array->n_segments;
......@@ -3690,6 +3702,9 @@ os_aio(
ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(os_aio_validate());
#ifdef WIN_ASYNC_IO
ut_ad((n & 0xFFFFFFFFUL) == n);
#endif
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
......@@ -3747,7 +3762,7 @@ try_again:
trx->io_read += n;
}
slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
name, buf, offset, offset_high, n, trx);
name, buf, offset, offset_high, n);
if (type == OS_FILE_READ) {
if (os_aio_use_native_aio) {
#ifdef WIN_ASYNC_IO
......@@ -3935,16 +3950,18 @@ os_aio_windows_handle(
/* retry failed read/write operation synchronously.
No need to hold array->mutex. */
ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
switch (slot->type) {
case OS_FILE_WRITE:
ret = WriteFile(slot->file, slot->buf,
slot->len, &len,
(DWORD) slot->len, &len,
&(slot->control));
break;
case OS_FILE_READ:
ret = ReadFile(slot->file, slot->buf,
slot->len, &len,
(DWORD) slot->len, &len,
&(slot->control));
break;
......
......@@ -141,10 +141,11 @@ MYSQL_PLUGIN_ACTIONS(xtradb, [
AC_MSG_CHECKING(whether Solaris libc atomic functions are available)
# either define HAVE_IB_SOLARIS_ATOMICS or not
AC_CHECK_FUNCS(atomic_add_long \
AC_CHECK_FUNCS(atomic_cas_ulong \
atomic_cas_32 \
atomic_cas_64 \
atomic_cas_ulong,
atomic_add_long_nv \
atomic_swap_uchar,
AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1],
[Define to 1 if Solaris libc atomic functions \
......
......@@ -445,7 +445,7 @@ row_mysql_convert_row_to_innobase(
row is used, as row may contain
pointers to this record! */
{
mysql_row_templ_t* templ;
const mysql_row_templ_t*templ;
dfield_t* dfield;
ulint i;
......@@ -1890,15 +1890,13 @@ err_exit:
err = trx->error_state;
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
switch (err) {
case DB_SUCCESS:
break;
case DB_OUT_OF_FILE_SPACE:
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
/* TO DO: free table? The code below will dereference
table->name, though. */
}
switch (err) {
case DB_OUT_OF_FILE_SPACE:
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: cannot create table ",
stderr);
......@@ -1913,9 +1911,13 @@ err_exit:
break;
case DB_DUPLICATE_KEY:
default:
/* We may also get err == DB_ERROR if the .ibd file for the
table already exists */
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, NULL);
dict_mem_table_free(table);
break;
}
......@@ -2830,15 +2832,6 @@ row_truncate_table_for_mysql(
trx->table_id = table->id;
/* Lock all index trees for this table, as we will
truncate the table/index and possibly change their metadata.
All DML/DDL are blocked by table level lock, with
a few exceptions such as queries into information schema
about the table, MySQL could try to access index stats
for this kind of query, we need to use index locks to
sync up */
dict_table_x_lock_indexes(table);
if (table->space && !table->dir_path_of_temp_table) {
/* Discard and create the single-table tablespace. */
ulint space = table->space;
......@@ -2851,6 +2844,11 @@ row_truncate_table_for_mysql(
dict_hdr_get_new_id(NULL, NULL, &space);
/* Lock all index trees for this table. We must
do so after dict_hdr_get_new_id() to preserve
the latch order */
dict_table_x_lock_indexes(table);
if (space == ULINT_UNDEFINED
|| fil_create_new_single_table_tablespace(
space, table->name, FALSE, flags,
......@@ -2884,6 +2882,15 @@ row_truncate_table_for_mysql(
FIL_IBD_FILE_INITIAL_SIZE, &mtr);
mtr_commit(&mtr);
}
} else {
/* Lock all index trees for this table, as we will
truncate the table/index and possibly change their metadata.
All DML/DDL are blocked by table level lock, with
a few exceptions such as queries into information schema
about the table, MySQL could try to access index stats
for this kind of query, we need to use index locks to
sync up */
dict_table_x_lock_indexes(table);
}
/* scan SYS_INDEXES for all indexes of the table */
......
......@@ -2675,39 +2675,39 @@ row_sel_store_mysql_rec(
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
const rec_t* rec, /*!< in: Innobase record in the index
which was described in prebuilt's
template; must be protected by
a page latch */
template, or in the clustered index;
must be protected by a page latch */
ibool rec_clust, /*!< in: TRUE if rec is in the
clustered index instead of
prebuilt->index */
const ulint* offsets) /*!< in: array returned by
rec_get_offsets() */
rec_get_offsets(rec) */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
mem_heap_t* heap;
const byte* data;
ulint len;
ulint i;
mem_heap_t* extern_field_heap = NULL;
mem_heap_t* heap;
ulint i;
ut_ad(prebuilt->mysql_template);
ut_ad(prebuilt->default_rec);
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
mem_heap_free(prebuilt->blob_heap);
prebuilt->blob_heap = NULL;
}
/* init null bytes with default values as they might be
left uninitialized in some cases and these uninited bytes
might be copied into mysql record buffer that leads to
valgrind warnings */
memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len);
for (i = 0; i < prebuilt->n_template; i++) {
templ = prebuilt->mysql_template + i;
const mysql_row_templ_t*templ = prebuilt->mysql_template + i;
const byte* data;
ulint len;
ulint field_no;
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
templ->rec_field_no))) {
field_no = rec_clust
? templ->clust_rec_field_no : templ->rec_field_no;
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) {
/* Copy an externally stored field to the temporary
heap */
......@@ -2735,7 +2735,7 @@ row_sel_store_mysql_rec(
data = btr_rec_copy_externally_stored_field(
rec, offsets,
dict_table_zip_size(prebuilt->table),
templ->rec_field_no, &len, heap);
field_no, &len, heap);
if (UNIV_UNLIKELY(!data)) {
/* The externally stored field
......@@ -2756,8 +2756,7 @@ row_sel_store_mysql_rec(
} else {
/* Field is stored in the row. */
data = rec_get_nth_field(rec, offsets,
templ->rec_field_no, &len);
data = rec_get_nth_field(rec, offsets, field_no, &len);
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
&& len != UNIV_SQL_NULL) {
......@@ -3119,7 +3118,7 @@ row_sel_pop_cached_row_for_mysql(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */
{
ulint i;
mysql_row_templ_t* templ;
const mysql_row_templ_t*templ;
byte* cached_rec;
ut_ad(prebuilt->n_fetch_cached > 0);
ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
......@@ -3176,15 +3175,21 @@ ibool
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
const rec_t* rec, /*!< in: record to push; must
be protected by a page latch */
const ulint* offsets) /*!< in: rec_get_offsets() */
const rec_t* rec, /*!< in: record to push, in the index
which was described in prebuilt's
template, or in the clustered index;
must be protected by a page latch */
ibool rec_clust, /*!< in: TRUE if rec is in the
clustered index instead of
prebuilt->index */
const ulint* offsets) /*!< in: rec_get_offsets(rec) */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
......@@ -3213,7 +3218,7 @@ row_sel_push_cache_row_for_mysql(
if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
prebuilt->fetch_cache[
prebuilt->n_fetch_cached],
prebuilt, rec, offsets))) {
prebuilt, rec, rec_clust, offsets))) {
return(FALSE);
}
......@@ -3400,6 +3405,12 @@ row_search_for_mysql(
ut_error;
}
/* init null bytes with default values as they might be
left uninitialized in some cases and these uninited bytes
might be copied into mysql record buffer that leads to
valgrind warnings */
memcpy(buf, prebuilt->default_rec, prebuilt->null_bitmap_len);
#if 0
/* August 19, 2005 by Heikki: temporarily disable this error
print until the cursor lock count is done correctly.
......@@ -3615,7 +3626,8 @@ row_search_for_mysql(
ut_ad(!rec_get_deleted_flag(rec, comp));
if (!row_sel_store_mysql_rec(buf, prebuilt,
rec, offsets)) {
rec, FALSE,
offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
......@@ -4273,7 +4285,6 @@ no_gap_lock:
is necessary, because we can only get the undo
information via the clustered index record. */
ut_ad(index != clust_index);
ut_ad(!dict_index_is_clust(index));
if (!lock_sec_rec_cons_read_sees(
......@@ -4389,26 +4400,10 @@ requires_clust_rec:
goto next_rec;
}
if (prebuilt->need_to_access_clustered) {
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index,
offsets));
} else {
/* We used 'offsets' for the clust rec, recalculate
them for 'rec' */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
result_rec = rec;
}
/* result_rec can legitimately be delete-marked
now that it has been established that it points to a
clustered index record that exists in the read view. */
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
} else {
result_rec = rec;
ut_ad(!rec_get_deleted_flag(rec, comp));
}
/* We found a qualifying record 'result_rec'. At this point,
......@@ -4417,6 +4412,7 @@ requires_clust_rec:
ut_ad(rec_offs_validate(result_rec,
result_rec != rec ? clust_index : index,
offsets));
ut_ad(!rec_get_deleted_flag(result_rec, comp));
/* At this point, the clustered index record is protected
by a page latch that was acquired when pcur was positioned.
......@@ -4441,6 +4437,7 @@ requires_clust_rec:
cursor. */
if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
result_rec != rec,
offsets)) {
/* Only fresh inserts may contain incomplete
externally stored columns. Pretend that such
......@@ -4458,15 +4455,31 @@ requires_clust_rec:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
if (UNIV_UNLIKELY
(prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) {
/* CHECK TABLE: fetch the row */
if (result_rec != rec
&& !prebuilt->need_to_access_clustered) {
/* We used 'offsets' for the clust
rec, recalculate them for 'rec' */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED,
&heap);
result_rec = rec;
}
memcpy(buf + 4, result_rec
- rec_offs_extra_size(offsets),
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
} else {
if (!row_sel_store_mysql_rec(buf, prebuilt,
result_rec, offsets)) {
/* Returning a row to MySQL */
if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec,
result_rec != rec,
offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such records do
......
......@@ -466,8 +466,11 @@ row_upd_changes_field_size_or_external(
#endif /* !UNIV_HOTBACKUP */
/***********************************************************//**
Replaces the new column values stored in the update vector to the record
given. No field size changes are allowed. */
Replaces the new column values stored in the update vector to the
record given. No field size changes are allowed. This function is
usually invoked on a clustered index. The only use case for a
secondary index is row_ins_sec_index_entry_by_modify() or its
counterpart in ibuf_insert_to_index_page(). */
UNIV_INTERN
void
row_upd_rec_in_place(
......
......@@ -463,7 +463,6 @@ io_handler_thread(
the aio array */
{
ulint segment;
ulint i;
segment = *((ulint*)arg);
......@@ -471,7 +470,7 @@ io_handler_thread(
fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment,
os_thread_pf(os_thread_get_curr_id()));
#endif
for (i = 0;; i++) {
while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
fil_aio_wait(segment);
mutex_enter(&ios_mutex);
......@@ -479,8 +478,6 @@ io_handler_thread(
mutex_exit(&ios_mutex);
}
thr_local_free(os_thread_get_curr_id());
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit.
The thread actually never comes here because it is exited in an
......@@ -2091,7 +2088,7 @@ innobase_shutdown_for_mysql(void)
#ifdef __NETWARE__
if (!panic_shutdown)
#endif
logs_empty_and_mark_files_at_shutdown();
logs_empty_and_mark_files_at_shutdown();
if (srv_conc_n_threads != 0) {
fprintf(stderr,
......
......@@ -248,10 +248,8 @@ rw_lock_create_func(
lock->mutex.cmutex_name = cmutex_name;
ut_d(lock->mutex.mutex_type = 1);
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
# ifdef UNIV_DEBUG
UT_NOT_USED(cfile_name);
UT_NOT_USED(cline);
# endif
(void) cfile_name;
(void) cline;
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
lock->lock_word = X_LOCK_DECR;
......
......@@ -266,6 +266,9 @@ mutex_create_func(
#ifdef UNIV_DEBUG
mutex->cfile_name = cfile_name;
mutex->cline = cline;
#else
(void) cfile_name;
(void) cline;
#endif /* UNIV_DEBUG */
mutex->count_os_wait = 0;
mutex->cmutex_name= cmutex_name;
......
......@@ -1861,21 +1861,11 @@ trx_undo_set_state_at_finish(
if (undo->size == 1
&& mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
< TRX_UNDO_PAGE_REUSE_LIMIT) {
< TRX_UNDO_PAGE_REUSE_LIMIT
&& UT_LIST_GET_LEN(rseg->update_undo_list) < 500
&& UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
/* This is a heuristic to avoid the problem of all UNDO
slots ending up in one of the UNDO lists. Previously if
the server crashed with all the slots in one of the lists,
transactions that required the slots of a different type
would fail for lack of slots. */
if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
&& UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
state = TRX_UNDO_CACHED;
} else {
state = TRX_UNDO_TO_FREE;
}
state = TRX_UNDO_CACHED;
} else if (undo->type == TRX_UNDO_INSERT) {
......
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