mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 15:15:34 +02:00
Bug #55284 Double BLOB free due to lock wait while updating PRIMARY KEY
This bug fix requires that Bug #58912 be fixed as well (bzr revision id marko.makela@oracle.com-20101221093919-mcmmgd4zpse9567d). Otherwise, another double BLOB free could occur when InnoDB would try to perform an update-in-place as delete-and-insert-by-update-in-place. row_upd_clust_rec_by_insert(): Do not disown the externally stored columns from the old record (btr_cur_mark_extern_inherited_fields()) until after checking the foreign key constraints and successfully inserting the updated record. If a lock wait timeout occurs between the delete-marking of the old record and the insertion of the updated record, mark the columns inherited before retrying the insert. Distinguish the state UPD_NODE_INSERT_BLOB from UPD_NODE_INSERT_CLUSTERED. btr_cur_del_mark_set_clust_rec(): Replace the cursor with block,rec,index,offsets so that the offsets need not be recalculated. Assert that rec is on a clustered index leaf page. btr_cur_disown_inherited_fields(): Renamed from btr_cur_mark_extern_inherited_fields(). Use upd_get_field_by_field_no(). Assert that there are externally stored columns. Assert that a mini-transaction is passed. Remove the return status. (The only caller, row_upd_clust_rec_by_insert(), will have determined that some fields have changed ownership.) btr_cur_mark_dtuple_inherited_extern(): Rename to row_upd_clust_rec_by_insert_inherit_func() and declare as static. Add the debug parameters rec, offsets. When rec is given, assert that the off-page columns match those in the inesrt tuple and that the off-page columns are owned by the record. Assert that the non-updated off-page columns in the insert tuple are owned, and mark them inherited. row_upd_clust_rec_by_insert_inherit(): A wrapper macro for row_upd_clust_rec_by_insert_inherit_func(). row_undo_mod_upd_exist_sec(): Adjust a comment about row_upd_clust_rec_by_insert(). rb:508 approved by Jimmy Yang
This commit is contained in:
parent
590fdf7792
commit
721a890e48
6 changed files with 228 additions and 213 deletions
|
|
@ -332,10 +332,14 @@ ulint
|
|||
btr_cur_del_mark_set_clust_rec(
|
||||
/*===========================*/
|
||||
ulint flags, /*!< in: undo logging and locking flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor */
|
||||
buf_block_t* block, /*!< in/out: buffer block of the record */
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
dict_index_t* index, /*!< in: clustered index of the record */
|
||||
const ulint* offsets,/*!< in: rec_get_offsets(rec) */
|
||||
ibool val, /*!< in: value to set */
|
||||
que_thr_t* thr, /*!< in: query thread */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
__attribute__((nonnull));
|
||||
/***********************************************************//**
|
||||
Sets a secondary index record delete mark to TRUE or FALSE.
|
||||
@return DB_SUCCESS, DB_LOCK_WAIT, or error number */
|
||||
|
|
@ -481,40 +485,22 @@ btr_estimate_number_of_different_key_vals(
|
|||
/*======================================*/
|
||||
dict_index_t* index); /*!< in: index */
|
||||
/*******************************************************************//**
|
||||
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
|
||||
Marks non-updated off-page fields as disowned by this record. The ownership
|
||||
must be 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.
|
||||
@return TRUE if BLOB ownership was transferred */
|
||||
to free the field. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_cur_mark_extern_inherited_fields(
|
||||
/*=================================*/
|
||||
void
|
||||
btr_cur_disown_inherited_fields(
|
||||
/*============================*/
|
||||
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
|
||||
part will be updated, or NULL */
|
||||
rec_t* rec, /*!< in/out: record in a clustered index */
|
||||
dict_index_t* index, /*!< in: index of the page */
|
||||
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
|
||||
const upd_t* update, /*!< in: update vector */
|
||||
mtr_t* mtr); /*!< in: mtr, or NULL if not logged */
|
||||
/*******************************************************************//**
|
||||
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. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_mark_dtuple_inherited_extern(
|
||||
/*=================================*/
|
||||
dtuple_t* entry, /*!< in/out: updated entry to be
|
||||
inserted to clustered index */
|
||||
const upd_t* update); /*!< in: update vector */
|
||||
/*******************************************************************//**
|
||||
Marks all extern fields in a dtuple as owned by the record. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_cur_unmark_dtuple_extern_fields(
|
||||
/*================================*/
|
||||
dtuple_t* entry); /*!< in/out: clustered index entry */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull(2,3,4,5,6)));
|
||||
/*******************************************************************//**
|
||||
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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue