共计 1675 个字符,预计需要花费 5 分钟才能阅读完成。
背景
编程过程中在存储用户数据的时候,会遇到数据存储大小的限制。经常遇到的限制可以分为:用户侧、服务端、数据库三个方面,按照流程可以划分为 5 个阶段,如图所示。作为开发人员,需要了解这些限制,避免撞墙。
第一道墙 -client:浏览器限制
用户通过 http 请求提交数据,http 请求本身是没有数据大小的限制,但是浏览器对 URI 的长度进行了限制。
浏览器限制的是 URI 长度,而不是你的请求参数
浏览器 | 限制大小(字符) |
---|---|
IE | 2083 |
Chrome | 8182 |
curl | 8167 |
汉字字符:在 utf- 8 编码格式中,3 个字节,在 gbk 编码中,2 个字节,英文就一个字符一个字节
超过限制长度就会返回错误码 414
第二道墙 -server:服务端限制
服务端对于数据的处理能力不同,对于提交的数据限制能力也不同,不同服务器对请求的限制不同,会存在两个方面的限制:
- URI 长度限制(以 Node 为例)
- 数据包大小限制(以 post 请求为例)
Node
Node 对 URI 的大小有一定的大小限制,最大值 8kb(8 * 1024),
一般情况下,不会触发这个限制,如果程序想单独限制一个大小,通过中间件限制下就行了
req.on('data', function(chunk){
received += chunk.length;
if (received > bytes) req.destroy();});
如果想修改最大的大小,只能去改变源码文件 http_parser.h
了
POST
服务器 | 限制大小(字符) |
---|---|
apache | 8192 |
IIS | 16384 |
nginx | 8kb |
附加:
get 请求是幂等操作,所以可以用缓存来处理,post 请求不是幂等的,所以无法应用缓存
第二道墙 - 数据库代理:DBProxy
线上环境会部署几个数据库,通常情况下,会使用 DBProxy 进行代理,实现负载均衡、IP 地址过滤、数据库分表等操作。常见的数据库代理 mycat/mybuh/dbproxy 等。不同的数据库代理默认的数据大小不同,比如有的公司,DBProxy 的代理设置大小最大为 150kb。
第三道墙 -max_allowed_packet
在实际读写数据库的时候,数据库本身会有容量限制,mysql 中 max_allow_packet,就是第三道墙。max_allow_pocket 是数据库对于单个数据包的大小限制。
参数 | 大小 |
---|---|
默认大小 | 64M(v >= 8.0.3)/4M |
最大值 | 1G |
第四道墙 - 数据库本身大小限制
每一条数据在数据库中都有对应的字段对应,而每一个字段会有对应的大小限制,所以在写入数据库的时候就有对应的大小限制。下面以 mysql 数据库为例说明一下:
mysql 的数据库类型分为五类:数字类型、日期类型、字符串类型,特殊类型、JSON 类型
数字类型
类型 | 存储(位) | 无符号范围 | 有符号范围 | 默认值 |
---|---|---|---|---|
TINYINT | 1 | -128~127 | 0~255 | |
SMALLINT | 2 | -32768~32767 | 0~65535 | |
MEDIUMINT | 3 | -8388608~8388607 | 0~16777215 | |
INT | 4 | -2147483648~2147483647 | 0~4294967295 | |
BIGINT | 8 | - 2 的 63 方~2 的 63 方 -1 | 0~2 的 64 方 -1 |
注意⚠️:超过范围怎么处理?
- 在严格模式下,会直接报错
- 在非严格模式下,会显示范围的边界,比如要存储 9223372036854775808 的值,会显示 9223372036854775807,因为有符号整数最大值为 9223372036854775807
假如就是想显示这样的值怎么办?
将值变为有符号的,或者使用字符串。
其他基本的数据类型和大小,在这里就不赘述了查看详情
JSON 类型
对于 JSON 数据类型,可以通过JSON_STORAGE_SIZE
,获取可以存储的 JSON 数据的大小
总结
本文目的不是让你记住这些限制,而是让你知道哪里有数据存储的限制,当出现问题的时候,知道去哪里排查。
参考文献
JSON MERGE FUNCTION
对 GET 和 POST 的理解很形象
url 长度限制
如何选择合适的数据库代理
美团点评的 DBProxy
常见的 Mysql 数据库类型
长度限制
推荐一个面试
JSON_STORAGE_SIZE()