Commit e0ce800f authored by inaam's avatar inaam

branches/zip issue# 33

This fix makes two basic changes in blob handling:
(The bug was introduced in r2252)

1) The blob prefixes are no longer stored in the undo if
  a) We are modifying a delete marked record and
  b) The record was delete marked by an already committed trx.

2) When building old row version to check if one of these versions
can hold an implicit lock on the record we stop our probe if
  a) The version is delete marked and
  b) The delete marking is done by a trx which is different from
     the current active trx on the record.

Reviewed by: Heikki
parent 131eb3b2
......@@ -178,6 +178,9 @@ trx_undo_rec_get_partial_row(
record! */
dict_index_t* index, /* in: clustered index */
dtuple_t** row, /* out, own: partial row */
ibool ignore_prefix, /* in: flag to indicate if we
expect blob prefixes in undo. Used
only in the assertion. */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/***************************************************************************
......
......@@ -559,8 +559,10 @@ err_exit:
/* Read to the partial row the fields that occur in indexes */
if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
ptr = trx_undo_rec_get_partial_row(ptr, clust_index,
&node->row, node->heap);
ptr = trx_undo_rec_get_partial_row(
ptr, clust_index, &node->row,
type == TRX_UNDO_UPD_DEL_REC,
node->heap);
}
return(TRUE);
......
......@@ -163,6 +163,26 @@ row_vers_impl_x_locked_off_kernel(
clust_offsets = rec_get_offsets(
prev_version, clust_index, NULL,
ULINT_UNDEFINED, &heap);
vers_del = rec_get_deleted_flag(prev_version,
comp);
prev_trx_id = row_get_rec_trx_id(prev_version,
clust_index,
clust_offsets);
/* If the trx_id and prev_trx_id are
different and if the prev_version is marked
deleted then the prev_trx_id must have
already committed for the trx_id to be able to
modify the row. Therefore, prev_trx_id cannot
hold any implicit lock. */
if (0 != ut_dulint_cmp(trx_id, prev_trx_id)
&& vers_del) {
mutex_enter(&kernel_mutex);
break;
}
/* The stack of versions is locked by mtr.
Thus, it is safe to fetch the prefixes for
externally stored columns. */
......@@ -206,8 +226,6 @@ row_vers_impl_x_locked_off_kernel(
if prev_version would require rec to be in a different
state. */
vers_del = rec_get_deleted_flag(prev_version, comp);
/* We check if entry and rec are identified in the alphabetical
ordering */
if (0 == cmp_dtuple_rec(entry, rec, offsets)) {
......@@ -243,9 +261,6 @@ row_vers_impl_x_locked_off_kernel(
break;
}
prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
clust_offsets);
if (0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
/* The versions modified by the trx_id transaction end
to prev_version: no implicit x-lock */
......
......@@ -533,6 +533,8 @@ trx_undo_page_report_modify(
ulint type_cmpl;
byte* type_cmpl_ptr;
ulint i;
dulint trx_id;
ibool ignore_prefix = FALSE;
byte ext_buf[REC_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE];
......@@ -565,6 +567,11 @@ trx_undo_page_report_modify(
type_cmpl = TRX_UNDO_DEL_MARK_REC;
} else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) {
type_cmpl = TRX_UNDO_UPD_DEL_REC;
/* We are about to update a delete marked record.
We don't typically need the prefix in this case unless
the delete marking is done by the same transaction
(which we check below). */
ignore_prefix = TRUE;
} else {
type_cmpl = TRX_UNDO_UPD_EXIST_REC;
}
......@@ -588,7 +595,16 @@ trx_undo_page_report_modify(
index, DATA_TRX_ID), &flen);
ut_ad(flen == DATA_TRX_ID_LEN);
ptr += mach_dulint_write_compressed(ptr, trx_read_trx_id(field));
trx_id = trx_read_trx_id(field);
/* If it is an update of a delete marked record, then we are
allowed to ignore blob prefixes if the delete marking was done
by some other trx as it must have committed by now for us to
allow an over-write. */
if (ignore_prefix) {
ignore_prefix = ut_dulint_cmp(trx_id, trx->id) != 0;
}
ptr += mach_dulint_write_compressed(ptr, trx_id);
field = rec_get_nth_field(rec, offsets,
dict_index_get_sys_col_pos(
......@@ -663,6 +679,7 @@ trx_undo_page_report_modify(
ptr,
dict_index_get_nth_col(index, pos)
->ord_part
&& !ignore_prefix
&& flen < REC_MAX_INDEX_COL_LEN
? ext_buf : NULL,
dict_table_zip_size(table),
......@@ -746,6 +763,7 @@ trx_undo_page_report_modify(
ptr = trx_undo_page_report_modify_ext(
ptr,
flen < REC_MAX_INDEX_COL_LEN
&& !ignore_prefix
? ext_buf : NULL,
dict_table_zip_size(table),
&field, &flen);
......@@ -996,6 +1014,9 @@ trx_undo_rec_get_partial_row(
record! */
dict_index_t* index, /* in: clustered index */
dtuple_t** row, /* out, own: partial row */
ibool ignore_prefix, /* in: flag to indicate if we
expect blob prefixes in undo. Used
only in the assertion. */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
{
......@@ -1045,7 +1066,8 @@ trx_undo_rec_get_partial_row(
/* If the prefix of this column is indexed,
ensure that enough prefix is stored in the
undo log record. */
ut_a(!col->ord_part
ut_a(ignore_prefix
|| !col->ord_part
|| dfield_get_len(dfield)
>= REC_MAX_INDEX_COL_LEN
+ BTR_EXTERN_FIELD_REF_SIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment