20191011-MySQL建索引的强约束

问题:

[42000][1071] Specified key was too long; max key length is 3072 bytes
[42000][1071] Specified key was too long; max key length is 767 bytes

创建表出现上述错的原因是什么?

正文:

Utf8 1~3byte=1字符;Utf8mb4 1~4byte=1字符

mysql 从5.7.17 默认是严格模式,单个列的索引长度不能超过767byte==255.5位(推荐varchar(255)的原因),
启用innodb_large_prefix选项,就可以将单个列约束项扩展至3072byte,
非严格模式下非唯一索引的建立将不会报错,而是自动截取。
联合索引长度不能超过3072byte(在innodb_large_prefix=off也一样),非严格也是自动截取。

为什么是3072 ?

InnoDB一个page的默认大小是16k。由于是Btree组织,
要求叶子节点上一个page至少要包含两条记录(否则就退化链表了)。
所以一个记录最多不能超过8k。又由于InnoDB的聚簇索引结构,
一个二级索引要包含主键索引,因此每个单个索引不能超过4k (极端情况,pk和某个二级索引都达到这个限制)。
由于需要预留和辅助空间,扣掉后不能超过3500,取个“整数”就是(1024*3)。 

如何超越3072 ?

MySQL 索引只支持767个字节,utf8mb4 每个字符占用4个字节,
所以索引最大长度只能为191个字符,即varchar(191),若想要使用更大的字段,
mysql需要设置成支持数据压缩,并且修改表属性 row_format ={DYNAMIC|COMPRESSED}

MySQL中sql mode 中STRICT_ALL_TABLES和STRICT_TRANS_TABLES的区别

只要有他们就是严格模式。默认都是严格模式。

对于事务表,当启用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式时,
如果语句中有非法或丢失值,则会出现错误。语句被放弃并滚动。

对于非事务表,如果插入或更新的第1行出现坏值,两种模式的行为相同。
语句被放弃,表保持不变。如果语句插入或修改多行,并且坏值出现在第2或后面的
行,结果取决于启用了哪个严格选项:

对于STRICT_ALL_TABLES,MySQL返回错误并忽视剩余的行。但是,在这种情况
下,前面的行已经被插入或更新。这说明你可以部分更新,这可能不是你想要的。要
避免这点,最好使用单行语句,因为这样可以不更改表即可以放弃。


 对于STRICT_TRANS_TABLES,MySQL将非法值转换为最接近该列的合法值并插入
调整后的值。如果值丢失,MySQL在列中插入隐式 默认值。在任何情况下,MySQL
都会生成警告而不是给出错误并继续执行语句。

mysql row_format 说明

在 msyql 5.7.9 及以后版本,默认行格式由innodb_default_row_format变量决定,它
的默认值是DYNAMIC,也可以在 create table 的时候指定
ROW_FORMAT=DYNAMIC。用户可以通过命令 SHOW TABLE STATUS 
LIKE'table_name' 来查看当前表使用的行格式,其中 row_format 列表示当前所使用的行记录结构类型。

ROW_FORMAT

命令:

show variables like 'sql_mode'; //查看sql mode
select version(); //
show variables like 'innodb_large_prefix'; //
show table status like  'book_info_22'; //查看row_format
set global innodb_large_prefix=1;
set global innodb_file_format=BARRACUDA

参考:官方文档

你可能感兴趣的:(20191011-MySQL建索引的强约束)