MySQL:列大小限制

时间:2016-04-30 10:09:23

标签: mysql sql database innodb

我目前正在开发Windows操作系统,我已经安装了MySQL社区服务器5.6.30,一切都很好。我有一个初始化数据库的脚本,而且一切正常。

现在我正在尝试在Linux环境中运行此脚本 - 相同的MySQL版本 - 我收到以下错误:

  

第3行的错误1074(42000):色谱柱长度过大   'txt'(最大= 21845);使用BLOB或TEXT代替

脚本 -

DROP TABLE IF EXISTS text;
CREATE TABLE `texts` (
  `id` BINARY(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `txt` VARCHAR(50000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

显然我的Windows操作系统上有一些MySQL服务器配置需要在Linux上复制;任何人都可以分享想法吗?

更新1

在AWS的RDS上它也可以工作,我非常确定它只是一个基于Linux的服务,所以显然它只是一个配置问题。

是否有人知道如何使用UTF8达到varchar 50k?我不想使用TEXT或MEDIUMTEXT或其他任何东西,只是普通的旧varchar(大小)

更新2

我很欣赏所提出的不同解决方案,但我不寻找新的解决方案,我只是在寻找答案,为什么varchar(50k)在windows下工作,在linux下也没有。 顺便说一句,我使用字符集UTF8和整理utf8_general_ci。

答案

回答我自己的问题,这是它设置的SQL_MODE的一个问题 STRICT_TRANS_TABLES,应该已被删除。

4 个答案:

答案 0 :(得分:3)

根据文件:

  

尽管InnoDB支持的行大小超过65,535字节   在内部,MySQL本身对行的行大小限制为65,535   所有列的总大小:

mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
    -> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
    -> f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
     

ERROR 1118(42000):行大小太大。最大行大小   使用的表类型,不计算BLOB,是65535.你必须改变一些   列到TEXT或BLOB

(不幸的是,这个例子没有提供字符集,所以我们真的不知道列有多大。)

utf8编码每个字符使用1,2或3个字节。因此,可安全放入65,535字节(MySQL最大值)页面的最大字符数为21,845个字符(21,845 * 3 = 65,535)。

尽管版本相似,但似乎Windows的空间分配保守,并保证您可以在字段中存储任何字符。 Linux似乎有更多自由放任的态度。您可以存储一些超过21,845个字符的字符串,具体取决于字符。

我不知道为什么在同一版本中存在这种差异。在某种意义上,这两种方法都是“正确的”。有足够简单的解决方法:

  • 使用TEXT
  • 切换到具有较短字符的排序规则(可能是您要存储的字符)。
  • 缩小田地的大小。

答案 1 :(得分:1)

请简单地使用TEXT声明txt列

DROP TABLE IF EXISTS text;
CREATE TABLE `texts` (
  `id` BINARY(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `txt` TEXT DEFAULT NULL,
   PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

答案 2 :(得分:1)

utf8每个字符最多需要3个字节。 utf8mb4:4;拉丁1:1; ascii:1;等等VARCHAR(N)实现为文本字节前面的1或2字节长度。允许保存N 字符(不是字节)。所以,如果你说你想要utf8,那么3 * N必须小于65535,这是2字节长度的最大值。

很高兴您没有使用某些旧版本,其中VARCHAR的限制为255.

如果您的txt不需要ascii或英语以外的字符,请使用CHARACTER SET latin1

在InnoDB中,当存在“长”字段(大字符,文本,blob等)时,部分或全部列存储在单独的块中。对于记录中存储的内容,存在大约8000字节的限制。

如果你真的需要50K的utf8,那么MEDIUMTEXT就是你所需要的。它使用3字节长度,最多可容纳16M字节(5M字符,可能更多,因为utf8是可变长度编码)。

大多数应用程序可以(应该?)使用ascii(每个字符1个字节)或utf8mb4(每个字符1-4个字节)。后者允许使用所有语言,包括表情符号和utf8无法处理的4字节中文字符。

至于为什么Windows和Linux在这里的工作方式不同,我不知道。你使用的是同一个版本吗?建议您使用http://bugs.mysql.com提交错误报告。 (并提供本课题的链接。)

答案 3 :(得分:0)

如果你绝对必须使用varchar - 这是解决这个问题的一个不好的方法! - 那么这是你可以尝试的东西:

CREATE TABLE `texts` (
  `id` BINARY(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `txt` VARCHAR(20000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `texts2` (
  `id` BINARY(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `txt` VARCHAR(20000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

CREATE TABLE `texts3` (
  `id` BINARY(16) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `txt` VARCHAR(10000) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

有50000个字符。现在,您的客户端应用程序必须管理将文本分解为单独的块,并在每个表中创建记录。同样,回读文本将要求你做3个选择语句,但是你将有50000个字符。

根本不建议在任何数据库实施中执行此操作。

我曾在一些环境中工作,在这些环境中,大型文本存储在数据库的列中,并且它总是会导致比解决的问题更多的问题。

这些应该真正假脱机到磁盘上的文件,以及对存储在数据库中的文件的完整路径的引用。

然后在这个文档集上运行一些索引引擎。

您将从此获得更大的可扩展性,并且更容易管理。