Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-13899

IMPORT TABLESPACE may corrupt ROW_FORMAT=REDUNDANT tables

    XMLWordPrintable

Details

    Description

      This old bug was noticed during MDEV-11369 development.
      The ALTER TABLE…IMPORT TABLESPACE adjustment code that was introduced by WL#5522 in MySQL 5.6 is incorrectly invoking rec_get_status() on a ROW_FORMAT=REDUNDANT record to determine if a record is a leaf page record. The function rec_get_status(rec) is only to be called on ROW_FORMAT=COMPACT, DYNAMIC or COMPRESSED records. The fix is simple:

      diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
      index 1337496b897..ca287b2d0d9 100644
      --- a/storage/innobase/row/row0import.cc
      +++ b/storage/innobase/row/row0import.cc
      @@ -1819,16 +1819,12 @@ PageConverter::update_records(
       
       	m_rec_iter.open(block);
       
      -	while (!m_rec_iter.end()) {
      +	if (!page_is_leaf(block->frame)) {
      +		return DB_SUCCESS;
      +	}
       
      +	while (!m_rec_iter.end()) {
       		rec_t*	rec = m_rec_iter.current();
      -
      -		/* FIXME: Move out of the loop */
      -
      -		if (rec_get_status(rec) == REC_STATUS_NODE_PTR) {
      -			break;
      -		}
      -
       		ibool	deleted = rec_get_deleted_flag(rec, comp);
       
       		/* For the clustered index we have to adjust the BLOB
      

      What is the impact of this bug? As noted in MDEV-13534, the delete-mark flag in node pointer records is basically garbage. If we are unlucky and some node pointer records carry the delete-mark flag, then the IMPORT TABLESPACE could incorrectly delete node pointer records, corrupting the B-tree index.

      Also, we could fail to purge some delete-marked leaf page records for which rec_get_status() happens to return REC_STATUS_NODE_PTR. If this happens in a secondary index, it could trigger MDEV-9663.

      When does rec_get_status(rec)==REC_STATUS_NODE_PTR hold on a ROW_FORMAT=REDUNDANT record? rec_get_status() reads the bits rec[-3]&7:

      			3	1 bit short flag
      				7 bits number of fields
      

      The predicate holds when the number of fields is divisible by 4, and the 'short flag' is set. Note that the number of fields typically differs between node pointer and leaf page records.

      It looks like this regression was introduced in MySQL 5.6.6.

      Attachments

        Issue Links

          Activity

            People

              marko Marko Mäkelä
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.