Skip to content

mysql-5.7.23

              TO VARCHAR(40) INSTANTANEOUSLY

Analysis
========

Indexed VARCHAR columns are not expanded instantaneously (without index rebuild)for
InnoDB tables using INPLACE algorithm. The other problems uncovered as part of this
bug are:
a) Indexed VARCHAR columns when converted from unpacked
   keys to packed keys(key size > 8 bytes) by expanding
   the VARCHAR column was not instantaneous for InnoDB
   tables using INPLACE algorithm even though pack keys
   is a no-op for InnoDB tables.
b) CREATE/ALTER of InnoDB tables where the index size
   exceeds the SE limit of 767 bytes for COMPACT or
   REDUNDANT row_format did not report error in STRICT
   mode and warning in non-strict mode.

SQL layer determines if there has been a change in index definition and sets the
appropriate handler flags which helps the SE to determine whether a index rebuild
needs to be performed. The 'has_index_def_changed()' did not check if the change
in length had a compatible packed data representation and marked it as a change in
index by setting the handler flags DROP_INDEX and ADD_INDEX triggering a recreation
of indexes in InnoDB.

When 'PACK_KEYS' option is not specified, indexes on columns with string types are
marked for packing through HA_PACK_KEY. Currently only MyISAM engine supports it.
Indexes on columns with length greater than 8 bytes were marked for packing
irrespective of the storage engine. Converting the indexes from non-packed to packed
i.e expanding the varchar column from lesser than 8 chars to more than 8 chars using
ALTER was marked as a change in index definition during the check in
'has_index_def_changed()' even though InnoDB does not support packed keys.

The handler API ha_innobase::max_supported_key_part_length() returned an incorrect
maximum support key part length since the row format of the table was not taken into
account. Hence creation of tables using REDUNDANT/COMPACT row format with index size
exceeding the SE limit were allowed.

Fix:
===
a) A new handler flag 'Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH"
   is introduced. This is set in 'has_index_def_changed()' when the
   index length differs due to column modification and has compatible
   packed data representation while determining if the index definition
   has changed.

b) Introduced a handlerton flag 'HTON_SUPPORTS_PACKED_KEYS' to check for
   'PACK_KEYS' support which is currently set for MyISAM engine since it
   is the only engine which supports packed keys. The 'HTON_SUPPORTS_PACKED_KEYS'
   is checked prior to setting the index flag 'HA_BINARY_PACK_KEY' for packed keys.
   Hence for InnoDB the packed key flag for indexes is not set.

c) The handler API max_supported_key_part_length() has been modified to take 'create_info'
   as a parameter from which the row_format can be fetched and appropriate index limit can
   be computed and returned by the InnoDB implementation of the handler API. More details
   on the behavior is mentioned in the table below.

   - Since the index limit is computed correctly and checked at the SQL layer,
     the error message 'ER_TOO_LONG_KEY' is reported at the SQL layer instead of
     'ER_INDEX_COLUMN_TOO_LONG' (which was reported by the handler interface
     after mapping the error returned by SE).
   - For COMPACT and REDUNDANT row format, when the index size exceeds 767 bytes,
     a warning is reported in non-STRICT mode and the index is truncated to fit
     767 bytes. In a STRICT mode, an error is reported.

This table describes the behavior of INDEX limit, Type of INDEX and
behavior under STRICT and NON_STRICT mode.
IL===> Index Limit.
-------------------------------------------------------------------------------|
  Row Format          |INDEX LIMIT | STRICT MODE(>IL) | NON-STRICT MODE(>IL)   |
----------------------|--------------------------------------------------------|
Compact/Redundant     |  767 bytes |    Error         | Index truncation(767)  |
(Non Unique Index)    |            |                  | and warning.           |
--------------------------------------------------------------------------------
Compact/Redundant     |  767 bytes |    Error         | Error                  |
(Unique/Primary Index)|            |                  |                        |
--------------------------------------------------------------------------------
Dynamic/Compressed    |  3072 byes |    Error         | Index truncation(3072) |
(Non Unique Index)    |            |                  | and warning            |
--------------------------------------------------------------------------------
Dynamic/Compressed    |  3072 bytes|    Error         | Error                  |
(Unique/Primary Index)|            |                  |                        |
--------------------------------------------------------------------------------

(cherry picked from commit bdc97b75674ade0251bdbc3ea2dc7d36871f73cd)
Assets 2
Loading