stonedb icon indicating copy to clipboard operation
stonedb copied to clipboard

bug: pecified key was too long; max key length is 255 bytes(innodb does not report errors)

Open shangyanwen opened this issue 1 year ago • 1 comments

Describe the problem

create table t1 (
  a varchar(112) charset utf8 collate utf8_bin not null,
  primary key (a)
) select 'test' as a ;

ERROR 1071 (42000): Specified key was too long; max key length is 255 bytes

Expected behavior

create table t1 (
  a varchar(112) charset utf8 collate utf8_bin not null,
  primary key (a)
) select 'test' as a ;

How To Reproduce

Can be created without error

Environment

  1. StoneDB for mysql5.7(release)
  2. Ubuntu 20.04.4

Are you interested in submitting a PR to solve the problem?

  • [ ] Yes, I will!

shangyanwen avatar Jul 18 '22 06:07 shangyanwen

I think we should check the length in primary key just innodb does.

hustjieke avatar Jul 24 '22 15:07 hustjieke

ACK

lujiashun avatar Sep 06 '22 06:09 lujiashun

it seems the function handler::max_supported_key_part_length results in the difference . innodb inherit the function,while tianmu/stonedb enginer didn't.

lujiashun avatar Sep 06 '22 10:09 lujiashun

  1. in myrocks5.6,storage\rocksdb\ha_rocksdb.cc
uint ha_rocksdb::max_supported_key_part_length() const {
  DBUG_ENTER_FUNC();
  DBUG_RETURN(rocksdb_large_prefix ? MAX_INDEX_COL_LEN_LARGE 
                                   : MAX_INDEX_COL_LEN_SMALL);
}

#define MAX_INDEX_COL_LEN_LARGE 3072 #define MAX_INDEX_COL_LEN_SMALL 767 rocksdb_large_prefix default value is 0

  1. in innodb, the function is :
uint
ha_innobase::max_supported_key_part_length(HA_CREATE_INFO *create_info) const
/*==============================================*/
{
	/* A table format specific index column length check will be performed
	at ha_innobase::add_index() and row_create_index_for_mysql() */
	switch (create_info->row_type) {
	case ROW_TYPE_REDUNDANT:
	case ROW_TYPE_COMPACT:
		return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
		break;
	default:
		if (innobase_large_prefix)
			return (REC_VERSION_56_MAX_INDEX_COL_LEN);
		else
			return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
	}

}

#define REC_ANTELOPE_MAX_INDEX_COL_LEN 768 #define REC_VERSION_56_MAX_INDEX_COL_LEN 3072 #define REC_ANTELOPE_MAX_INDEX_COL_LEN 768

  1. We can conclude that: 3.1. innodb is key-part-length default is 768-1; if set the innobase_large_prefix variables to ture(default is false), key-part-length can be 3072; 3.2. rocksdb's key-part-length default is 767(768-1); if set rocksdb_large_prefix variables to ture(default is false) , key-part-length can be 3072;

So, should we add a system variable(default values is false,and key-part-length is 767).if the system variable is true, key-part-length is 3072-1 ? @hustjieke @RingsC @isredstar

lujiashun avatar Sep 06 '22 12:09 lujiashun

max_supported_key_length in tianmu is 1024, this limit the key length, innodb's value is 3500, myrocks's value is 161024; tianmu use rocksdb as storage, so use the value 161024;

  1. innodb's max_supported_key_length
ha_innobase::max_supported_key_length() const
/*=========================================*/
{
	/* An InnoDB page must store >= 2 keys; a secondary key record
	must also contain the primary key value.  Therefore, if both
	the primary key and the secondary key are at this maximum length,
	it must be less than 1/4th of the free space on a page including
	record overhead.

	MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.

	For page sizes = 16k, InnoDB historically reported 3500 bytes here,
	But the MySQL limit of 3072 was always used through the handler
	interface. */

	switch (UNIV_PAGE_SIZE) {
	case 4096:
		return(768);
	case 8192:
		return(1536);
	default:
		return(3500);
	}
}
  1. myrock5.6's max_supported_key_length
  uint max_supported_key_length() const override {
    DBUG_ENTER_FUNC();

    DBUG_RETURN(16 * 1024); /* just to return something*/
  }

lujiashun avatar Sep 08 '22 11:09 lujiashun

image

lujiashun avatar Sep 08 '22 12:09 lujiashun