Bug #8552 CHECKSUM TABLE is broken in InnoDB
Submitted: 16 Feb 2005 16:37 Modified: 10 Aug 2006 21:04
Reporter: Sergei Golubchik Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:5.0 OS:
Assigned to: Osku Salerma CPU Architecture:Any

[16 Feb 2005 16:37] Sergei Golubchik
Description:
CHECKSUM TABLE tt;

returns different results depending on whether
1, table is MyISAM or InnoDB
2. in MyISAM - whether checksum is live or calculated
(because of true varchars)

it should not be the case (and it was not).

How to repeat:
see innodb.results
[16 Feb 2005 16:45] Heikki Tuuri
Sergei,

in which version is this?

Sergey Petrunia changed the checksum calculation in InnoDB in 5.0 because of the ROR, but he should have rolled back those changes by now.

Regards,

Heikki
[16 Feb 2005 17:33] Sergei Golubchik
5.0 (sorry for this)
I believe it's mostly because of true varchars, not ROR code
[24 Feb 2005 5:51] Brian Aker
Assigned it to you Heikki, based on Serg's feedback. Once you have the new varchar support we can see if this goes away.
[28 Feb 2005 12:13] Sergei Golubchik
MyISAM part of a bug moved to a http://bugs.mysql.com/8841
[2 Mar 2006 16:39] Heikki Tuuri
Ingo has now fixed the MyISAM part of this bug:

http://lists.mysql.com/commits/2012

Reverting the below patch may also help in fixing this:

ChangeSet
  1.1703 04/12/03 14:25:07 serg...@mysql.com +3 -0
  Fix and testcase for BUG#5401

  mysql-test/t/index_merge_innodb.test
    1.4 04/12/03 14:23:43 serg...@mysql.com +24 -0
    Test for BUG#5401

  mysql-test/r/index_merge_innodb.result
    1.6 04/12/03 14:23:43 serg...@mysql.com +20 -0
    Test for BUG#5401

  innobase/row/row0sel.c
    1.58 04/12/03 14:23:43 serg...@mysql.com +2 -5
    Fix for BUG#5401: Don't reset the entire NULL mask, only set/clear bits for particular fields.
      This is necessary because index_merge ROR-intersection uses simulatenous scans on several keys
      with the same row buffer.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: sergefp
# Host: psergey.(none)
# Root: /dbdata/psergey/mysql-5.0-bug5401

--- 1.57/innobase/row/row0sel.c Tue Nov 30 20:58:12 2004
+++ 1.58/innobase/row/row0sel.c Fri Dec  3 14:23:43 2004
@@ -2255,11 +2255,6 @@
                prebuilt->blob_heap = NULL;
        }

-       /* MySQL assumes that all columns have the SQL NULL bit set unless it
-       is a nullable column with a non-NULL value */
-
-       memset(mysql_rec, 0xFF, prebuilt->null_bitmap_len);
-
        for (i = 0; i < prebuilt->n_template; i++) {

Regards,

Heikki
[28 Jul 2006 21:16] Heikki Tuuri
Osku,

are you waiting for feedback from Sergei?

Regards,

Heikki
[2 Aug 2006 7:25] Heikki Tuuri
Assigning this to Sunny.

I need to ask the sysadmin to create a bugs.mysql.com account for Sunny.
[8 Aug 2006 7:20] Heikki Tuuri
It may be that MySQL AB has fixed this bug meanwhile. Sunny is investigating this.
[10 Aug 2006 21:04] Heikki Tuuri
This was probably fixed by MySQL AB in sql_table.cc.

The code below seems to leave unused SQL NULL bits and unused bytes in BLOB and VARCHAR out of the checksum calculation. If the checksum is calculated from the actual data content of the row, the problems we had previously are solved.

Thus, this was fixed in February 2006 by Ingo.

          for (;;)
          {
            ha_checksum row_crc= 0;
            int error= t->file->rnd_next(t->record[0]);
            if (unlikely(error))
            {
              if (error == HA_ERR_RECORD_DELETED)
                continue;
              break;
            }
            if (t->s->null_bytes)
            {
              /* fix undefined null bits */
              t->record[0][t->s->null_bytes-1] |= null_mask;
              if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
                t->record[0][0] |= 1;

              row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
            }

            for (uint i= 0; i < t->s->fields; i++ )
            {
              Field *f= t->field[i];
              if ((f->type() == FIELD_TYPE_BLOB) ||
                  (f->type() == MYSQL_TYPE_VARCHAR))
              {
                String tmp;
                f->val_str(&tmp);
                row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length());
              }
              else
                row_crc= my_checksum(row_crc, (byte*) f->ptr,
                                     f->pack_length());
            }

            crc+= row_crc;
          }
          protocol->store((ulonglong)crc);
          t->file->ha_rnd_end();
        }