mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
branches/zip: When logging updates or deletes in the undo log, store long
enough prefixes of externally stored columns, so that purge will not have to dereference any BLOB pointers, which may be invalid. This will not be necessary for logging inserts, because inserts are no-ops in purge, and the record will remain locked during transaction rollback. TODO: in dict_build_table_def_step() or dict_build_index_def_step(), prevent the creation of tables with too many columns for which a prefix index is defined. This is because there is a size limit of undo log records, and for each prefix-indexed column, the log must store REC_MAX_INDEX_COL_LEN + BTR_EXTERN_FIELD_REF_SIZE bytes. trx_undo_page_report_insert(): Assert that the index is clustered. trx_undo_page_fetch_ext(): New function, for fetching the BLOB prefix in trx_undo_page_report_modify(). trx_undo_page_report_modify(): Write long enough prefixes of the externally stored columns to the undo log. trx_undo_rec_get_partial_row(): Remove the parameter "ext". Assert that the undo log contains long enough prefixes of the externally stored columns. purge_node_t: Remove the field "ext".
This commit is contained in:
parent
3044ef3523
commit
a65020d27f
4 changed files with 68 additions and 32 deletions
|
@ -65,8 +65,6 @@ struct purge_node_struct{
|
|||
dtuple_t* row; /* NULL, or a copy (also fields copied to
|
||||
heap) of the indexed fields of the row to
|
||||
handle */
|
||||
row_ext_t* ext; /* NULL, or prefixes of the externally
|
||||
stored columns of the row */
|
||||
dict_index_t* index; /* NULL, or the next index whose record should
|
||||
be handled */
|
||||
mem_heap_t* heap; /* memory heap used as auxiliary storage for
|
||||
|
|
|
@ -178,8 +178,6 @@ trx_undo_rec_get_partial_row(
|
|||
record! */
|
||||
dict_index_t* index, /* in: clustered index */
|
||||
dtuple_t** row, /* out, own: partial row */
|
||||
row_ext_t** ext, /* out, own: prefix cache for
|
||||
externally stored columns */
|
||||
mem_heap_t* heap); /* in: memory heap from which the memory
|
||||
needed is allocated */
|
||||
/***************************************************************************
|
||||
|
|
|
@ -337,9 +337,7 @@ row_purge_del_mark(
|
|||
index = node->index;
|
||||
|
||||
/* Build the index entry */
|
||||
entry = row_build_index_entry(node->row,
|
||||
node->ext,
|
||||
index, heap);
|
||||
entry = row_build_index_entry(node->row, NULL, index, heap);
|
||||
ut_a(entry);
|
||||
row_purge_remove_sec_if_poss(node, index, entry);
|
||||
|
||||
|
@ -385,7 +383,7 @@ row_purge_upd_exist_or_extern(
|
|||
if (row_upd_changes_ord_field_binary(NULL, node->index,
|
||||
node->update)) {
|
||||
/* Build the older version of the index entry */
|
||||
entry = row_build_index_entry(node->row, node->ext,
|
||||
entry = row_build_index_entry(node->row, NULL,
|
||||
index, heap);
|
||||
ut_a(entry);
|
||||
row_purge_remove_sec_if_poss(node, index, entry);
|
||||
|
@ -562,9 +560,7 @@ err_exit:
|
|||
|
||||
if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
||||
ptr = trx_undo_rec_get_partial_row(ptr, clust_index,
|
||||
&node->row,
|
||||
&node->ext,
|
||||
node->heap);
|
||||
&node->row, node->heap);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
|
|
@ -202,6 +202,7 @@ trx_undo_page_report_insert(
|
|||
byte* ptr;
|
||||
ulint i;
|
||||
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
|
||||
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT);
|
||||
|
||||
|
@ -402,6 +403,35 @@ trx_undo_rec_skip_row_ref(
|
|||
return(ptr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Fetch a prefix of an externally stored column, for writing to the undo log
|
||||
of an update or delete marking of a clustered index record. */
|
||||
static
|
||||
byte*
|
||||
trx_undo_page_fetch_ext(
|
||||
/*====================*/
|
||||
/* out: ext_buf */
|
||||
byte* ext_buf, /* in: a buffer of
|
||||
REC_MAX_INDEX_COL_LEN
|
||||
+ BTR_EXTERN_FIELD_REF_SIZE */
|
||||
ulint zip_size, /* compressed page size in bytes,
|
||||
or 0 for uncompressed BLOB */
|
||||
const byte* field, /* in: an externally stored column */
|
||||
ulint* len) /* in: length of field;
|
||||
out: used length of ext_buf */
|
||||
{
|
||||
/* Fetch the BLOB. */
|
||||
ulint ext_len = btr_copy_externally_stored_field_prefix(
|
||||
ext_buf, REC_MAX_INDEX_COL_LEN, zip_size, field, *len);
|
||||
ut_a(ext_len);
|
||||
/* Append the BLOB pointer to the prefix. */
|
||||
memcpy(ext_buf + ext_len,
|
||||
field + *len - BTR_EXTERN_FIELD_REF_SIZE,
|
||||
BTR_EXTERN_FIELD_REF_SIZE);
|
||||
*len = ext_len + BTR_EXTERN_FIELD_REF_SIZE;
|
||||
return(ext_buf);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Reports in the undo log of an update or delete marking of a clustered index
|
||||
record. */
|
||||
|
@ -435,6 +465,8 @@ trx_undo_page_report_modify(
|
|||
ulint type_cmpl;
|
||||
byte* type_cmpl_ptr;
|
||||
ulint i;
|
||||
byte ext_buf[REC_MAX_INDEX_COL_LEN
|
||||
+ BTR_EXTERN_FIELD_REF_SIZE];
|
||||
|
||||
ut_a(dict_index_is_clust(index));
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
|
@ -505,7 +537,11 @@ trx_undo_page_report_modify(
|
|||
|
||||
field = rec_get_nth_field(rec, offsets, i, &flen);
|
||||
|
||||
if (trx_undo_left(undo_page, ptr) < 4) {
|
||||
/* The ordering columns must not be stored externally. */
|
||||
ut_ad(!rec_offs_nth_extern(offsets, i));
|
||||
ut_ad(dict_index_get_nth_col(index, i)->ord_part);
|
||||
|
||||
if (trx_undo_left(undo_page, ptr) < 5) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -555,6 +591,18 @@ trx_undo_page_report_modify(
|
|||
}
|
||||
|
||||
if (rec_offs_nth_extern(offsets, pos)) {
|
||||
/* If an ordering field has external
|
||||
storage, we will store a longer
|
||||
prefix of the field. */
|
||||
|
||||
if (dict_index_get_nth_col(index,
|
||||
pos)->ord_part) {
|
||||
field = trx_undo_page_fetch_ext(
|
||||
ext_buf,
|
||||
dict_table_zip_size(table),
|
||||
field, &flen);
|
||||
}
|
||||
|
||||
/* If a field has external storage, we add
|
||||
to flen the flag */
|
||||
|
||||
|
@ -637,6 +685,15 @@ trx_undo_page_report_modify(
|
|||
&flen);
|
||||
|
||||
if (rec_offs_nth_extern(offsets, pos)) {
|
||||
/* If an ordering field has external
|
||||
storage, we will store a longer
|
||||
prefix of the field. */
|
||||
|
||||
field = trx_undo_page_fetch_ext(
|
||||
ext_buf,
|
||||
dict_table_zip_size(table),
|
||||
field, &flen);
|
||||
|
||||
/* If a field has external
|
||||
storage, we add to flen the flag */
|
||||
|
||||
|
@ -884,15 +941,11 @@ trx_undo_rec_get_partial_row(
|
|||
record! */
|
||||
dict_index_t* index, /* in: clustered index */
|
||||
dtuple_t** row, /* out, own: partial row */
|
||||
row_ext_t** ext, /* out, own: prefix cache for
|
||||
externally stored columns */
|
||||
mem_heap_t* heap) /* in: memory heap from which the memory
|
||||
needed is allocated */
|
||||
{
|
||||
const byte* end_ptr;
|
||||
ulint row_len;
|
||||
ulint n_ext_cols;
|
||||
ulint* ext_cols;
|
||||
|
||||
ut_ad(index);
|
||||
ut_ad(ptr);
|
||||
|
@ -901,8 +954,6 @@ trx_undo_rec_get_partial_row(
|
|||
ut_ad(dict_index_is_clust(index));
|
||||
|
||||
row_len = dict_table_get_n_cols(index->table);
|
||||
n_ext_cols = 0;
|
||||
ext_cols = mem_heap_alloc(heap, row_len * sizeof *ext_cols);
|
||||
|
||||
*row = dtuple_create(heap, row_len);
|
||||
|
||||
|
@ -935,23 +986,16 @@ trx_undo_rec_get_partial_row(
|
|||
dfield_set_len(dfield,
|
||||
len - UNIV_EXTERN_STORAGE_FIELD);
|
||||
dfield_set_ext(dfield);
|
||||
if (col->ord_part) {
|
||||
/* We will have to fetch prefixes of
|
||||
externally stored columns that are
|
||||
referenced by column prefixes. */
|
||||
ext_cols[n_ext_cols++] = col_no;
|
||||
}
|
||||
/* If the prefix of this column is indexed,
|
||||
ensure that enough prefix is stored in the
|
||||
undo log record. */
|
||||
ut_a(!col->ord_part
|
||||
|| dfield_get_len(dfield)
|
||||
>= REC_MAX_INDEX_COL_LEN
|
||||
+ BTR_EXTERN_FIELD_REF_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
if (n_ext_cols) {
|
||||
*ext = row_ext_create(n_ext_cols, ext_cols, *row,
|
||||
dict_table_zip_size(index->table),
|
||||
heap);
|
||||
} else {
|
||||
*ext = NULL;
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue