中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

MySQL 問題分析:ERROR 1071 (42000) : Specified key was too long; max key length is 767 bytes

2018-09-27    來源:importnew

容器云強(qiáng)勢上線!快速搭建集群,上萬Linux鏡像隨意使用

今天在MySQL 5.6版本的數(shù)據(jù)庫中修改InnoDB表字段長度時遇到了”ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes”錯誤,第一次遇到這個錯誤,遂花了點學(xué)習(xí)、研究過、總結(jié)這個問題。?

我們先來創(chuàng)建一個測試表,構(gòu)造這樣的錯誤。

mysql> use MyDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
mysql> CREATE TABLE `TEST` (
    ->   `CODE_NAME` varchar(100) NOT NULL DEFAULT '',
    ->   `CODE_SEQ` smallint(6) NOT NULL DEFAULT '1',
    ->   `ACTIVE` char(1) DEFAULT 'Y',
    ->   `CODE_VALUE1` varchar(250) DEFAULT NULL,
    ->   PRIMARY KEY (`CODE_NAME`,`CODE_SEQ`),
    ->   KEY `IDX_GEN_CODE` (`CODE_NAME`,`CODE_VALUE1`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.02 sec)
 
 
mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
mysql>

其實這個“ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes”錯誤是指超出索引字節(jié)的限制,并不是指字段長度限制。在官方文檔“Limits on InnoDB Tables”有關(guān)于這方面的介紹、描述(詳情請見參考資料):

MySQL 5.6文檔內(nèi)容如下?

By default, the index key prefix length limit is 767 bytes. See Section 13.1.13, “CREATE INDEX Syntax”. For example, you might hit this limit with a column prefix index of more than 255 characters on a TEXT or VARCHAR column, assuming a utf8mb3 character set and the maximum of 3 bytes for each character. When the innodb_large_prefix configuration option is enabled, the index key prefix length limit is raised to 3072 bytes for InnoDB tables that use DYNAMIC or COMPRESSED row format.

 

Attempting to use an index key prefix length that exceeds the limit returns an error. To avoid such errors in replication configurations, avoid enablinginnodb_large_prefix on the master if it cannot also be enabled on slaves.

The limits that apply to index key prefixes also apply to full-column index keys.

MySQL 5.7文檔內(nèi)容如下:

If innodb_large_prefix is enabled (the default), the index key prefix limit is 3072 bytes for InnoDB tables that use DYNAMIC or COMPRESSED row format. If innodb_large_prefix is disabled, the index key prefix limit is 767 bytes for tables of any row format.

innodb_large_prefix is deprecated and will be removed in a future release. innodb_large_prefix was introduced in MySQL 5.5 to disable large index key prefixes for compatibility with earlier versions of InnoDB that do not support large index key prefixes.

The index key prefix length limit is 767 bytes for InnoDB tables that use the REDUNDANT or COMPACT row format. For example, you might hit this limit with a column prefix index of more than 255 characters on a TEXT or VARCHAR column, assuming a utf8mb3 character set and the maximum of 3 bytes for each character.

Attempting to use an index key prefix length that exceeds the limit returns an error. To avoid such errors in replication configurations, avoid enablinginnodb_large_prefix on the master if it cannot also be enabled on slaves.

The limits that apply to index key prefixes also apply to full-column index keys.

如果啟用了系統(tǒng)變量innodb_large_prefix(默認(rèn)啟用,注意實驗版本為MySQL 5.6.41,默認(rèn)是關(guān)閉的,MySQL 5.7默認(rèn)開啟),則對于使用DYNAMIC或COMPRESSED行格式的InnoDB表,索引鍵前綴限制為3072字節(jié)。如果禁用innodb_large_prefix,則對于任何行格式的表,索引鍵前綴限制為767字節(jié)。

innodb_large_prefix將在以后的版本中刪除、棄用。在MySQL 5.5中引入了innodb_large_prefix,用來禁用大型前綴索引,以便與不支持大索引鍵前綴的早期版本的InnoDB兼容。

對于使用REDUNDANT或COMPACT行格式的InnoDB表,索引鍵前綴長度限制為767字節(jié)。例如,您可能會在TEXT或VARCHAR列上使用超過255個字符的列前綴索引達(dá)到此限制,假設(shè)為utf8mb3字符集,并且每個字符最多包含3個字節(jié)。

嘗試使用超出限制的索引鍵前綴長度會返回錯誤。要避免復(fù)制配置中出現(xiàn)此類錯誤,請避免在主服務(wù)器上啟用enableinnodb_large_prefix(如果無法在從服務(wù)器上啟用)。

適用于索引鍵前綴的限制也適用于全列索引鍵。

注意:上面是767個字節(jié),而不是字符,具體到字符數(shù)量,這就跟字符集有關(guān)。GBK是雙字節(jié)的,UTF-8是三字節(jié)的

解決方案:

1:啟用系統(tǒng)變量innodb_large_prefix

注意:光有這個系統(tǒng)變量開啟是不夠的。必須滿足下面幾個條件:

  • 系統(tǒng)變量innodb_large_prefix為ON
  • 系統(tǒng)變量innodb_file_format為Barracuda
  • ROW_FORMAT為DYNAMIC或COMPRESSED

如下測試所示:

mysql> show variables like '%innodb_large_prefix%';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| innodb_large_prefix | OFF   |
+---------------------+-------+
1 row in set (0.00 sec)
 
mysql> set global innodb_large_prefix=on;
Query OK, 0 rows affected (0.00 sec)
 
mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);
ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.
mysql> 
mysql> show variables like '%innodb_file_format%';
+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| innodb_file_format       | Antelope  |
| innodb_file_format_check | ON        |
| innodb_file_format_max   | Barracuda |
+--------------------------+-----------+
3 rows in set (0.01 sec)
 
mysql> set global innodb_file_format=Barracuda;
Query OK, 0 rows affected (0.00 sec)
 
mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);
ERROR 1709 (HY000): Index column size too large. The maximum column size is 767 bytes.
mysql> 
 
mysql> 
mysql> show table status from MyDB where name='TEST'\G;
*************************** 1. row ***************************
           Name: TEST
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2018-09-20 13:53:49
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 
 
mysql>  ALTER TABLE TEST ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> show table status from MyDB where name='TEST'\G;
*************************** 1. row ***************************
           Name: TEST
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2018-09-20 14:04:05
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options: row_format=DYNAMIC
        Comment: 
1 row in set (0.00 sec)
 
ERROR: 
No query specified
 
mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

2:使用前綴索引解決這個問題

之所以要限制索引鍵值的大小,是因為性能問題,而前綴索引能很好的解決這個問題。不需要修改任何系統(tǒng)變量。

mysql> show index from TEST;
..................................
 
mysql> ALTER TABLE TEST DROP INDEX IDX_GEN_CODE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> CREATE IDX_GEN_CODE TEST ON TEST (CODE_NAME, CODE_VALUE1(12));
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> ALTER TABLE TEST MODIFY CODE_VALUE1 VARCHAR(350);
Query OK, 1064 rows affected (0.08 sec)
Records: 1064  Duplicates: 0  Warnings: 0

問題延伸: 為什么InnoDB的索引字節(jié)數(shù)限制為767字節(jié)? 而不是800字節(jié)呢? 這樣限制又是出于什么具體性能的考慮呢? 暫時還沒有弄清楚這些細(xì)節(jié)問題!?

參考資料:

  • https://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html
  • https://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html

標(biāo)簽: Mysql 服務(wù)器 數(shù)據(jù)庫

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:Spring Boot基礎(chǔ)教程 ( 五 ) :構(gòu)建 RESTful API 與單元測試

下一篇:Spring Boot基礎(chǔ)教程 ( 四 ) :Spring Boot 屬性配置文件詳解