Bug #19217 dict_load_indexes() may read the delete-mark incorrectly
Submitted: 20 Apr 2006 13:52 Modified: 27 Apr 2006 15:09
Reporter: Marko Mäkelä
Status: Closed
Category:Server: InnoDB Severity:S2 (Serious)
Version:5.0.3 and later OS:Any (all)
Assigned to: Marko Mäkelä Target Version:

[20 Apr 2006 13:52] Marko Mäkelä
Description:
The InnoDB system tables are in ROW_FORMAT=REDUNDANT format. However, the function
dict_load_indexes() will pass the wrong format flag to rec_get_deleted_flag() when
attempting to load indexes belonging to a ROW_FORMAT=COMPACT table.

How to repeat:
It is unsure if this bug can manifest itself. It appears as if the bit would always read
as '0' for ROW_FORMAT=COMPACT tables. It might be that the records in SYS_INDEXES never
are delete-marked in the current version of MySQL/InnoDB.

The bug was found when trying to implement fast index creation (smart ALTER TABLE).

Suggested fix:
Pass the "compact format" flag as 0.
[20 Apr 2006 16:52] Heikki Tuuri
Marko,

I think the bug does not manifest itself in < InnoDB-5.2.

When a table is altered in those earlier versions, a new table id and index ids are
assigned to it. I do not see how load_table could scan a delete-marked record. There are
assertions in InnoDB-5.0 that specifically say that the records cannot be delete-marked.
Jan had to remove those assertions in 5.2 to get new CREATE INDEX to work.

Regards,

Heikki
[21 Apr 2006 2:26] Heikki Tuuri
Marko,

after second thought, this could affect 5.0, too. If it reads the delete mark from a
wrong location then it could see it as 1, and our assertions would fail.

Regards,

Heikki
[21 Apr 2006 9:15] Marko Mäkelä
Like I wrote in the original report, the bit is very likely read as '0'. When read from
the wrong location, it would be read from one of the most significant bits of heap_no,
which should always be 0, given the minimum record size of SYS_INDEXES.
[21 Apr 2006 10:18] Heikki Tuuri
The patch:

dict0load.c:
>>> @@ -617,7 +617,7 @@
>>>              break;
>>>          }
>>>
>>> -        if (rec_get_deleted_flag(rec, table->comp)) {
>>> +        if (rec_get_deleted_flag(rec, 0)) {
>>>              dict_load_report_deleted_index(table->name,
>>>                  ULINT_UNDEFINED);
[21 Apr 2006 11:00] Marko Mäkelä
The patch has been committed to the InnoDB Subversion repositories and will be shipped to
MySQL AB shortly.
[25 Apr 2006 21:42] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/5506
[25 Apr 2006 21:58] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/5508
[25 Apr 2006 22:37] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/5511
[26 Apr 2006 8:57] Alexander Ivanov
Fixed in 5.0.22 and 5.1.10-beta.
[27 Apr 2006 15:09] Paul DuBois
Noted in 5.0.21 (it was merged into 5.0.21), 5.1.10 changelogs.