📄 trx0rec.c
字号:
ptr++; len = mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += len; len = mach_dulint_write_much_compressed(ptr, table->id); ptr += len; /*----------------------------------------*/ /* Store the state of the info bits */ bits = rec_get_info_bits(rec, table->comp); mach_write_to_1(ptr, bits); ptr += 1; /* Store the values of the system columns */ field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos(index, DATA_TRX_ID), &len); ut_ad(len == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), &len); ut_ad(len == DATA_ROLL_PTR_LEN); roll_ptr = trx_read_roll_ptr(field); len = mach_dulint_write_compressed(ptr, trx_id); ptr += len; len = mach_dulint_write_compressed(ptr, roll_ptr); ptr += len; /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record which will be modified in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { field = rec_get_nth_field(rec, offsets, i, &flen); if (trx_undo_left(undo_page, ptr) < 4) { return(0); } len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } /*----------------------------------------*/ /* Save to the undo log the old values of the columns to be updated. */ if (update) { if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, upd_get_n_fields(update)); ptr += len; for (i = 0; i < upd_get_n_fields(update); i++) { upd_field = upd_get_nth_field(update, i); pos = upd_field->field_no; /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, pos); ptr += len; /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } if (rec_offs_nth_extern(offsets, pos)) { /* If a field has external storage, we add to flen the flag */ len = mach_write_compressed(ptr, UNIV_EXTERN_STORAGE_FIELD + flen); /* Notify purge that it eventually has to free the old externally stored field */ trx->update_undo->del_marks = TRUE; *type_cmpl_ptr = *type_cmpl_ptr | TRX_UNDO_UPD_EXTERN; } else { len = mach_write_compressed(ptr, flen); } ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } /*----------------------------------------*/ /* In the case of a delete marking, and also in the case of an update where any ordering field of any index changes, store the values of all columns which occur as ordering fields in any index. This info is used in the purge of old versions where we use it to build and search the delete marked index records, to look if we can remove them from the index tree. Note that starting from 4.0.14 also externally stored fields can be ordering in some index. But we always store at least 384 first bytes locally to the clustered index record, which means we can construct the column prefix fields in the index from the stored data. */ if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { trx->update_undo->del_marks = TRUE; if (trx_undo_left(undo_page, ptr) < 5) { return(0); } old_ptr = ptr; /* Reserve 2 bytes to write the number of bytes the stored fields take in this undo record */ ptr += 2; for (col_no = 0; col_no < dict_table_get_n_cols(table); col_no++) { col = dict_table_get_nth_col(table, col_no); if (col->ord_part > 0) { pos = dict_index_get_nth_col_pos(index, col_no); /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, pos); ptr += len; /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } mach_write_to_2(old_ptr, ptr - old_ptr); } /*----------------------------------------*/ /* Write pointers to the previous and the next undo log records */ if (trx_undo_left(undo_page, ptr) < 2) { return(0); } mach_write_to_2(ptr, first_free); ptr += 2; mach_write_to_2(undo_page + first_free, ptr - undo_page); mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, ptr - undo_page); /* Write to the REDO log about this change in the UNDO log */ trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); return(first_free); }/**************************************************************************Reads from an undo log update record the system field values of the oldversion. */byte*trx_undo_update_rec_get_sys_cols(/*=============================*/ /* out: remaining part of undo log record after reading these values */ byte* ptr, /* in: remaining part of undo log record after reading general parameters */ dulint* trx_id, /* out: trx id */ dulint* roll_ptr, /* out: roll ptr */ ulint* info_bits) /* out: info bits state */{ ulint len; /* Read the state of the info bits */ *info_bits = mach_read_from_1(ptr); ptr += 1; /* Read the values of the system columns */ *trx_id = mach_dulint_read_compressed(ptr); len = mach_dulint_get_compressed_size(*trx_id); ptr += len; *roll_ptr = mach_dulint_read_compressed(ptr); len = mach_dulint_get_compressed_size(*roll_ptr); ptr += len; return(ptr);}/**************************************************************************Reads from an update undo log record the number of updated fields. */UNIV_INLINEbyte*trx_undo_update_rec_get_n_upd_fields(/*=================================*/ /* out: remaining part of undo log record after reading this value */ byte* ptr, /* in: pointer to remaining part of undo log record */ ulint* n) /* out: number of fields */{ *n = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*n); return(ptr);}/**************************************************************************Reads from an update undo log record a stored field number. */UNIV_INLINEbyte*trx_undo_update_rec_get_field_no(/*=============================*/ /* out: remaining part of undo log record after reading this value */ byte* ptr, /* in: pointer to remaining part of undo log record */ ulint* field_no)/* out: field number */{ *field_no = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*field_no); return(ptr);}/***********************************************************************Builds an update vector based on a remaining part of an undo log record. */byte*trx_undo_update_rec_get_update(/*===========================*/ /* out: remaining part of the record, NULL if an error detected, which means that the record is corrupted */ byte* ptr, /* in: remaining part in update undo log record, after reading the row reference NOTE that this copy of the undo log record must be preserved as long as the update vector is used, as we do NOT copy the data in the record! */ dict_index_t* index, /* in: clustered index */ ulint type, /* in: TRX_UNDO_UPD_EXIST_REC, TRX_UNDO_UPD_DEL_REC, or TRX_UNDO_DEL_MARK_REC; in the last case, only trx id and roll ptr fields are added to the update vector */ dulint trx_id, /* in: transaction id from this undo record */ dulint roll_ptr,/* in: roll pointer from this undo record */ ulint info_bits,/* in: info bits from this undo record */ trx_t* trx, /* in: transaction */ mem_heap_t* heap, /* in: memory heap from which the memory needed is allocated */ upd_t** upd) /* out, own: update vector */{ upd_field_t* upd_field; upd_t* update; ulint n_fields; byte* buf; byte* field; ulint len; ulint field_no; ulint i; ut_a(index->type & DICT_CLUSTERED); if (type != TRX_UNDO_DEL_MARK_REC) { ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields); } else { n_fields = 0; } update = upd_create(n_fields + 2, heap); update->info_bits = info_bits; /* Store first trx id and roll ptr to update vector */ upd_field = upd_get_nth_field(update, n_fields); buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN); trx_write_trx_id(buf, trx_id); upd_field_set_field_no(upd_field, dict_index_get_sys_col_pos(index, DATA_TRX_ID), index, trx); dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); upd_field = upd_get_nth_field(update, n_fields + 1); buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); trx_write_roll_ptr(buf, roll_ptr); upd_field_set_field_no(upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), index, trx); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); /* Store then the updated ordinary columns to the update vector */ for (i = 0; i < n_fields; i++) { ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); if (field_no >= dict_index_get_n_fields(index)) { fprintf(stderr,"InnoDB: Error: trying to access update undo rec field %lu in ", (ulong) field_no); dict_index_name_print(stderr, trx, index); fprintf(stderr, "\n""InnoDB: but index has only %lu fields\n""InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n""InnoDB: Run also CHECK TABLE ", (ulong) dict_index_get_n_fields(index)); ut_print_name(stderr, trx, index->table_name); fprintf(stderr, "\n""InnoDB: n_fields = %lu, i = %lu, ptr %p\n", (ulong) n_fields, (ulong) i, ptr); return(NULL); } ptr = trx_undo_rec_get_col_val(ptr, &field, &len); upd_field = upd_get_nth_field(update, i); upd_field_set_field_no(upd_field, field_no, index, trx); if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) { upd_field->extern_storage = TRUE; len -= UNIV_EXTERN_STORAGE_FIELD; } dfield_set_data(&(upd_field->new_val), field, len); } *upd = update; return(ptr);} /***********************************************************************Builds a partial row from an update undo log record. It contains thecolumns which occur as ordering in any index of the table. */byte*trx_undo_rec_get_partial_row(/*=========================*/ /* out: pointer to remaining part of undo record */ byte* ptr, /* in: remaining part in update undo log record of a suitable type, at the start of the stored index columns; NOTE that this copy of the undo log record must be preserved as long as the partial row is used, as we do NOT copy the data in the record! */ dict_index_t* index, /* in: clustered index */ dtuple_t** row, /* out, own: partial row */ mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */{ dfield_t* dfield; byte* field; ulint len; ulint field_no; ulint col_no; ulint row_len; ulint total_len; byte* start_ptr; ulint i; ut_ad(index && ptr && row && heap); row_len = dict_table_get_n_cols(index->table); *row = dtuple_create(heap, row_len); dict_table_copy_types(*row, index->table); start_ptr = ptr; total_len = mach_read_from_2(ptr); ptr += 2; for (i = 0;; i++) { if (ptr == start_ptr + total_len) { break; } ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); col_no = dict_index_get_nth_col_no(index, field_no); ptr = trx_undo_rec_get_col_val(ptr, &field, &len); dfield = dtuple_get_nth_field(*row, col_no); dfield_set_data(dfield, field, len); } return(ptr);} /***************************************************************************Erases the unused undo log page end. */staticvoidtrx_undo_erase_page_end(/*====================*/ page_t* undo_page, /* in: undo page whose end to erase */ mtr_t* mtr) /* in: mtr */{ ulint first_free;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -