Commit bbcdac2c authored by marko's avatar marko

branches/zip: Fix the decompression of deleted records containing externally

stored columns.

page_zip_decompress(): We indeed need to clear the BLOB pointers of deleted
records twice.  This implies that we also need to invoke rec_get_offsets()
twice for each record on a leaf page.  Add clarifying comments.

page_zip_clear_rec(): Add the flag page_zip_clear_rec_disable for
disabling the clearing of deleted records.
parent 8ebc2719
...@@ -1762,12 +1762,19 @@ page_zip_decompress_low( ...@@ -1762,12 +1762,19 @@ page_zip_decompress_low(
goto zlib_error; goto zlib_error;
} }
/* Skip the BLOB pointer in case /* Clear the BLOB pointer in case
the record was deleted. The BLOB the record will be deleted and the
pointers will be initialized space will not be reused. Note that
(copied from "externs" or cleared) the final initialization of the BLOB
pointers (copying from "externs"
or clearing) will have to take place
only after the page modification log only after the page modification log
has been applied. */ has been applied. Otherwise, we
could end up with an uninitialized
BLOB pointer when a record is deleted,
reallocated and deleted. */
memset(d_stream.next_out, 0,
BTR_EXTERN_FIELD_REF_SIZE);
d_stream.next_out d_stream.next_out
+= BTR_EXTERN_FIELD_REF_SIZE; += BTR_EXTERN_FIELD_REF_SIZE;
} }
...@@ -1905,10 +1912,10 @@ page_zip_decompress_low( ...@@ -1905,10 +1912,10 @@ page_zip_decompress_low(
ibool exists = !page_zip_dir_find_free( ibool exists = !page_zip_dir_find_free(
page_zip, ut_align_offset( page_zip, ut_align_offset(
rec, UNIV_PAGE_SIZE)); rec, UNIV_PAGE_SIZE));
if (UNIV_UNLIKELY(trx_id_col != ULINT_UNDEFINED)) { offsets = rec_get_offsets(rec, index, offsets,
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
ULINT_UNDEFINED, &heap);
if (UNIV_UNLIKELY(trx_id_col != ULINT_UNDEFINED)) {
dst = rec_get_nth_field(rec, offsets, dst = rec_get_nth_field(rec, offsets,
trx_id_col, &len); trx_id_col, &len);
ut_ad(len >= DATA_TRX_ID_LEN ut_ad(len >= DATA_TRX_ID_LEN
...@@ -1916,21 +1923,12 @@ page_zip_decompress_low( ...@@ -1916,21 +1923,12 @@ page_zip_decompress_low(
storage -= DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; storage -= DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
memcpy(dst, storage, memcpy(dst, storage,
DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
if (UNIV_UNLIKELY(!exists)) {
continue;
}
} else if (UNIV_LIKELY(exists)) {
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
} else {
continue;
} }
/* Check if there are any externally stored /* Check if there are any externally stored
columns in this existing (not deleted) columns in this record. For each externally
record. For each externally stored column, stored column, restore or clear the
restore or clear the BTR_EXTERN_FIELD_REF. */ BTR_EXTERN_FIELD_REF. */
for (i = 0; i < rec_offs_n_fields(offsets); i++) { for (i = 0; i < rec_offs_n_fields(offsets); i++) {
if (!rec_offs_nth_extern(offsets, i)) { if (!rec_offs_nth_extern(offsets, i)) {
...@@ -1941,6 +1939,8 @@ page_zip_decompress_low( ...@@ -1941,6 +1939,8 @@ page_zip_decompress_low(
dst += len - BTR_EXTERN_FIELD_REF_SIZE; dst += len - BTR_EXTERN_FIELD_REF_SIZE;
if (UNIV_LIKELY(exists)) { if (UNIV_LIKELY(exists)) {
/* Existing record:
restore the BLOB pointer */
externs -= BTR_EXTERN_FIELD_REF_SIZE; externs -= BTR_EXTERN_FIELD_REF_SIZE;
memcpy(dst, externs, memcpy(dst, externs,
...@@ -1948,6 +1948,8 @@ page_zip_decompress_low( ...@@ -1948,6 +1948,8 @@ page_zip_decompress_low(
page_zip->n_blobs++; page_zip->n_blobs++;
} else { } else {
/* Deleted record:
clear the BLOB pointer */
memset(dst, 0, memset(dst, 0,
BTR_EXTERN_FIELD_REF_SIZE); BTR_EXTERN_FIELD_REF_SIZE);
} }
...@@ -2672,6 +2674,13 @@ page_zip_write_trx_id_and_roll_ptr( ...@@ -2672,6 +2674,13 @@ page_zip_write_trx_id_and_roll_ptr(
memcpy(storage, field, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); memcpy(storage, field, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
} }
#ifdef UNIV_ZIP_DEBUG
/* Set this variable in a debugger to disable page_zip_clear_rec().
The only observable effect should be the compression ratio due to
deleted records not being zeroed out. */
ibool page_zip_clear_rec_disable;
#endif /* UNIV_ZIP_DEBUG */
/************************************************************************** /**************************************************************************
Clear an area on the uncompressed and compressed page, if possible. */ Clear an area on the uncompressed and compressed page, if possible. */
static static
...@@ -2697,7 +2706,11 @@ page_zip_clear_rec( ...@@ -2697,7 +2706,11 @@ page_zip_clear_rec(
heap_no = rec_get_heap_no_new(rec); heap_no = rec_get_heap_no_new(rec);
ut_ad(heap_no >= 2); /* exclude infimum and supremum */ ut_ad(heap_no >= 2); /* exclude infimum and supremum */
if (page_zip->m_end if (
#ifdef UNIV_ZIP_DEBUG
!page_zip_clear_rec_disable &&
#endif /* UNIV_ZIP_DEBUG */
page_zip->m_end
+ 1 + ((heap_no - 1) >= 64)/* size of the log entry */ + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
+ page_zip_get_trailer_len(page_zip, index, NULL) + page_zip_get_trailer_len(page_zip, index, NULL)
< page_zip->size) { < page_zip->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