diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2010-11-02 09:28:48 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2010-11-02 09:28:48 +0200 |
commit | 004bb1b15ebbf4efe996d04c4bb95a235a718c62 (patch) | |
tree | 454e099d4ae96b242006e3d162678846ccfc0ab6 /storage | |
parent | 6c802b3c4307580a3387a5a8fcd29a0656fa4177 (diff) | |
download | mariadb-git-004bb1b15ebbf4efe996d04c4bb95a235a718c62.tar.gz |
Bug#57799 READ UNCOMMITTED access failure of off-page DYNAMIC or COMPRESSED
columns again
This is follow-up to Bug #54358. Not all occurrences of the bug were fixed.
We need to check all calls to btr_copy_externally_stored_field_prefix_low()
and do the right thing when the pointer to the off-page column is null
(full of zero bytes).
It turns out that only the call to btr_copy_externally_stored_field_prefix()
in row_sel_sec_rec_is_for_blob() needs to be changed.
For fetching complete off-page columns rather than prefixes, the function
btr_rec_copy_externally_stored_field() already checks if the pointer
is null (all-zero). Two of its callers (row_merge_copy_blobs() and
row_sel_fetch_columns()) are never executed as READ COMMITTED and can
rightfully assert that the fetch succeeded. The third caller,
row_sel_store_mysql_rec(), already does the right thing.
The calls in row_upd_ext_fetch() and trx_undo_page_fetch_ext() must
expect that the off-page column exists. Update and rollback are
locking operations, never READ UNCOMMITTED.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innodb_plugin/ChangeLog | 6 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0sel.c | 12 |
2 files changed, 18 insertions, 0 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 1be14034be4..3792d48e5f2 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-11-02 The InnoDB Team + + * row/row0sel.c: + Fix Bug#57799 READ UNCOMMITTED access failure of off-page + DYNAMIC or COMPRESSED columns again + 2010-10-24 The InnoDB Team * row/row0mysql.c diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index ac78a95839c..423ddfade22 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -106,6 +106,18 @@ row_sel_sec_rec_is_for_blob( ulint len; byte buf[DICT_MAX_INDEX_COL_LEN]; + ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE); + + if (UNIV_UNLIKELY + (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE, + field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE))) { + /* The externally stored field was not written yet. + This record should only be seen by + recv_recovery_rollback_active() or any + TRX_ISO_READ_UNCOMMITTED transactions. */ + return(FALSE); + } + len = btr_copy_externally_stored_field_prefix(buf, sizeof buf, zip_size, clust_field, clust_len); |