【MySQL】结构行长度的一些限制
今天被开发提交的DDL变更再次困惑,表中字段较多,希望将已有的两个varchar(4000)字段改为varchar(20000),我想innodb对varchar的存储不就是取前768字节记录当前行空间嘛,所以变更不会有任何问题的,但铁打的事实给了我结结实实的一个巴掌,直接报错,现在回放下这个错误!
模拟测试:
CREATE TABLE `ttt` (
`id` DOUBLE ,
`select_type` VARCHAR (57),
`table` VARCHAR (192),
`type` VARCHAR (30),
`possible_keys` VARCHAR (22288),
`key` VARCHAR (192),
`key_len` VARCHAR (22288),
`ref` VARCHAR (3072),
`rows` DOUBLE ,
`Extra` VARCHAR (765)
);
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
看了提示,表的2个varchar字段长度设置过长了,需要改成text,blob之类的类型,修改之后执行成功了。
mysql> use test;
Database changed
mysql>
mysql> CREATE TABLE `ttt` (
-> `id` DOUBLE ,
-> `select_type` VARCHAR (57),
-> `table` VARCHAR (192),
-> `type` VARCHAR (30),
-> `possible_keys` TEXT,
-> `key` VARCHAR (192),
-> `key_len` TEXT,
-> `ref` VARCHAR (3072),
-> `rows` DOUBLE ,
-> `Extra` VARCHAR (765)
-> );
Query OK, 0 rows affected (0.00 sec)
疑惑:varchar(N),这个N不是最大为65535吗?为什么设置成12288就会报错?12288比65535小很多啊。
上官网:http://dev.mysql.com/doc/refman/5.6/en/column-count-limit.html:
Every table (regardless of storage engine) has a maximum row size of 65,535 bytes. Storage engines may place additional constraints on this limit, reducing the effective maximum row size.
解析:65,535所说明的是针对的是整个表的非大字段类型的字段的bytes总合。
欲看详细分析还要继续往下看
每个表有4096个列的硬性限制,但是到具体表是往往小于这个数字,确切的限制取决于几个相互作用的因素:
每个表(不考虑存储引擎)为65,535字节的最大行大小限制。存储引擎可能会对这个限制进行额外的限制,降低了有效的最大行大小。
- 受到行大小限制,列的数目还要看具体的字段长度,例如,UTF8字符需要三个字节存储,因此对于CHAR(255)CHARACTER SET UTF8列,服务器必须分配255×3 =765的字节。因此,一个表不能包含超过65,535/765=85这样的列。
- 可变长度列在评估字段大小时还要考虑存储列实际长度的字节数。例如,VARCHAR(255)CHARACTER SET UTF8列需要额外的两个字节来存储值长度信息,所以该列需要多达767个字节存储,其实最大可以存储65533字节,剩余两个字节存储长度信息。
- BLOB和TEXT列不同于varchar字段,列长度信息独立于行长存储,可以达到65535字节真实存储。
- 声明NULL列可降低允许的最大列数。对于MyISAM表,NULL列需要该行中额外的空间记录其值是否为NULL。每个NULL列需要一个额外的位,四舍五入到最接近的字节。
最大行长度计算如下:
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + delete_flag + 7)/8
+ (number of variable-length columns)
对于静态表,delete_flag = 1,静态表通过在该行记录一个位来标识该行是否已被删除。 动态表时delete_flag = 0,因为该标记存储在动态行首,动态表具体可以根据row_format判断,详情参考Section 15.2.3, “MyISAM Table Storage Formats”
对于InnoDB表,NULL和NOT NULL列存储大小是一样,因此上述计算并不适用。
以下测试是没有问题的,(32765 + 2 + 32766 + 2 )bytes < 655535
mysql> CREATE TABLE t1
-> (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
-> ENGINE = MyISAM CHARACTER SET latin1;
Query OK, 0 rows affected (0.02 sec)
因为NULL属性需要额外的储存空间,超过了最大65535的限制
mysql> CREATE TABLE t2
-> (c1 VARCHAR(32765) NULL, c2 VARCHAR(32766) NULL)
-> ENGINE = MyISAM CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some
columns to TEXT or BLOBs
因为变成字段需要占用行内额外的储存空间,所以超过了最大65535的限制
mysql> CREATE TABLE t3
-> (c1 VARCHAR(65535) NOT NULL)
-> ENGINE = MyISAM CHARACTER SET latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the
used table type, not counting BLOBs, is 65535. You have to change some
columns to TEXT or BLOBs
除此之外,一些存储引擎可能会强加限制表中列数的附加限制。如:
- InnoDB允许单表最多1000个列
- InnoDB限制行大小不到数据库页面的一半,不包括VARBINARY,VARCHAR,BLOB或TEXT列。欲了解更多信息,更多影响体现DML,而不是DML。详情参考Limits on InnoDB Tables
- InnoDB不同的存储格式(压缩,冗余)使用不同数量的页面头部和尾部,这会影响可用于存储行的长度。
如果innodbstrictmode禁用,创建表时使用冗余(REDUNDANT)或紧凑COMPACT格式,如果列超过最大行大小也会成功的定义,只是产生警告:
| Warning | 139 | Row size too large (> 8123). Changing some columns to TEXT or BLOB
or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help.
In current row format, BLOB prefix of 768 bytes is stored inline.
如果innodbstrictmode禁用,创建表时使用动态(DYNAMIC)或压缩(COMPRESSED)格式,如果列超过最大行大小也会成功的定义,就会直接报错:
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help.
In current row format, BLOB prefix of 0 bytes is stored inline.
每个表都有一个包含表定义的.frm文件。文件定义的内容也会影响到字段数的上限,详情参考Limits Imposed by .frm File Structure
参考:
- MySQL 错误:ERROR 1118 (42000): Row size too large. The maximum row size for the used table type
- Limits on Table Column Count and Row Size
- 【MySQL】数据行长度的一些限制
- Limits Imposed by .frm File Structure
【MySQL】结构行长度的一些限制的更多相关文章
- MySQL 如何存储长度较大的varchar与blob
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/96 最近,在工作中遇到了MySQL中如何存储长度较长的字段类型问 ...
- MySQL InnoDB 行记录格式(ROW_FORMAT)
MySQL InnoDB 行记录格式(ROW_FORMAT) 一.行记录格式的分类和介绍 在早期的InnoDB版本中,由于文件格式只有一种,因此不需要为此文件格式命名.随着InnoDB引擎的发展,开发 ...
- MySQL数据行溢出的深入理解
一.从常见的报错说起 故事的开头我们先来看一个常见的sql报错信息: 相信对于这类报错大家一定遇到过很多次了,特别对于OMG这种已内容生产为主要工作核心的BG,在内容线的存储中,数据大一定是个绕不开的 ...
- [转]分析MySQL数据类型的长度【mysql数据字段 中length和decimals的作用!熟悉mysql必看】
转载自:http://blog.csdn.net/daydreamingboy/article/details/6310907 分析MySQL数据类型的长度 MySQL有几种数据类型可以限制类型的&q ...
- 通过mysql命令行理解mysql
引言:工具不可谓给我们的生活带来了便利,但有些时候我们却忘记了事物本身的意义.在大多数人都在追捧甚至是盲从各种各样的工具有多先进的时候,你是否有反思过:你目前是否有使用它的资格. 假设你学会了使用一款 ...
- mysql命令行参数(转)
MySQL命令行参数 Usage: mysql [OPTIONS] [database] //命令方式 -?, --help //显示帮助信息并退出 -I, --help //显示帮助信息并退出 ...
- [转]Mysql命令行常用操作
Mysql命令行常用操作 一.从命令行登录MySQL数据库服务器 1.登录使用默认3306端口的MySQL /usr/local/mysql/bin/mysql -u root -p 2.通过TCP连 ...
- mysql 命令行参数
MySQL命令行参数 Usage: mysql [OPTIONS] [database] //命令方式 例如: mysql -h${HOSTNAME} -P${PORT} -u${USERNAM ...
- Mysql varchar大小长度问题介绍
如果被 varchar 超过上述的 b 规则,被强转成 text 类型,则每个字段占用定义长度为 11 字节,当然这已经不是 varchar 了4.0版本以下,varchar(20),指的是20字节, ...
随机推荐
- (Python)导出指定文件夹中as文件的完全限定类名
AS3程序在编译的过程中,有一个特点是这样的,不管是项目中的类,还是标准库或者第三方库的类,编译的时候只会把用到的那些类文件编译进去,也就是说,某一些类,只要没有被主程序引用到,那这个文件是不会被编译 ...
- JavaScipt 源码解析 异步
我们常见的异步操作: 定时器setTimeout postmessage WebWorkor CSS3 动画 XMLHttpRequest HTML5的本地数据 等等- JavaScript要求在与服 ...
- jQuery经典面试题及答案精选(转)
jQuery是一款非常流行的Javascript框架,如果你想要从事Web前端开发这个岗位,那么jQuery是你必须掌握而且能够熟练应用的一门技术.本文整理了一些关于jQuery的经典面试题及答案,分 ...
- WCF初探-19:WCF消息协定
WCF消息协定概述 在生成 WCF应用程序时,开发人员通常会密切关注数据结构和序列化问题,而不必关心携带数据的消息结构. 对于这些应用程序,为参数或返回值创建数据协定的过程很简单.但是,有时完全控制 ...
- bzoj 2761: [JLOI2011]不重复数字
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #d ...
- wp8.1 Study19:通知
一.通知形式 在windowsphone系统中,通知有很多中形式,如下图 (Tile磁贴在前一博文已复习过,Badge形式与tile类似) 1.Toast 它主要是利用xml文件来编写的,xml代码如 ...
- 利用GCC编译器生成动态链接库和静态链接库
转载请标明:http://www.cnblogs.com/winifred-tang94/ 1.编译过程 gcc –fPIC –c xxx.c 其中-fPIC是通知gcc编译器产生位置独立的目标代码. ...
- windowsAzure模拟器错误
Failed to initialize Microsoft Azure storage emulator. Unable to open wait handle 无法初始化微软Azure存储模拟器. ...
- Hadoop随笔(二):Hadoop V1到Hadoop V2的主要变化
一.消失的概念与新鲜的名词 Hadoop V2相对于Hadoop V1的变化主要在于资源管理和任务调度,计算模型仍然保持map/reduce的模型.资源管理和任务调度的变化导致了工作流程的变化,一些概 ...
- Python学习路程day13
JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. ...