Commit de90b6dc authored by Vasil Dimov's avatar Vasil Dimov

Merge mysql-5.1-innodb -> mysql-5.1

parents 94097ecd b7cc4aa0
...@@ -744,3 +744,50 @@ ...@@ -744,3 +744,50 @@
Memcheck:Addr1 Memcheck:Addr1
fun:buf_buddy_relocate fun:buf_buddy_relocate
} }
{
Bug 59874 Valgrind warning in InnoDB compression code
Memcheck:Cond
fun:*
fun:*
fun:deflate
fun:btr_store_big_rec_extern_fields_func
fun:row_ins_index_entry_low
fun:row_ins_index_entry
fun:row_ins_index_entry_step
fun:row_ins
fun:row_ins_step
fun:row_insert_for_mysql
}
{
In page0zip.c we have already checked that the memory is initialized before calling deflate()
Memcheck:Cond
fun:*
fun:*
fun:deflate
fun:page_zip_compress
fun:page_cur_insert_rec_zip_reorg
fun:page_cur_insert_rec_zip
fun:page_cur_tuple_insert
fun:btr_cur_optimistic_insert
fun:row_ins_index_entry_low
fun:row_ins_index_entry
fun:row_ins_index_entry_step
fun:row_ins
fun:row_ins_step
fun:row_insert_for_mysql
}
{
Bug 59875 Valgrind warning in buf0buddy.c
Memcheck:Addr1
fun:mach_read_from_4
fun:buf_buddy_relocate
fun:buf_buddy_free_low
fun:buf_buddy_free
fun:buf_LRU_block_remove_hashed_page
fun:buf_LRU_invalidate_tablespace
fun:fil_delete_tablespace
fun:row_drop_table_for_mysql
}
2011-01-31 The InnoDB Team
* btr/btr0cur.c, include/row0upd.h,
row/row0purge.c, row/row0umod.c, row/row0upd.c:
Bug#59230 assert 0 row_upd_changes_ord_field_binary()
in post-crash rollback or purge
2011-01-27 The InnoDB Team 2011-01-27 The InnoDB Team
* btr/btr0cur.c: * btr/btr0cur.c:
......
...@@ -186,7 +186,7 @@ static ...@@ -186,7 +186,7 @@ static
ulint ulint
btr_rec_get_externally_stored_len( btr_rec_get_externally_stored_len(
/*==============================*/ /*==============================*/
rec_t* rec, /*!< in: record */ const rec_t* rec, /*!< in: record */
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -1768,8 +1768,8 @@ btr_cur_update_in_place( ...@@ -1768,8 +1768,8 @@ btr_cur_update_in_place(
NOT call it if index is secondary */ NOT call it if index is secondary */
if (!dict_index_is_clust(index) if (!dict_index_is_clust(index)
|| row_upd_changes_ord_field_binary(NULL, NULL, || row_upd_changes_ord_field_binary(index, update, thr,
index, update)) { NULL, NULL)) {
/* Remove possible hash index pointer to this record */ /* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor); btr_search_update_hash_on_delete(cursor);
...@@ -3483,6 +3483,35 @@ btr_estimate_number_of_different_key_vals( ...@@ -3483,6 +3483,35 @@ btr_estimate_number_of_different_key_vals(
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
/***********************************************************//**
Gets the offset of the pointer to the externally stored part of a field.
@return offset of the pointer to the externally stored part */
static
ulint
btr_rec_get_field_ref_offs(
/*=======================*/
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
ulint n) /*!< in: index of the external field */
{
ulint field_ref_offs;
ulint local_len;
ut_a(rec_offs_nth_extern(offsets, n));
field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len);
ut_a(local_len != UNIV_SQL_NULL);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE);
}
/** Gets a pointer to the externally stored part of a field.
@param rec record
@param offsets rec_get_offsets(rec)
@param n index of the externally stored field
@return pointer to the externally stored part */
#define btr_rec_get_field_ref(rec, offsets, n) \
((rec) + btr_rec_get_field_ref_offs(offsets, n))
/***********************************************************//** /***********************************************************//**
Gets the externally stored size of a record, in units of a database page. Gets the externally stored size of a record, in units of a database page.
@return externally stored part, in units of a database page */ @return externally stored part, in units of a database page */
...@@ -3490,28 +3519,27 @@ static ...@@ -3490,28 +3519,27 @@ static
ulint ulint
btr_rec_get_externally_stored_len( btr_rec_get_externally_stored_len(
/*==============================*/ /*==============================*/
rec_t* rec, /*!< in: record */ const rec_t* rec, /*!< in: record */
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
{ {
ulint n_fields; ulint n_fields;
byte* data;
ulint local_len;
ulint extern_len;
ulint total_extern_len = 0; ulint total_extern_len = 0;
ulint i; ulint i;
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec)); ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
if (!rec_offs_any_extern(offsets)) {
return(0);
}
n_fields = rec_offs_n_fields(offsets); n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) { if (rec_offs_nth_extern(offsets, i)) {
data = rec_get_nth_field(rec, offsets, i, &local_len); ulint extern_len = mach_read_from_4(
btr_rec_get_field_ref(rec, offsets, i)
local_len -= BTR_EXTERN_FIELD_REF_SIZE; + BTR_EXTERN_LEN + 4);
extern_len = mach_read_from_4(data + local_len
+ BTR_EXTERN_LEN + 4);
total_extern_len += ut_calc_align(extern_len, total_extern_len += ut_calc_align(extern_len,
UNIV_PAGE_SIZE); UNIV_PAGE_SIZE);
...@@ -3541,7 +3569,7 @@ btr_cur_set_ownership_of_extern_field( ...@@ -3541,7 +3569,7 @@ btr_cur_set_ownership_of_extern_field(
ulint byte_val; ulint byte_val;
data = rec_get_nth_field(rec, offsets, i, &local_len); data = rec_get_nth_field(rec, offsets, i, &local_len);
ut_ad(rec_offs_nth_extern(offsets, i));
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE); ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE; local_len -= BTR_EXTERN_FIELD_REF_SIZE;
...@@ -3551,6 +3579,9 @@ btr_cur_set_ownership_of_extern_field( ...@@ -3551,6 +3579,9 @@ btr_cur_set_ownership_of_extern_field(
if (val) { if (val) {
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG); byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
} else { } else {
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
} }
...@@ -3788,8 +3819,8 @@ file segment of the index tree. ...@@ -3788,8 +3819,8 @@ file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN UNIV_INTERN
ulint ulint
btr_store_big_rec_extern_fields( btr_store_big_rec_extern_fields_func(
/*============================*/ /*=================================*/
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 */
buf_block_t* rec_block, /*!< in/out: block containing rec */ buf_block_t* rec_block, /*!< in/out: block containing rec */
...@@ -3798,11 +3829,17 @@ btr_store_big_rec_extern_fields( ...@@ -3798,11 +3829,17 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets the "external storage" flags in offsets
will not correspond to rec when will not correspond to rec when
this function returns */ this function returns */
big_rec_t* big_rec_vec, /*!< in: vector containing fields #ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */
#endif /* UNIV_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
const 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
containing the latch to rec and to the
tree */
{ {
ulint rec_page_no; ulint rec_page_no;
byte* field_ref; byte* field_ref;
...@@ -3820,6 +3857,7 @@ btr_store_big_rec_extern_fields( ...@@ -3820,6 +3857,7 @@ btr_store_big_rec_extern_fields(
z_stream c_stream; z_stream c_stream;
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
...@@ -3851,21 +3889,37 @@ btr_store_big_rec_extern_fields( ...@@ -3851,21 +3889,37 @@ btr_store_big_rec_extern_fields(
ut_a(err == Z_OK); ut_a(err == Z_OK);
} }
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/* All pointers to externally stored columns in the record
must either be zero or they must be pointers to inherited
columns, owned by this record or an earlier record version. */
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
if (!rec_offs_nth_extern(offsets, i)) {
continue;
}
field_ref = btr_rec_get_field_ref(rec, offsets, i);
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
/* Either this must be an update in place,
or the BLOB must be inherited, or the BLOB pointer
must be zero (will be written in this function). */
ut_a(update_in_place
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|| !memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE));
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
/* We have to create a file segment to the tablespace /* We have to create a file segment to the tablespace
for each field and put the pointer to the field in rec */ for each field and put the pointer to the field in rec */
for (i = 0; i < big_rec_vec->n_fields; i++) { for (i = 0; i < big_rec_vec->n_fields; i++) {
ut_ad(rec_offs_nth_extern(offsets, field_ref = btr_rec_get_field_ref(
big_rec_vec->fields[i].field_no)); rec, offsets, big_rec_vec->fields[i].field_no);
{ #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ulint local_len; /* A zero BLOB pointer should have been initially inserted. */
field_ref = rec_get_nth_field( ut_a(!memcmp(field_ref, field_ref_zero,
rec, offsets, big_rec_vec->fields[i].field_no, BTR_EXTERN_FIELD_REF_SIZE));
&local_len); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
field_ref += local_len;
}
extern_len = big_rec_vec->fields[i].len; extern_len = big_rec_vec->fields[i].len;
UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data, UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data,
extern_len); extern_len);
...@@ -4147,6 +4201,23 @@ next_zip_page: ...@@ -4147,6 +4201,23 @@ next_zip_page:
mem_heap_free(heap); mem_heap_free(heap);
} }
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
/* All pointers to externally stored columns in the record
must be valid. */
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
if (!rec_offs_nth_extern(offsets, i)) {
continue;
}
field_ref = btr_rec_get_field_ref(rec, offsets, i);
/* The pointer must not be zero. */
ut_a(0 != memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE));
/* The column must not be disowned by this record. */
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -4169,6 +4240,7 @@ btr_check_blob_fil_page_type( ...@@ -4169,6 +4240,7 @@ btr_check_blob_fil_page_type(
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) { if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
ulint flags = fil_space_get_flags(space_id); ulint flags = fil_space_get_flags(space_id);
#ifndef UNIV_DEBUG /* Improve debug test coverage */
if (UNIV_LIKELY if (UNIV_LIKELY
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) { ((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
/* Old versions of InnoDB did not initialize /* Old versions of InnoDB did not initialize
...@@ -4177,6 +4249,7 @@ btr_check_blob_fil_page_type( ...@@ -4177,6 +4249,7 @@ btr_check_blob_fil_page_type(
a BLOB page that is in Antelope format.*/ a BLOB page that is in Antelope format.*/
return; return;
} }
#endif /* !UNIV_DEBUG */
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
...@@ -4226,23 +4299,13 @@ btr_free_externally_stored_field( ...@@ -4226,23 +4299,13 @@ btr_free_externally_stored_field(
ulint page_no; ulint page_no;
ulint next_page_no; ulint next_page_no;
mtr_t mtr; mtr_t mtr;
#ifdef UNIV_DEBUG
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains_page(local_mtr, field_ref, ut_ad(mtr_memo_contains_page(local_mtr, field_ref,
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
ut_ad(!rec || rec_offs_validate(rec, index, offsets)); ut_ad(!rec || rec_offs_validate(rec, index, offsets));
ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i));
if (rec) {
ulint local_len;
const byte* f = rec_get_nth_field(rec, offsets,
i, &local_len);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
f += local_len;
ut_ad(f == field_ref);
}
#endif /* UNIV_DEBUG */
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero, if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) { BTR_EXTERN_FIELD_REF_SIZE))) {
...@@ -4407,13 +4470,8 @@ btr_rec_free_externally_stored_fields( ...@@ -4407,13 +4470,8 @@ btr_rec_free_externally_stored_fields(
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
if (rec_offs_nth_extern(offsets, i)) { if (rec_offs_nth_extern(offsets, i)) {
ulint len;
byte* data
= rec_get_nth_field(rec, offsets, i, &len);
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
btr_free_externally_stored_field( btr_free_externally_stored_field(
index, data + len - BTR_EXTERN_FIELD_REF_SIZE, index, btr_rec_get_field_ref(rec, offsets, i),
rec, offsets, page_zip, i, rb_ctx, mtr); rec, offsets, page_zip, i, rb_ctx, mtr);
} }
} }
......
...@@ -657,9 +657,9 @@ buf_block_init( ...@@ -657,9 +657,9 @@ buf_block_init(
block->modify_clock = 0; block->modify_clock = 0;
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE; block->page.file_page_was_freed = FALSE;
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
block->check_index_page_at_flush = FALSE; block->check_index_page_at_flush = FALSE;
block->index = NULL; block->index = NULL;
...@@ -1600,7 +1600,7 @@ buf_page_peek_if_search_hashed( ...@@ -1600,7 +1600,7 @@ buf_page_peek_if_search_hashed(
return(is_hashed); return(is_hashed);
} }
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//** /********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool. Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the This function should be called when we free a file page and want the
...@@ -1621,6 +1621,8 @@ buf_page_set_file_page_was_freed( ...@@ -1621,6 +1621,8 @@ buf_page_set_file_page_was_freed(
bpage = buf_page_hash_get(space, offset); bpage = buf_page_hash_get(space, offset);
if (bpage) { if (bpage) {
/* bpage->file_page_was_freed can already hold
when this code is invoked from dict_drop_index_tree() */
bpage->file_page_was_freed = TRUE; bpage->file_page_was_freed = TRUE;
} }
...@@ -1656,7 +1658,7 @@ buf_page_reset_file_page_was_freed( ...@@ -1656,7 +1658,7 @@ buf_page_reset_file_page_was_freed(
return(bpage); return(bpage);
} }
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//** /********************************************************************//**
Get read access to a compressed page (usually of type Get read access to a compressed page (usually of type
...@@ -1753,7 +1755,7 @@ got_block: ...@@ -1753,7 +1755,7 @@ got_block:
buf_page_set_accessed_make_young(bpage, access_time); buf_page_set_accessed_make_young(bpage, access_time);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!bpage->file_page_was_freed); ut_a(!bpage->file_page_was_freed);
#endif #endif
...@@ -2321,7 +2323,7 @@ wait_until_unfixed: ...@@ -2321,7 +2323,7 @@ wait_until_unfixed:
buf_page_set_accessed_make_young(&block->page, access_time); buf_page_set_accessed_make_young(&block->page, access_time);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(!block->page.file_page_was_freed); ut_a(!block->page.file_page_was_freed);
#endif #endif
...@@ -2479,7 +2481,7 @@ buf_page_optimistic_get( ...@@ -2479,7 +2481,7 @@ buf_page_optimistic_get(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE); ut_a(block->page.file_page_was_freed == FALSE);
#endif #endif
if (UNIV_UNLIKELY(!access_time)) { if (UNIV_UNLIKELY(!access_time)) {
...@@ -2587,7 +2589,7 @@ buf_page_get_known_nowait( ...@@ -2587,7 +2589,7 @@ buf_page_get_known_nowait(
ut_a(block->page.buf_fix_count > 0); ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE); ut_a(block->page.file_page_was_freed == FALSE);
#endif #endif
...@@ -2670,9 +2672,9 @@ buf_page_try_get_func( ...@@ -2670,9 +2672,9 @@ buf_page_try_get_func(
ut_a(block->page.buf_fix_count > 0); ut_a(block->page.buf_fix_count > 0);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(block->page.file_page_was_freed == FALSE); ut_a(block->page.file_page_was_freed == FALSE);
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
buf_pool->stat.n_page_gets++; buf_pool->stat.n_page_gets++;
...@@ -2701,9 +2703,9 @@ buf_page_init_low( ...@@ -2701,9 +2703,9 @@ buf_page_init_low(
bpage->newest_modification = 0; bpage->newest_modification = 0;
bpage->oldest_modification = 0; bpage->oldest_modification = 0;
HASH_INVALIDATE(bpage, hash); HASH_INVALIDATE(bpage, hash);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
bpage->file_page_was_freed = FALSE; bpage->file_page_was_freed = FALSE;
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
} }
/********************************************************************//** /********************************************************************//**
...@@ -3009,9 +3011,9 @@ buf_page_create( ...@@ -3009,9 +3011,9 @@ buf_page_create(
#ifdef UNIV_IBUF_COUNT_DEBUG #ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, offset) == 0); ut_a(ibuf_count_get(space, offset) == 0);
#endif #endif
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
block->page.file_page_was_freed = FALSE; block->page.file_page_was_freed = FALSE;
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/* Page can be found in buf_pool */ /* Page can be found in buf_pool */
buf_pool_mutex_exit(); buf_pool_mutex_exit();
......
...@@ -3444,9 +3444,9 @@ fseg_free_page( ...@@ -3444,9 +3444,9 @@ fseg_free_page(
fseg_free_page_low(seg_inode, space, zip_size, page, mtr); fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(space, page); buf_page_set_file_page_was_freed(space, page);
#endif #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -3513,13 +3513,13 @@ fseg_free_extent( ...@@ -3513,13 +3513,13 @@ fseg_free_extent(
fsp_free_extent(space, zip_size, page, mtr); fsp_free_extent(space, zip_size, page, mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
for (i = 0; i < FSP_EXTENT_SIZE; i++) { for (i = 0; i < FSP_EXTENT_SIZE; i++) {
buf_page_set_file_page_was_freed(space, buf_page_set_file_page_was_freed(space,
first_page_in_extent + i); first_page_in_extent + i);
} }
#endif #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
} }
/**********************************************************************//** /**********************************************************************//**
......
...@@ -1878,9 +1878,9 @@ ibuf_remove_free_page(void) ...@@ -1878,9 +1878,9 @@ ibuf_remove_free_page(void)
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_SPACE_ID, page_no, &mtr); IBUF_SPACE_ID, page_no, &mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no); buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
#endif #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
ibuf_enter(); ibuf_enter();
...@@ -1922,9 +1922,9 @@ ibuf_remove_free_page(void) ...@@ -1922,9 +1922,9 @@ ibuf_remove_free_page(void)
ibuf_bitmap_page_set_bits( ibuf_bitmap_page_set_bits(
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr); bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no); buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
#endif #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
mtr_commit(&mtr); mtr_commit(&mtr);
mutex_exit(&ibuf_mutex); mutex_exit(&ibuf_mutex);
......
...@@ -512,8 +512,8 @@ file segment of the index tree. ...@@ -512,8 +512,8 @@ file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN UNIV_INTERN
ulint ulint
btr_store_big_rec_extern_fields( btr_store_big_rec_extern_fields_func(
/*============================*/ /*=================================*/
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 */
buf_block_t* rec_block, /*!< in/out: block containing rec */ buf_block_t* rec_block, /*!< in/out: block containing rec */
...@@ -522,10 +522,42 @@ btr_store_big_rec_extern_fields( ...@@ -522,10 +522,42 @@ btr_store_big_rec_extern_fields(
the "external storage" flags in offsets the "external storage" flags in offsets
will not correspond to rec when will not correspond to rec when
this function returns */ this function returns */
big_rec_t* big_rec_vec, /*!< in: vector containing fields #ifdef UNIV_DEBUG
mtr_t* local_mtr, /*!< in: mtr containing the
latch to rec and to the tree */
#endif /* UNIV_DEBUG */
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
ibool update_in_place,/*! in: TRUE if the record is updated
in place (not delete+insert) */
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
const 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 __attribute__((nonnull));
rec and to the tree */
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
@param index in: clustered index; MUST be X-latched by mtr
@param b in/out: block containing rec; MUST be X-latched by mtr
@param rec in/out: clustered index record
@param offsets in: rec_get_offsets(rec, index);
the "external storage" flags in offsets will not be adjusted
@param mtr in: mini-transaction that holds x-latch on index and b
@param upd in: TRUE if the record is updated in place (not delete+insert)
@param big in: vector containing fields to be stored externally
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
#ifdef UNIV_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
#elif defined UNIV_BLOB_LIGHT_DEBUG
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
#else
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
#endif
/*******************************************************************//** /*******************************************************************//**
Frees the space in an externally stored field to the file space Frees the space in an externally stored field to the file space
management if the field in data is owned the externally stored field, management if the field in data is owned the externally stored field,
......
...@@ -368,7 +368,7 @@ buf_reset_check_index_page_at_flush( ...@@ -368,7 +368,7 @@ buf_reset_check_index_page_at_flush(
/*================================*/ /*================================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint offset);/*!< in: page number */ ulint offset);/*!< in: page number */
#ifdef UNIV_DEBUG_FILE_ACCESSES #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
/********************************************************************//** /********************************************************************//**
Sets file_page_was_freed TRUE if the page is found in the buffer pool. Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the This function should be called when we free a file page and want the
...@@ -393,7 +393,7 @@ buf_page_reset_file_page_was_freed( ...@@ -393,7 +393,7 @@ buf_page_reset_file_page_was_freed(
/*===============================*/ /*===============================*/
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint offset); /*!< in: page number */ ulint offset); /*!< in: page number */
#endif /* UNIV_DEBUG_FILE_ACCESSES */ #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
/********************************************************************//** /********************************************************************//**
Reads the freed_page_clock of a buffer block. Reads the freed_page_clock of a buffer block.
@return freed_page_clock */ @return freed_page_clock */
...@@ -1135,11 +1135,11 @@ struct buf_page_struct{ ...@@ -1135,11 +1135,11 @@ struct buf_page_struct{
0 if the block was never accessed 0 if the block was never accessed
in the buffer pool */ in the buffer pool */
/* @} */ /* @} */
# ifdef UNIV_DEBUG_FILE_ACCESSES # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ibool file_page_was_freed; ibool file_page_was_freed;
/*!< this is set to TRUE when fsp /*!< this is set to TRUE when fsp
frees a page in buffer pool */ frees a page in buffer pool */
# endif /* UNIV_DEBUG_FILE_ACCESSES */ # endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
}; };
......
...@@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings! ...@@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */ @return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN UNIV_INTERN
ibool ibool
row_upd_changes_ord_field_binary( row_upd_changes_ord_field_binary_func(
/*=============================*/ /*==================================*/
dict_index_t* index, /*!< in: index of the record */
const upd_t* update, /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
#ifdef UNIV_DEBUG
const que_thr_t*thr, /*!< in: query thread */
#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not row and the data values in update are not
known when this function is called, e.g., at known when this function is called, e.g., at
compile time */ compile time */
const row_ext_t*ext, /*!< NULL, or prefixes of the externally const row_ext_t*ext) /*!< NULL, or prefixes of the externally
stored columns in the old row */ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */ __attribute__((nonnull(1,2), warn_unused_result));
const upd_t* update) /*!< in: update vector for the row; NOTE: the #ifdef UNIV_DEBUG
field numbers in this MUST be clustered index # define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
positions! */ row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
__attribute__((nonnull(3,4), warn_unused_result)); #else /* UNIV_DEBUG */
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
row_upd_changes_ord_field_binary_func(index,update,row,ext)
#endif /* UNIV_DEBUG */
/***********************************************************//** /***********************************************************//**
Checks if an update vector changes an ordering field of an index record. Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering This function is fast if the update vector is short or the number of ordering
......
...@@ -177,14 +177,15 @@ command. Not tested on Windows. */ ...@@ -177,14 +177,15 @@ command. Not tested on Windows. */
debugging without UNIV_DEBUG */ debugging without UNIV_DEBUG */
#define UNIV_BUF_DEBUG /* Enable buffer pool #define UNIV_BUF_DEBUG /* Enable buffer pool
debugging without UNIV_DEBUG */ debugging without UNIV_DEBUG */
#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
debugging without UNIV_DEBUG */
#define UNIV_DEBUG /* Enable ut_ad() assertions #define UNIV_DEBUG /* Enable ut_ad() assertions
and disable UNIV_INLINE */ and disable UNIV_INLINE */
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable #define UNIV_DEBUG_LOCK_VALIDATE /* Enable
ut_ad(lock_rec_validate_page()) ut_ad(lock_rec_validate_page())
assertions. */ assertions. */
#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access #define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access
(field file_page_was_freed debugging without UNIV_DEBUG */
in buf_page_t) */
#define UNIV_LRU_DEBUG /* debug the buffer pool LRU */ #define UNIV_LRU_DEBUG /* debug the buffer pool LRU */
#define UNIV_HASH_DEBUG /* debug HASH_ macros */ #define UNIV_HASH_DEBUG /* debug HASH_ macros */
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */ #define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
......
...@@ -2130,7 +2130,7 @@ function_exit: ...@@ -2130,7 +2130,7 @@ function_exit:
err = btr_store_big_rec_extern_fields( err = btr_store_big_rec_extern_fields(
index, btr_cur_get_block(&cursor), index, btr_cur_get_block(&cursor),
rec, offsets, big_rec, &mtr); rec, offsets, &mtr, FALSE, big_rec);
if (modify) { if (modify) {
dtuple_big_rec_free(big_rec); dtuple_big_rec_free(big_rec);
......
...@@ -387,8 +387,11 @@ Purges an update of an existing record. Also purges an update of a delete ...@@ -387,8 +387,11 @@ Purges an update of an existing record. Also purges an update of a delete
marked record if that record contained an externally stored field. */ marked record if that record contained an externally stored field. */
static static
void void
row_purge_upd_exist_or_extern( row_purge_upd_exist_or_extern_func(
/*==========================*/ /*===============================*/
#ifdef UNIV_DEBUG
const que_thr_t*thr, /*!< in: query thread */
#endif /* UNIV_DEBUG */
purge_node_t* node) /*!< in: row purge node */ purge_node_t* node) /*!< in: row purge node */
{ {
mem_heap_t* heap; mem_heap_t* heap;
...@@ -413,8 +416,8 @@ row_purge_upd_exist_or_extern( ...@@ -413,8 +416,8 @@ row_purge_upd_exist_or_extern(
while (node->index != NULL) { while (node->index != NULL) {
index = node->index; index = node->index;
if (row_upd_changes_ord_field_binary(NULL, NULL, node->index, if (row_upd_changes_ord_field_binary(node->index, node->update,
node->update)) { thr, NULL, NULL)) {
/* Build the older version of the index entry */ /* Build the older version of the index entry */
entry = row_build_index_entry(node->row, NULL, entry = row_build_index_entry(node->row, NULL,
index, heap); index, heap);
...@@ -496,6 +499,14 @@ skip_secondaries: ...@@ -496,6 +499,14 @@ skip_secondaries:
} }
} }
#ifdef UNIV_DEBUG
# define row_purge_upd_exist_or_extern(thr,node) \
row_purge_upd_exist_or_extern_func(thr,node)
#else /* UNIV_DEBUG */
# define row_purge_upd_exist_or_extern(thr,node) \
row_purge_upd_exist_or_extern_func(node)
#endif /* UNIV_DEBUG */
/***********************************************************//** /***********************************************************//**
Parses the row reference and other info in a modify undo log record. Parses the row reference and other info in a modify undo log record.
@return TRUE if purge operation required: NOTE that then the CALLER @return TRUE if purge operation required: NOTE that then the CALLER
...@@ -602,47 +613,32 @@ err_exit: ...@@ -602,47 +613,32 @@ err_exit:
/***********************************************************//** /***********************************************************//**
Fetches an undo log record and does the purge for the recorded operation. Fetches an undo log record and does the purge for the recorded operation.
If none left, or the current purge completed, returns the control to the If none left, or the current purge completed, returns the control to the
parent node, which is always a query thread node. parent node, which is always a query thread node. */
@return DB_SUCCESS if operation successfully completed, else error code */ static __attribute__((nonnull))
static void
ulint
row_purge( row_purge(
/*======*/ /*======*/
purge_node_t* node, /*!< in: row purge node */ purge_node_t* node, /*!< in: row purge node */
que_thr_t* thr) /*!< in: query thread */ que_thr_t* thr) /*!< in: query thread */
{ {
roll_ptr_t roll_ptr;
ibool purge_needed;
ibool updated_extern; ibool updated_extern;
trx_t* trx;
ut_ad(node && thr); ut_ad(node);
ut_ad(thr);
trx = thr_get_trx(thr);
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr, node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
&(node->reservation), &node->reservation,
node->heap); node->heap);
if (!node->undo_rec) { if (!node->undo_rec) {
/* Purge completed for this query thread */ /* Purge completed for this query thread */
thr->run_node = que_node_get_parent(node); thr->run_node = que_node_get_parent(node);
return(DB_SUCCESS); return;
}
node->roll_ptr = roll_ptr;
if (node->undo_rec == &trx_purge_dummy_rec) {
purge_needed = FALSE;
} else {
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
thr);
/* If purge_needed == TRUE, we must also remember to unfreeze
data dictionary! */
} }
if (purge_needed) { if (node->undo_rec != &trx_purge_dummy_rec
&& row_purge_parse_undo_rec(node, &updated_extern, thr)) {
node->found_clust = FALSE; node->found_clust = FALSE;
node->index = dict_table_get_next_index( node->index = dict_table_get_next_index(
...@@ -654,14 +650,14 @@ row_purge( ...@@ -654,14 +650,14 @@ row_purge(
} else if (updated_extern } else if (updated_extern
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) { || node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
row_purge_upd_exist_or_extern(node); row_purge_upd_exist_or_extern(thr, node);
} }
if (node->found_clust) { if (node->found_clust) {
btr_pcur_close(&(node->pcur)); btr_pcur_close(&(node->pcur));
} }
row_mysql_unfreeze_data_dictionary(trx); row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
} }
/* Do some cleanup */ /* Do some cleanup */
...@@ -669,8 +665,6 @@ row_purge( ...@@ -669,8 +665,6 @@ row_purge(
mem_heap_empty(node->heap); mem_heap_empty(node->heap);
thr->run_node = node; thr->run_node = node;
return(DB_SUCCESS);
} }
/***********************************************************//** /***********************************************************//**
...@@ -684,9 +678,6 @@ row_purge_step( ...@@ -684,9 +678,6 @@ row_purge_step(
que_thr_t* thr) /*!< in: query thread */ que_thr_t* thr) /*!< in: query thread */
{ {
purge_node_t* node; purge_node_t* node;
#ifdef UNIV_DEBUG
ulint err;
#endif /* UNIV_DEBUG */
ut_ad(thr); ut_ad(thr);
...@@ -694,12 +685,7 @@ row_purge_step( ...@@ -694,12 +685,7 @@ row_purge_step(
ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); ut_ad(que_node_get_type(node) == QUE_NODE_PURGE);
#ifdef UNIV_DEBUG
err =
#endif /* UNIV_DEBUG */
row_purge(node, thr); row_purge(node, thr);
ut_ad(err == DB_SUCCESS);
return(thr); return(thr);
} }
...@@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low( ...@@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low(
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{ {
btr_pcur_t* pcur;
btr_cur_t* btr_cur; btr_cur_t* btr_cur;
ulint err; ulint err;
ibool success;
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC); ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
pcur = &(node->pcur);
btr_cur = btr_pcur_get_btr_cur(pcur);
success = btr_pcur_restore_position(mode, pcur, mtr); /* Find out if the record has been purged already
or if we can remove it. */
if (!success) { if (!btr_pcur_restore_position(mode, &node->pcur, mtr)
|| row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/* Find out if we can remove the whole clustered index record */ btr_cur = btr_pcur_get_btr_cur(&node->pcur);
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
&& !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
/* Ok, we can remove */
} else {
return(DB_SUCCESS);
}
if (mode == BTR_MODIFY_LEAF) { if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete(btr_cur, mtr); err = btr_cur_optimistic_delete(btr_cur, mtr)
? DB_SUCCESS
if (success) { : DB_FAIL;
err = DB_SUCCESS;
} else {
err = DB_FAIL;
}
} else { } else {
ut_ad(mode == BTR_MODIFY_TREE); ut_ad(mode == BTR_MODIFY_TREE);
...@@ -668,8 +654,9 @@ row_undo_mod_upd_exist_sec( ...@@ -668,8 +654,9 @@ row_undo_mod_upd_exist_sec(
while (node->index != NULL) { while (node->index != NULL) {
index = node->index; index = node->index;
if (row_upd_changes_ord_field_binary( if (row_upd_changes_ord_field_binary(node->index, node->update,
node->row, node->ext, node->index, node->update)) { thr,
node->row, node->ext)) {
/* Build the newest version of the index entry */ /* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, node->ext, entry = row_build_index_entry(node->row, node->ext,
......
...@@ -1192,25 +1192,31 @@ NOTE: we compare the fields as binary strings! ...@@ -1192,25 +1192,31 @@ NOTE: we compare the fields as binary strings!
@return TRUE if update vector changes an ordering field in the index record */ @return TRUE if update vector changes an ordering field in the index record */
UNIV_INTERN UNIV_INTERN
ibool ibool
row_upd_changes_ord_field_binary( row_upd_changes_ord_field_binary_func(
/*=============================*/ /*==================================*/
dict_index_t* index, /*!< in: index of the record */
const upd_t* update, /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
#ifdef UNIV_DEBUG
const que_thr_t*thr, /*!< in: query thread */
#endif /* UNIV_DEBUG */
const dtuple_t* row, /*!< in: old value of row, or NULL if the const dtuple_t* row, /*!< in: old value of row, or NULL if the
row and the data values in update are not row and the data values in update are not
known when this function is called, e.g., at known when this function is called, e.g., at
compile time */ compile time */
const row_ext_t*ext, /*!< NULL, or prefixes of the externally const row_ext_t*ext) /*!< NULL, or prefixes of the externally
stored columns in the old row */ stored columns in the old row */
dict_index_t* index, /*!< in: index of the record */
const upd_t* update) /*!< in: update vector for the row; NOTE: the
field numbers in this MUST be clustered index
positions! */
{ {
ulint n_unique; ulint n_unique;
ulint i; ulint i;
const dict_index_t* clust_index; const dict_index_t* clust_index;
ut_ad(update);
ut_ad(index); ut_ad(index);
ut_ad(update);
ut_ad(thr);
ut_ad(thr->graph);
ut_ad(thr->graph->trx);
n_unique = dict_index_get_n_unique(index); n_unique = dict_index_get_n_unique(index);
...@@ -1263,9 +1269,14 @@ row_upd_changes_ord_field_binary( ...@@ -1263,9 +1269,14 @@ row_upd_changes_ord_field_binary(
if (UNIV_LIKELY_NULL(buf)) { if (UNIV_LIKELY_NULL(buf)) {
if (UNIV_UNLIKELY(buf == field_ref_zero)) { if (UNIV_UNLIKELY(buf == field_ref_zero)) {
/* This should never happen, but /* The externally stored field
we try to fail safe here. */ was not written yet. This
ut_ad(0); record should only be seen by
recv_recovery_rollback_active(),
when the server had crashed before
storing the field. */
ut_ad(thr->graph->trx->is_recovered);
ut_ad(trx_is_recv(thr->graph->trx));
return(TRUE); return(TRUE);
} }
...@@ -1612,8 +1623,8 @@ row_upd_sec_step( ...@@ -1612,8 +1623,8 @@ row_upd_sec_step(
ut_ad(!dict_index_is_clust(node->index)); ut_ad(!dict_index_is_clust(node->index));
if (node->state == UPD_NODE_UPDATE_ALL_SEC if (node->state == UPD_NODE_UPDATE_ALL_SEC
|| row_upd_changes_ord_field_binary(node->row, node->ext, || row_upd_changes_ord_field_binary(node->index, node->update,
node->index, node->update)) { thr, node->row, node->ext)) {
return(row_upd_sec_index_entry(node, thr)); return(row_upd_sec_index_entry(node, thr));
} }
...@@ -1941,7 +1952,7 @@ row_upd_clust_rec( ...@@ -1941,7 +1952,7 @@ row_upd_clust_rec(
index, btr_cur_get_block(btr_cur), rec, index, btr_cur_get_block(btr_cur), rec,
rec_get_offsets(rec, index, offsets_, rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap), ULINT_UNDEFINED, &heap),
big_rec, mtr); mtr, TRUE, big_rec);
mtr_commit(mtr); mtr_commit(mtr);
} }
...@@ -2140,8 +2151,8 @@ exit_func: ...@@ -2140,8 +2151,8 @@ exit_func:
row_upd_store_row(node); row_upd_store_row(node);
if (row_upd_changes_ord_field_binary(node->row, node->ext, index, if (row_upd_changes_ord_field_binary(index, node->update, thr,
node->update)) { node->row, node->ext)) {
/* Update causes an ordering field (ordering fields within /* Update causes an ordering field (ordering fields within
the B-tree) of the clustered index record to change: perform the B-tree) of the clustered index record to change: perform
......
...@@ -48,8 +48,8 @@ Created 3/26/1996 Heikki Tuuri ...@@ -48,8 +48,8 @@ Created 3/26/1996 Heikki Tuuri
rollback */ rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1 #define TRX_ROLL_TRUNC_THRESHOLD 1
/** In crash recovery, the current trx to be rolled back */ /** In crash recovery, the current trx to be rolled back; NULL otherwise */
static trx_t* trx_roll_crash_recv_trx = NULL; static const trx_t* trx_roll_crash_recv_trx = NULL;
/** In crash recovery we set this to the undo n:o of the current trx to be /** In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */ rolled back. Then we can print how many % the rollback has progressed. */
......
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