mysql 单行数据的最大存储限制,并非一个固定值,而是由 存储引擎、页大小、行格式、列类型 共同决定的动态上限。
一、innodb 行大小硬限制
1.官方文档定义
- 最大行大小:略小于 16kb 的页大小(默认 16,384 字节)
- 实际可用空间:
≈ 8,000 字节(因页头/尾、系统列、预留空间占用)
✅ 关键公式:
有效行大小 ≤ 16,384 - 页开销(~200b) - 系统列(13b) - 预留空间(~7,000b)
2.为什么不是 16kb?
- 页结构开销:
- 页头/尾:约 120 字节
- 事务id + 回滚指针:13 字节
- null 位图:
(列数+7)/8字节 - 变长字段长度列表:1~2 字节/字段
- 预留空间:
innodb 为 行更新 预留约 50% 页空间(防页分裂)
⚠️ 实测上限:
单行总数据(不含溢出)≤ 7,950 字节(mysql 8.0)
二、突破限制:溢出页(off-page storage)
当行数据超过阈值,innodb 自动将 大字段 存入 溢出页(overflow pages):
| 列类型 | 溢出阈值 | 存储方式 |
|---|---|---|
| text/blob | > 768 字节 | 主键页存 20 字节指针,数据存独立页 |
| varchar | > 768 字节 | 同 text |
| json | 总大小 > 768 字节 | 同 text |
✅ 效果:
逻辑行大小无硬上限(受限于innodb_page_size和磁盘空间)
示例:
create table t (
id int primary key,
content longtext -- 可存 4gb 数据
);
- 主键页:仅存
id+ 20 字节指针 - 溢出页:
content数据分散在多个 16kb 页中
三、各列类型的存储上限
| 类型 | 最大值 | 磁盘占用 |
|---|---|---|
| tinyint | 1 字节 | 1b |
| int | 4 字节 | 4b |
| bigint | 8 字节 | 8b |
| varchar(n) | 65,535 字节 | 实际长度 + 1~2b 长度前缀 |
| text | 65,535 字节 | 同 varchar |
| mediumtext | 16mb | 指针 + 溢出页 |
| longtext | 4gb | 指针 + 溢出页 |
| json | ≈ 1gb | 以 text 形式存储 |
⚠️ 注意:
所有列总和 ≤ 65,535 字节(mysql 行格式限制,非 innodb)
四、行格式(row_format)的影响
| 格式 | 溢出策略 | 适用场景 |
|---|---|---|
| compact | > 768 字节溢出 | 旧版本兼容 |
| dynamic | 所有大字段直接溢出 | 推荐!减少主键页碎片 |
| redundant | 已废弃 | — |
✅ 最佳实践:
create table t (...) row_format=dynamic;
五、极端情况测试
1.最大单行(无溢出)
-- 创建接近 8kb 的行
create table max_row (
c1 varchar(7000),
c2 varchar(900)
) row_format=dynamic;
- 插入:
insert into max_row values (repeat('a',7000), repeat('b',900)); - 结果:成功(总 ≈ 7,900b)
2.最大单行(含溢出)
-- 存储 1gb json
create table huge_json (
id int primary key,
data json
) row_format=dynamic;
insert into huge_json values (1, load_file('/path/to/1gb.json'));
- 结果:成功(主键页仅存指针)
六、生产建议
避免宽表:
- 单行 > 4kb 会降低 buffer pool 效率
- 将大字段拆到单独表
强制 dynamic 格式:
set global innodb_file_format=barracuda; set global innodb_file_per_table=on; create table t (...) row_format=dynamic;
监控溢出页:
-- 查看溢出页使用 select * from information_schema.innodb_sys_tablespaces where name='your_db/your_table';
总结
- 物理行上限:≈ 8,000 字节(主键页内)
- 逻辑行上限:4gb(通过溢出页)
- 工程原则:
“单行越小,buffer pool 效率越高;大字段必须溢出”。
用row_format=dynamic+ 拆分宽表,方能兼顾容量与性能。
到此这篇关于mysql数据库单行数据最大可以存储多少的文章就介绍到这了,更多相关mysql单行数据最大存储内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论