📄 trx0rec.c
字号:
/******************************************************Transaction undo log record(c) 1996 Innobase OyCreated 3/26/1996 Heikki Tuuri*******************************************************/#include "trx0rec.h"#ifdef UNIV_NONINL#include "trx0rec.ic"#endif#include "fsp0fsp.h"#include "mach0data.h"#include "trx0rseg.h"#include "trx0trx.h"#include "trx0undo.h"#include "dict0dict.h"#include "ut0mem.h"#include "row0upd.h"#include "que0que.h"#include "trx0purge.h"#include "row0row.h"/*=========== UNDO LOG RECORD CREATION AND DECODING ====================*//**************************************************************************Writes the mtr log entry of the inserted undo log record on the undo logpage. */UNIV_INLINEvoidtrx_undof_page_add_undo_rec_log(/*============================*/ page_t* undo_page, /* in: undo log page */ ulint old_free, /* in: start offset of the inserted entry */ ulint new_free, /* in: end offset of the entry */ mtr_t* mtr) /* in: mtr */{ byte* log_ptr; const byte* log_end; ulint len; log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN); if (log_ptr == NULL) { return; } log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN]; log_ptr = mlog_write_initial_log_record_fast(undo_page, MLOG_UNDO_INSERT, log_ptr, mtr); len = new_free - old_free - 4; mach_write_to_2(log_ptr, len); log_ptr += 2; if (log_ptr + len <= log_end) { memcpy(log_ptr, undo_page + old_free + 2, len); mlog_close(mtr, log_ptr + len); } else { mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, undo_page + old_free + 2, len); }} /***************************************************************Parses a redo log record of adding an undo log record. */byte*trx_undo_parse_add_undo_rec(/*========================*/ /* out: end of log record or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ page_t* page) /* in: page or NULL */{ ulint len; byte* rec; ulint first_free; if (end_ptr < ptr + 2) { return(NULL); } len = mach_read_from_2(ptr); ptr += 2; if (end_ptr < ptr + len) { return(NULL); } if (page == NULL) { return(ptr + len); } first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); rec = page + first_free; mach_write_to_2(rec, first_free + 4 + len); mach_write_to_2(rec + 2 + len, first_free); mach_write_to_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, first_free + 4 + len); ut_memcpy(rec + 2, ptr, len); return(ptr + len);} /**************************************************************************Calculates the free space left for extending an undo log record. */UNIV_INLINEulinttrx_undo_left(/*==========*/ /* out: bytes left */ page_t* page, /* in: undo log page */ byte* ptr) /* in: pointer to page */{ /* The '- 10' is a safety margin, in case we have some small calculation error below */ return(UNIV_PAGE_SIZE - (ptr - page) - 10 - FIL_PAGE_DATA_END);}/**************************************************************************Reports in the undo log of an insert of a clustered index record. */staticulinttrx_undo_page_report_insert(/*========================*/ /* out: offset of the inserted entry on the page if succeed, 0 if fail */ page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index */ dtuple_t* clust_entry, /* in: index entry which will be inserted to the clustered index */ mtr_t* mtr) /* in: mtr */{ ulint first_free; byte* ptr; ulint len; dfield_t* field; ulint flen; ulint i; ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT); first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 30) { /* NOTE: the value 30 must be big enough such that the general fields written below fit on the undo log page */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ mach_write_to_1(ptr, TRX_UNDO_INSERT_REC); ptr++; len = mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += len; len = mach_dulint_write_much_compressed(ptr, (index->table)->id); ptr += len; /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record to be inserted in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { field = dtuple_get_nth_field(clust_entry, i); flen = dfield_get_len(field); 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, dfield_get_data(field), flen); ptr += flen; } } if (trx_undo_left(undo_page, ptr) < 2) { return(0); } /*----------------------------------------*/ /* 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 the log entry to the REDO log of 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 record the general parameters. */byte*trx_undo_rec_get_pars(/*==================*/ /* out: remaining part of undo log record after reading these values */ trx_undo_rec_t* undo_rec, /* in: undo log record */ ulint* type, /* out: undo record type: TRX_UNDO_INSERT_REC, ... */ ulint* cmpl_info, /* out: compiler info, relevant only for update type records */ ibool* updated_extern, /* out: TRUE if we updated an externally stored fild */ dulint* undo_no, /* out: undo log record number */ dulint* table_id) /* out: table id */{ byte* ptr; ulint len; ulint type_cmpl; ptr = undo_rec + 2; type_cmpl = mach_read_from_1(ptr); ptr++; if (type_cmpl & TRX_UNDO_UPD_EXTERN) { *updated_extern = TRUE; type_cmpl -= TRX_UNDO_UPD_EXTERN; } else { *updated_extern = FALSE; } *type = type_cmpl & (TRX_UNDO_CMPL_INFO_MULT - 1); *cmpl_info = type_cmpl / TRX_UNDO_CMPL_INFO_MULT; *undo_no = mach_dulint_read_much_compressed(ptr); len = mach_dulint_get_much_compressed_size(*undo_no); ptr += len; *table_id = mach_dulint_read_much_compressed(ptr); len = mach_dulint_get_much_compressed_size(*table_id); ptr += len; return(ptr);}/**************************************************************************Reads from an undo log record a stored column value. */staticbyte*trx_undo_rec_get_col_val(/*=====================*/ /* out: remaining part of undo log record after reading these values */ byte* ptr, /* in: pointer to remaining part of undo log record */ byte** field, /* out: pointer to stored field */ ulint* len) /* out: length of the field, or UNIV_SQL_NULL */{ *len = mach_read_compressed(ptr); ptr += mach_get_compressed_size(*len); *field = ptr; if (*len != UNIV_SQL_NULL) { if (*len >= UNIV_EXTERN_STORAGE_FIELD) { ptr += (*len - UNIV_EXTERN_STORAGE_FIELD); } else { ptr += *len; } } return(ptr);}/***********************************************************************Builds a row reference from an undo log record. */byte*trx_undo_rec_get_row_ref(/*=====================*/ /* out: pointer to remaining part of undo record */ byte* ptr, /* in: remaining part of a copy of an undo log record, at the start of the row reference; NOTE that this copy of the undo log record must be preserved as long as the row reference is used, as we do NOT copy the data in the record! */ dict_index_t* index, /* in: clustered index */ dtuple_t** ref, /* out, own: row reference */ mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */{ dfield_t* dfield; byte* field; ulint len; ulint ref_len; ulint i; ut_ad(index && ptr && ref && heap); ut_a(index->type & DICT_CLUSTERED); ref_len = dict_index_get_n_unique(index); *ref = dtuple_create(heap, ref_len); dict_index_copy_types(*ref, index, ref_len); for (i = 0; i < ref_len; i++) { dfield = dtuple_get_nth_field(*ref, i); ptr = trx_undo_rec_get_col_val(ptr, &field, &len); dfield_set_data(dfield, field, len); } return(ptr);} /***********************************************************************Skips a row reference from an undo log record. */byte*trx_undo_rec_skip_row_ref(/*======================*/ /* out: pointer to remaining part of undo record */ byte* ptr, /* in: remaining part in update undo log record, at the start of the row reference */ dict_index_t* index) /* in: clustered index */{ byte* field; ulint len; ulint ref_len; ulint i; ut_ad(index && ptr); ut_a(index->type & DICT_CLUSTERED); ref_len = dict_index_get_n_unique(index); for (i = 0; i < ref_len; i++) { ptr = trx_undo_rec_get_col_val(ptr, &field, &len); } return(ptr);} /**************************************************************************Reports in the undo log of an update or delete marking of a clustered indexrecord. */staticulinttrx_undo_page_report_modify(/*========================*/ /* out: byte offset of the inserted undo log entry on the page if succeed, 0 if fail */ page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index where update or delete marking is done */ rec_t* rec, /* in: clustered index record which has NOT yet been modified */ const ulint* offsets, /* in: rec_get_offsets(rec, index) */ upd_t* update, /* in: update vector which tells the columns to be updated; in the case of a delete, this should be set to NULL */ ulint cmpl_info, /* in: compiler info on secondary index updates */ mtr_t* mtr) /* in: mtr */{ dict_table_t* table; upd_field_t* upd_field; dict_col_t* col; ulint first_free; byte* ptr; ulint len; byte* field; ulint flen; ulint pos; dulint roll_ptr; dulint trx_id; ulint bits; ulint col_no; byte* old_ptr; ulint type_cmpl; byte* type_cmpl_ptr; ulint i; ut_a(index->type & DICT_CLUSTERED); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); table = index->table; first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 50) { /* NOTE: the value 50 must be big enough so that the general fields written below fit on the undo log page */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ if (update) { if (rec_get_deleted_flag(rec, table->comp)) { type_cmpl = TRX_UNDO_UPD_DEL_REC; } else { type_cmpl = TRX_UNDO_UPD_EXIST_REC; } } else { type_cmpl = TRX_UNDO_DEL_MARK_REC; } type_cmpl = type_cmpl | (cmpl_info * TRX_UNDO_CMPL_INFO_MULT); mach_write_to_1(ptr, type_cmpl); type_cmpl_ptr = ptr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -