~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0upd.c

  • Committer: Stewart Smith
  • Author(s): Sunny Bains, Stewart Smith
  • Date: 2010-12-03 04:01:54 UTC
  • mto: (2021.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1986.
  • Revision ID: stewart@flamingspork.com-20101203040154-gul37i0qaqnqpmw7
Merge Revision revid:sunny.bains@oracle.com-20100805091817-nsk8q8dzz47puv9p from MySQL InnoDB

Original revid:sunny.bains@oracle.com-20100805091817-nsk8q8dzz47puv9p

Original Authors: Sunny Bains <Sunny.Bains@Oracle.Com>
Original commit 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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1636
1636
        dict_table_t*   table;
1637
1637
        dtuple_t*       entry;
1638
1638
        ulint           err;
 
1639
        ibool           change_ownership = FALSE;
1639
1640
 
1640
1641
        ut_ad(node);
1641
1642
        ut_ad(dict_index_is_clust(index));
1668
1669
                index = dict_table_get_first_index(table);
1669
1670
                offsets = rec_get_offsets(rec, index, offsets_,
1670
1671
                                          ULINT_UNDEFINED, &heap);
1671
 
                btr_cur_mark_extern_inherited_fields(
1672
 
                        btr_cur_get_page_zip(btr_cur),
1673
 
                        rec, index, offsets, node->update, mtr);
 
1672
                change_ownership = btr_cur_mark_extern_inherited_fields(
 
1673
                        btr_cur_get_page_zip(btr_cur), rec, index, offsets,
 
1674
                        node->update, mtr);
1674
1675
                if (referenced) {
1675
1676
                        /* NOTE that the following call loses
1676
1677
                        the position of pcur ! */
1704
1705
 
1705
1706
        row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
1706
1707
 
1707
 
        if (node->upd_ext) {
 
1708
        if (change_ownership) {
1708
1709
                /* If we return from a lock wait, for example, we may have
1709
1710
                extern fields marked as not-owned in entry (marked in the
1710
 
                if-branch above). We must unmark them. */
 
1711
                if-branch above). We must unmark them, take the ownership
 
1712
                back. */
1711
1713
 
1712
1714
                btr_cur_unmark_dtuple_extern_fields(entry);
1713
1715