Commit 97aa1215 authored by Sunny Bains's avatar Sunny Bains

Merge from -c3476 mysql-5.1-security.

     ------------------------------------------------------------
     revno: 3476
     committer: Sunny Bains <Sunny.Bains@Oracle.Com>
     branch nick: 5.1-security
     timestamp: Thu 2010-08-05 19:18:17 +1000
     message:
       Fix bug# 55543 - InnoDB Plugin: Signal 6: Assertion failure in file fil/fil0fil.c line 4306

         The bug is due to a double delete of a BLOB, once via:

               rollback -> btr_cur_pessimistic_delete()

         and the second time via purge.

         The bug is in row_upd_clust_rec_by_insert(). There we relinquish ownership
         of the non-updated BLOB columns in btr_cur_mark_extern_inherited_fields()
         before building the row entry that will be inserted and whose contents will
         be logged in the UNDO log. However, we don't set the BLOB column later to
         INHERITED so that a possible rollback will not free the original row's
         non-updated BLOB entries. This is because the condition that checks for
         that is in :

     		    	if (node->upd_ext) {}.

         node->upd_ext is non-NULL only if a BLOB column was updated and that column
         is part of some key ordering (see row_upd_replace()). This results in the
         non-update BLOB columns being deleted during a rollback and subsequently by
         purge again.

         rb://413
parent 787f0c54
......@@ -3603,9 +3603,10 @@ btr_cur_set_ownership_of_extern_field(
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. */
to free the field.
@return TRUE if BLOB ownership was transferred */
UNIV_INTERN
void
ibool
btr_cur_mark_extern_inherited_fields(
/*=================================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
......@@ -3619,13 +3620,14 @@ btr_cur_mark_extern_inherited_fields(
ulint n;
ulint j;
ulint i;
ibool change_ownership = FALSE;
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
if (!rec_offs_any_extern(offsets)) {
return;
return(FALSE);
}
n = rec_offs_n_fields(offsets);
......@@ -3648,10 +3650,14 @@ btr_cur_mark_extern_inherited_fields(
btr_cur_set_ownership_of_extern_field(
page_zip, rec, index, offsets, i, FALSE, mtr);
change_ownership = TRUE;
updated:
;
}
}
return(change_ownership);
}
/*******************************************************************//**
......
......@@ -456,9 +456,10 @@ btr_estimate_number_of_different_key_vals(
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. */
to free the field.
@return TRUE if BLOB ownership was transferred */
UNIV_INTERN
void
ibool
btr_cur_mark_extern_inherited_fields(
/*=================================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
......
......@@ -1626,6 +1626,7 @@ row_upd_clust_rec_by_insert(
dict_table_t* table;
dtuple_t* entry;
ulint err;
ibool change_ownership = FALSE;
ut_ad(node);
ut_ad(dict_index_is_clust(index));
......@@ -1658,10 +1659,11 @@ row_upd_clust_rec_by_insert(
index = dict_table_get_first_index(table);
offsets = rec_get_offsets(rec, index, offsets_,
ULINT_UNDEFINED, &heap);
btr_cur_mark_extern_inherited_fields(
change_ownership = btr_cur_mark_extern_inherited_fields(
btr_cur_get_page_zip(btr_cur),
rec, index, offsets, node->update, mtr);
if (referenced) {
/* NOTE that the following call loses
the position of pcur ! */
......@@ -1694,10 +1696,11 @@ row_upd_clust_rec_by_insert(
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
if (node->upd_ext) {
if (change_ownership) {
/* If we return from a lock wait, for example, we may have
extern fields marked as not-owned in entry (marked in the
if-branch above). We must unmark them. */
if-branch above). We must unmark them, take the ownership
back. */
btr_cur_unmark_dtuple_extern_fields(entry);
......
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