Commit 1311f7ce authored by heikki@donna.mysql.fi's avatar heikki@donna.mysql.fi
Browse files

trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints

trx0sys.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0trx.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0mysql.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0purge.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0sel.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0uins.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0umod.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
row0upd.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0srv.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0start.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
sync0arr.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
fil0fil.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
ibuf0ibuf.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
lock0lock.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
os0file.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0btr.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0cur.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0sea.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
buf0buf.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
data0data.c	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
srv0srv.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0sys.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
trx0trx.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
btr0cur.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
buf0buf.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
data0data.h	Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
ha_innobase.cc	Fix the auto-inc+REPLACE+replication bug, improve InnoDB Monitor prints
parent e4ba2983
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1738,8 +1738,8 @@ btr_node_ptr_delete(

	btr_cur_position(UT_LIST_GET_FIRST(tree->tree_indexes), node_ptr,
								&cursor);
	compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, mtr);

	compressed = btr_cur_pessimistic_delete(&err, TRUE, &cursor, FALSE,
									mtr);
	ut_a(err == DB_SUCCESS);

	if (!compressed) {
+276 −10
Original line number Diff line number Diff line
@@ -80,6 +80,9 @@ btr_rec_free_updated_extern_fields(
				X-latched */
	rec_t*		rec,	/* in: record */
	upd_t*		update,	/* in: update vector */
	ibool		do_not_free_inherited,/* in: TRUE if called in a
				rollback and we do not want to free
				inherited fields */
	mtr_t*		mtr);	/* in: mini-transaction handle which contains
				an X-latch to record page and to the tree */

@@ -813,7 +816,7 @@ btr_cur_optimistic_insert(
		/* The record is so big that we have to store some fields
		externally on separate database pages */
		
                big_rec_vec = dtuple_convert_big_rec(index, entry);
                big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0);

		if (big_rec_vec == NULL) {
		
@@ -1021,7 +1024,7 @@ btr_cur_pessimistic_insert(
		/* The record is so big that we have to store some fields
		externally on separate database pages */
		
                big_rec_vec = dtuple_convert_big_rec(index, entry);
                big_rec_vec = dtuple_convert_big_rec(index, entry, NULL, 0);

		if (big_rec_vec == NULL) {
		
@@ -1242,6 +1245,7 @@ btr_cur_update_in_place(
	rec_t*		rec;
	dulint		roll_ptr;
	trx_t*		trx;
	ibool		was_delete_marked;

	/* Only clustered index records are updated using this function */
	ut_ad((cursor->index)->type & DICT_CLUSTERED);
@@ -1271,6 +1275,8 @@ btr_cur_update_in_place(
	/* FIXME: in a mixed tree, all records may not have enough ordering
	fields for btr search: */

	was_delete_marked = rec_get_deleted_flag(rec);
	
	row_upd_rec_in_place(rec, update);

	if (block->is_hashed) {
@@ -1279,6 +1285,13 @@ btr_cur_update_in_place(

	btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
									mtr);
	if (was_delete_marked && !rec_get_deleted_flag(rec)) {
		/* The new updated record owns its possible externally
		stored fields */

		btr_cur_unmark_extern_fields(rec, mtr);
	}

	return(DB_SUCCESS);
}

@@ -1434,6 +1447,13 @@ btr_cur_optimistic_update(

	ut_a(rec); /* <- We calculated above the insert would fit */

	if (!rec_get_deleted_flag(rec)) {
		/* The new inserted record owns its possible externally
		stored fields */

		btr_cur_unmark_extern_fields(rec, mtr);
	}

	/* Restore the old explicit lock state on the record */

	lock_rec_restore_from_page_infimum(rec, page);
@@ -1655,11 +1675,15 @@ btr_cur_pessimistic_update(
	if (flags & BTR_NO_UNDO_LOG_FLAG) {
		/* We are in a transaction rollback undoing a row
		update: we must free possible externally stored fields
		which got new values in the update */
		which got new values in the update, if they are not
		inherited values. They can be inherited if we have
		updated the primary key to another value, and then
		update it back again. */

		ut_a(big_rec_vec == NULL);
		
		btr_rec_free_updated_extern_fields(index, rec, update, mtr);
		btr_rec_free_updated_extern_fields(index, rec, update,
						 		TRUE, mtr);
	}

	/* We have to set appropriate extern storage bits in the new
@@ -1676,8 +1700,8 @@ btr_cur_pessimistic_update(
				page_get_free_space_of_empty() / 2)
	    || (rec_get_converted_size(new_entry) >= REC_MAX_DATA_SIZE)) {

                big_rec_vec = dtuple_convert_big_rec(index, new_entry);

                big_rec_vec = dtuple_convert_big_rec(index, new_entry,
                					ext_vect, n_ext_vect);
		if (big_rec_vec == NULL) {

			mem_heap_free(heap);
@@ -1694,6 +1718,13 @@ btr_cur_pessimistic_update(
		lock_rec_restore_from_page_infimum(rec, page);
		rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
		
		if (!rec_get_deleted_flag(rec)) {
			/* The new inserted record owns its possible externally
			stored fields */

			btr_cur_unmark_extern_fields(rec, mtr);
		}

		btr_cur_compress_if_useful(cursor, mtr);

		err = DB_SUCCESS;
@@ -1725,6 +1756,13 @@ btr_cur_pessimistic_update(

	rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);

	if (!rec_get_deleted_flag(rec)) {
		/* The new inserted record owns its possible externally
		stored fields */

		btr_cur_unmark_extern_fields(rec, mtr);
	}

	lock_rec_restore_from_page_infimum(rec, page);

	/* If necessary, restore also the correct lock state for a new,
@@ -2183,6 +2221,7 @@ btr_cur_pessimistic_delete(
				if compression does not occur, the cursor
				stays valid: it points to successor of
				deleted record on function exit */
	ibool		in_rollback,/* in: TRUE if called in rollback */
	mtr_t*		mtr)	/* in: mtr */
{
	page_t*		page;
@@ -2218,7 +2257,8 @@ btr_cur_pessimistic_delete(
	}

	btr_rec_free_externally_stored_fields(cursor->index,
					btr_cur_get_rec(cursor), mtr);
			btr_cur_get_rec(cursor), in_rollback, mtr);

	if ((page_get_n_recs(page) < 2)
	    && (dict_tree_get_page(btr_cur_get_tree(cursor))
					!= buf_frame_get_page_no(page))) {
@@ -2516,6 +2556,199 @@ btr_estimate_number_of_different_key_vals(

/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/

/***********************************************************************
Sets the ownership bit of an externally stored field in a record. */
static
void
btr_cur_set_ownership_of_extern_field(
/*==================================*/
	rec_t*	rec,	/* in: clustered index record */
	ulint	i,	/* in: field number */
	ibool	val,	/* in: value to set */
	mtr_t*	mtr)	/* in: mtr */
{
	byte*	data;
	ulint	local_len;
	ulint	byte_val;

	data = rec_get_nth_field(rec, i, &local_len);
	
	ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);

	local_len -= BTR_EXTERN_FIELD_REF_SIZE;

	byte_val = mach_read_from_1(data + local_len + BTR_EXTERN_LEN);

	if (val) {
		byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
	} else {
		byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
	}
	
	mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
							MLOG_1BYTE, mtr);
}

/***********************************************************************
Marks not updated extern fields as not-owned by this record. The ownership
is transferred to the updated record which is inserted elsewhere in the
index tree. In purge only the owner of externally stored field is allowed
to free the field. */

void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
	rec_t*	rec,	/* in: record in a clustered index */
	upd_t*	update,	/* in: update vector */
	mtr_t*	mtr)	/* in: mtr */
{
	ibool	is_updated;
	ulint	n;
	ulint	j;
	ulint	i;
	
	n = rec_get_n_fields(rec);

	for (i = 0; i < n; i++) {
		if (rec_get_nth_field_extern_bit(rec, i)) {
			
			/* Check it is not in updated fields */
			is_updated = FALSE;

			if (update) {
				for (j = 0; j < upd_get_n_fields(update);
								j++) {
					if (upd_get_nth_field(update, j)
							->field_no == i) {
						is_updated = TRUE;
					}
				}
			}

			if (!is_updated) {
				btr_cur_set_ownership_of_extern_field(rec, i,
								FALSE, mtr);
			}
		}
	}
}

/***********************************************************************
The complement of the previous function: in an update entry may inherit
some externally stored fields from a record. We must mark them as inherited
in entry, so that they are not freed in a rollback. */

void
btr_cur_mark_dtuple_inherited_extern(
/*=================================*/
	dtuple_t*	entry,		/* in: updated entry to be inserted to
					clustered index */
	ulint*		ext_vec,	/* in: array of extern fields in the
					original record */
	ulint		n_ext_vec,	/* in: number of elements in ext_vec */
	upd_t*		update)		/* in: update vector */
{
	dfield_t* dfield;
	ulint	byte_val;
	byte*	data;
	ulint	len;
	ibool	is_updated;
	ulint	j;
	ulint	i;

	if (ext_vec == NULL) {

		return;
	}
	
	for (i = 0; i < n_ext_vec; i++) {

		/* Check ext_vec[i] is in updated fields */
		is_updated = FALSE;

		for (j = 0; j < upd_get_n_fields(update); j++) {
			if (upd_get_nth_field(update, j)->field_no
							== ext_vec[i]) {
				is_updated = TRUE;
			}
		}

		if (!is_updated) {
			dfield = dtuple_get_nth_field(entry, ext_vec[i]);

			data = dfield_get_data(dfield);
			len = dfield_get_len(dfield);
		
			len -= BTR_EXTERN_FIELD_REF_SIZE;

			byte_val = mach_read_from_1(data + len
							+ BTR_EXTERN_LEN);

			byte_val = byte_val | BTR_EXTERN_INHERITED_FLAG;
		
			mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val);
		}
	}
}

/***********************************************************************
Marks all extern fields in a record as owned by the record. This function
should be called if the delete mark of a record is removed: a not delete
marked record always owns all its extern fields. */

void
btr_cur_unmark_extern_fields(
/*=========================*/
	rec_t*	rec,	/* in: record in a clustered index */
	mtr_t*	mtr)	/* in: mtr */
{
	ulint	n;
	ulint	i;

	n = rec_get_n_fields(rec);

	for (i = 0; i < n; i++) {
		if (rec_get_nth_field_extern_bit(rec, i)) {
			
			btr_cur_set_ownership_of_extern_field(rec, i,
								TRUE, mtr);
		}
	}	
}

/***********************************************************************
Marks all extern fields in a dtuple as owned by the record. */

void
btr_cur_unmark_dtuple_extern_fields(
/*================================*/
	dtuple_t*	entry,		/* in: clustered index entry */
	ulint*		ext_vec,	/* in: array of numbers of fields
					which have been stored externally */
	ulint		n_ext_vec)	/* in: number of elements in ext_vec */
{
	dfield_t* dfield;
	ulint	byte_val;
	byte*	data;
	ulint	len;
	ulint	i;

	for (i = 0; i < n_ext_vec; i++) {
		dfield = dtuple_get_nth_field(entry, ext_vec[i]);

		data = dfield_get_data(dfield);
		len = dfield_get_len(dfield);
		
		len -= BTR_EXTERN_FIELD_REF_SIZE;

		byte_val = mach_read_from_1(data + len + BTR_EXTERN_LEN);

		byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
		
		mach_write_to_1(data + len + BTR_EXTERN_LEN, byte_val);
	}	
}

/***********************************************************************
Stores the positions of the fields marked as extern storage in the update
vector, and also those fields who are marked as extern storage in rec
@@ -2766,7 +2999,9 @@ btr_store_big_rec_extern_fields(

/***********************************************************************
Frees the space in an externally stored field to the file space
management. */
management if the field in data is owned the externally stored field,
in a rollback we may have the additional condition that the field must
not be inherited. */

void
btr_free_externally_stored_field(
@@ -2777,6 +3012,9 @@ btr_free_externally_stored_field(
					+ reference to the externally
					stored part */
	ulint		local_len,	/* in: length of data */
	ibool		do_not_free_inherited,/* in: TRUE if called in a
					rollback and we do not want to free
					inherited fields */
	mtr_t*		local_mtr)	/* in: mtr containing the latch to
					data an an X-latch to the index
					tree */
@@ -2828,6 +3066,26 @@ btr_free_externally_stored_field(
			return;
		}

		if (mach_read_from_1(data + local_len + BTR_EXTERN_LEN)
						& BTR_EXTERN_OWNER_FLAG) {
			/* This field does not own the externally
			stored field: do not free! */

			mtr_commit(&mtr);

			return;
		}

		if (do_not_free_inherited
			&& mach_read_from_1(data + local_len + BTR_EXTERN_LEN)
						& BTR_EXTERN_INHERITED_FLAG) {
			/* Rollback and inherited field: do not free! */

			mtr_commit(&mtr);

			return;
		}
		
		page = buf_page_get(space_id, page_no, RW_X_LATCH, &mtr);
		
		buf_page_dbg_add_level(page, SYNC_EXTERN_STORAGE);
@@ -2872,6 +3130,9 @@ btr_rec_free_externally_stored_fields(
	dict_index_t*	index,	/* in: index of the data, the index
				tree MUST be X-latched */
	rec_t*		rec,	/* in: record */
	ibool		do_not_free_inherited,/* in: TRUE if called in a
				rollback and we do not want to free
				inherited fields */
	mtr_t*		mtr)	/* in: mini-transaction handle which contains
				an X-latch to record page and to the index
				tree */
@@ -2896,7 +3157,8 @@ btr_rec_free_externally_stored_fields(
		if (rec_get_nth_field_extern_bit(rec, i)) {

			data = rec_get_nth_field(rec, i, &len);
			btr_free_externally_stored_field(index, data, len, mtr);
			btr_free_externally_stored_field(index, data, len,
						do_not_free_inherited, mtr);
		}
	}
}
@@ -2912,6 +3174,9 @@ btr_rec_free_updated_extern_fields(
				X-latched */
	rec_t*		rec,	/* in: record */
	upd_t*		update,	/* in: update vector */
	ibool		do_not_free_inherited,/* in: TRUE if called in a
				rollback and we do not want to free
				inherited fields */
	mtr_t*		mtr)	/* in: mini-transaction handle which contains
				an X-latch to record page and to the tree */
{
@@ -2938,7 +3203,8 @@ btr_rec_free_updated_extern_fields(
		if (rec_get_nth_field_extern_bit(rec, ufield->field_no)) {

			data = rec_get_nth_field(rec, ufield->field_no, &len);
			btr_free_externally_stored_field(index, data, len, mtr);
			btr_free_externally_stored_field(index, data, len,
						do_not_free_inherited, mtr);
		}
	}
}
+5 −0
Original line number Diff line number Diff line
@@ -769,6 +769,11 @@ btr_search_guess_on_hash(
		buf_page_make_young(page);
	}	

	/* Increment the page get statistics though we did not really
	fix the page: for user info only */

	buf_pool->n_page_gets++;

	return(TRUE);	

	/*-------------------------------------------*/
+21 −0
Original line number Diff line number Diff line
@@ -349,6 +349,10 @@ buf_pool_create(
	buf_pool->n_pages_written = 0;
	buf_pool->n_pages_created = 0;

	buf_pool->n_page_gets = 0;
	buf_pool->n_page_gets_old = 0;
	buf_pool->n_pages_read_old = 0;
	
	/* 2. Initialize flushing fields
	   ---------------------------- */
	UT_LIST_INIT(buf_pool->flush_list);
@@ -667,6 +671,7 @@ buf_page_get_gen(
#ifndef UNIV_LOG_DEBUG
	ut_ad(!ibuf_inside() || ibuf_page(space, offset));
#endif
	buf_pool->n_page_gets++;
loop:
	mutex_enter_fast(&(buf_pool->mutex));

@@ -846,6 +851,8 @@ buf_page_optimistic_get_func(
	ut_ad(mtr && guess);
	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));

	buf_pool->n_page_gets++;

	block = buf_block_align(guess);
	
	mutex_enter(&(buf_pool->mutex));
@@ -976,6 +983,8 @@ buf_page_get_known_nowait(
	ut_ad(mtr);
	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));

	buf_pool->n_page_gets++;

	block = buf_block_align(guess);
	
	mutex_enter(&(buf_pool->mutex));
@@ -1643,6 +1652,18 @@ buf_print_io(void)
	printf("Pages read %lu, created %lu, written %lu\n",
			buf_pool->n_pages_read, buf_pool->n_pages_created,
						buf_pool->n_pages_written);

	if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
		printf("Buffer pool hit rate %lu / 1000\n",
		1000
		- ((1000 *
		    (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
		/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old)));
	}

	buf_pool->n_page_gets_old = buf_pool->n_page_gets;
	buf_pool->n_pages_read_old = buf_pool->n_pages_read;

	mutex_exit(&(buf_pool->mutex));
}

+23 −2
Original line number Diff line number Diff line
@@ -395,7 +395,12 @@ dtuple_convert_big_rec(
				the entry enough, i.e., if there are
				too many short fields in entry */
	dict_index_t*	index,	/* in: index */
	dtuple_t*	entry)	/* in: index entry */
	dtuple_t*	entry,	/* in: index entry */
	ulint*		ext_vec,/* in: array of externally stored fields,
				or NULL: if a field already is externally
				stored, then we cannot move it to the vector
				this function returns */
	ulint		n_ext_vec)/* in: number of elements is ext_vec */
{
	mem_heap_t*	heap;
	big_rec_t*	vector;
@@ -404,7 +409,9 @@ dtuple_convert_big_rec(
	ulint		n_fields;
	ulint		longest;
	ulint		longest_i;
	ibool		is_externally_stored;
	ulint		i;
	ulint		j;
	
	size = rec_get_converted_size(entry);

@@ -431,9 +438,23 @@ dtuple_convert_big_rec(
		for (i = dict_index_get_n_unique_in_tree(index);
				i < dtuple_get_n_fields(entry); i++) {

			/* Skip over fields which already are externally
			stored */

			is_externally_stored = FALSE;

			if (ext_vec) {
				for (j = 0; j < n_ext_vec; j++) {
					if (ext_vec[j] == i) {
						is_externally_stored = TRUE;
					}
				}
			}
				
			/* Skip over fields which are ordering in some index */

			if (dict_field_get_col(
			if (!is_externally_stored &&
			    dict_field_get_col(
			    	dict_index_get_nth_field(index, i))
			    ->ord_part == 0) {

Loading