diff options
author | unknown <heikki@donna.mysql.fi> | 2001-08-29 19:42:23 +0300 |
---|---|---|
committer | unknown <heikki@donna.mysql.fi> | 2001-08-29 19:42:23 +0300 |
commit | a8e4b9b21c8574d91f7f817bf9a5f0099848886a (patch) | |
tree | 9d78d40bd578ed463aac576cc0fbd077bbe9cd20 /innobase/btr/btr0cur.c | |
parent | cd0c4bb2e792ad0c5c62aa8b68b02e5656687af9 (diff) | |
download | mariadb-git-a8e4b9b21c8574d91f7f817bf9a5f0099848886a.tar.gz |
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
sql/ha_innobase.cc:
Fix the auto-inc+REPLACE+replication bug, improve InnoDB Monitor prints
innobase/include/btr0cur.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/include/buf0buf.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/include/data0data.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/include/srv0srv.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/include/trx0sys.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/include/trx0trx.h:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/btr/btr0btr.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/btr/btr0cur.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/btr/btr0sea.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/buf/buf0buf.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/data/data0data.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/fil/fil0fil.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/ibuf/ibuf0ibuf.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/lock/lock0lock.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/os/os0file.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0mysql.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0purge.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0sel.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0uins.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0umod.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/row/row0upd.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/srv/srv0srv.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/srv/srv0start.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/sync/sync0arr.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/trx/trx0roll.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/trx/trx0sys.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
innobase/trx/trx0trx.c:
Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
Diffstat (limited to 'innobase/btr/btr0cur.c')
-rw-r--r-- | innobase/btr/btr0cur.c | 286 |
1 files changed, 276 insertions, 10 deletions
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 47a67d425cd..7783f618d6d 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -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 @@ calculate_sizes_again: /* 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); @@ -1270,6 +1274,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); @@ -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))) { @@ -2517,6 +2557,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 and not mentioned in updated fields. We use this function to remember @@ -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); } } } |