MySQL:列大小限制

2nbm6dog  于 2023-02-28  发布在  Mysql
关注(0)|答案(5)|浏览(110)

我目前在Windows操作系统上工作,我安装了MySQL社区服务器5.6.30,一切都很好。我有一个初始化DB的脚本,一切都很好。
现在,我尝试在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 50 k?。我不想使用文本或中文本或任何其他,只是普通的旧varchar(大小)

更新2

我很欣赏所建议的不同解决方案,但我不是在寻找新的解决方案,我只是在寻找一个答案,为什么varchar(50 k)在windows下工作,而在linux下不工作。顺便说一句,我使用的是字符集UTF8和排序utf8_general_ci。

回答我

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

2wnc66cl

2wnc66cl1#

根据文件:
尽管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;

错误1118(42000):行大小太大。所用表类型的最大行大小为65535(不包括BLOB)。必须将某些列更改为TEXT或BLOB
(不幸的是,这个例子没有提供字符集,所以我们并不真正知道列有多大。)
utf8编码每个字符使用1、2或3个字节,因此,一个65,535字节的页面可以容纳的最大字符数(MySQL的最大值)是21,845个字符(21,845 * 3 = 65,535)。
尽管两个版本相似,但Windows在空间分配方面似乎比较保守,并保证您可以在字段中存储任何字符。Linux似乎更倾向于"自由放任"态度。您可以存储一些超过21,845个字符的字符串,具体取决于字符。
我不知道为什么在同一个版本中会存在这种差异。从某种意义上说,这两种方法都是"正确的"。有足够简单的解决方法:

  • 使用TEXT
  • 切换到具有较短字符的归类(这可能是您要存储的)。
  • 减小字段的大小。
qnakjoqk

qnakjoqk2#

请简单地使用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;
a6b3iqyw

a6b3iqyw3#

utf8每个字符最多需要3个字节。utf8 mb 4:4;拉丁文1:1;ascii:1; etc. VARCHAR(N)被实现为文本字节前面的1字节或2字节长度。这允许容纳N * 个字符 (不是字节)。因此,如果你说你想要utf8,那么3N必须小于65535,这是2字节长度的最大值。
很高兴您没有运行旧版本,其中VARCHAR的限制为255。
如果您的txt不需要ascii或英语以外的字符,则使用CHARACTER SET latin1
在InnoDB中,当有“长”字段(大的变量字符、文本、斑点等)时,部分或全部列存储在一个单独的块中。记录中存储的内容限制为大约8000字节。
如果你真的需要50 K的utf8,那么MEDIUMTEXT就是你所需要的,它使用3字节的长度,最多可以容纳16 M字节(5 M字符,可能更多,因为utf8是一个可变长度编码)。
大多数应用程序可以(应该?)使用ascii(每个字符1字节)或utf8mb4(每个字符1-4字节)。后者支持所有语言,包括表情符号和utf8无法处理的4字节中文字符。
至于为什么Windows和Linux在这里的工作方式不同,我不知道。你用的是同一个版本吗?建议你用http://bugs.mysql.com提交一个bug报告。(并在这个问题中提供一个链接。)

zd287kbt

zd287kbt4#

如果你一定要使用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个select语句,但是你将有50000个字符。

对于任何数据库实现,都不建议这样做。

我曾经在一些环境中工作过,在这些环境中,大文本存储在数据库的列中,结果总是导致比解决的问题更多的问题。
这些应该被假脱机到磁盘上的文件中,并引用存储在数据库中的文件的完整路径。
然后在这个文档语料库上运行一些索引引擎。
您将从中获得更大的可伸缩性和更简单的管理。

aiazj4mn

aiazj4mn5#

为了更清楚起见,如果您使用的解决方案确实需要一个长VarChar,就像我在尝试配置WatchDog.NET以使用mysql数据库作为.NET web API日志时的情况一样,您可以以root用户身份登录mysql数据库,然后运行:

SET GLOBAL sql_mode = ""

相关问题