MySQL 中 tinyint(1)、int(11)、bigint(20) 的数字到底是什么意思?
在设计数据库表时,你可能经常看到这样的字段定义:
id int(11) not null auto_increment
is_active tinyint(1) not null default 1
order_id bigint(20) not null
很多人会以为括号里的数字决定了 存储范围大小,比如 int(11)
就能存 11 位数字,其实这是一个误解。今天我们来彻底讲清楚。
一、整数类型的本质存储
在 MySQL 中,整数类型的存储空间是固定的,不会因为你写了括号里的数字而改变。
类型 | 存储空间 | 有符号范围(默认) | 无符号范围(unsigned) |
---|---|---|---|
tinyint | 1字节 | -128 ~ 127 | 0 ~ 255 |
smallint | 2字节 | -32768 ~ 32767 | 0 ~ 65535 |
int | 4字节 | -2147483648 ~ 2147483647 | 0 ~ 4294967295 |
bigint | 8字节 | -2^63 ~ 2^63 - 1 | 0 ~ 2^64 - 1 |
👉 所以:
int
永远是 4 字节,和int(11)
、int(3)
没区别bigint
永远是 8 字节,和bigint(20)
没区别tinyint
永远是 1 字节,和tinyint(1)
、tinyint(2)
都一样
二、括号里的数字 (M) 到底是什么?
这个 (M)
在 MySQL 5.x 里是 显示宽度,意思是 显示时最少显示 M 位数字,但它不会影响存储范围。
例如:
create table test (a int(5) zerofill
);insert into test values (123);
select a from test;
结果会显示:
00123
因为设置了 zerofill
,会自动在前面补零。
但如果没有 zerofill
,就是正常显示 123
。
三、MySQL 8 之后的变化
从 MySQL 8.0.17 开始,整数类型的 (M)
已经被废弃了。
现在你写 int(11)
和 int
完全一样,括号里的数字被忽略。
官方文档说明:MySQL 8.0 Deprecated Features
四、常见误区
-
❌ 以为 int(11) 可以存 11 位数字
- 实际上 int 最大值就是 2147483647(10 位),和 (11) 没关系
-
❌ 以为 bigint(20) 就能存 20 位数字
- 实际上 bigint 最大值是 2^63-1,大约 19 位数字,括号里的 20 纯属无效
-
❌ 以为 tinyint(1) 就是布尔值
- tinyint(1) 本质还是 tinyint,只是 ORM 框架(比如 MySQL JDBC、Laravel)会把它当作布尔值来映射
五、正确写法建议
✅ 在 MySQL 8 及以上:
- 直接写
int
、bigint
、tinyint
就够了,不要写(11)
、(20)
- 如果需要布尔值,直接用
tinyint(1)
或boolean
(底层还是 tinyint(1))
✅ 在 MySQL 5.x(老系统还没升级):
int(11)
里的(11)
只是显示宽度,不影响存储范围- 如果配合
zerofill
才有意义,否则完全可以省略
六、总结
tinyint
、int
、bigint
的存储范围固定,和括号里的数字无关(M)
在 MySQL 5.x 是显示宽度,用处有限,在 8.0 已经废弃- 写
int(11)
其实和int
一样,别再误解了 - 如果需要布尔值,用
tinyint(1)
,只是约定俗成
👉 最佳实践:新项目直接写 int
/ bigint
/ tinyint
,不要加 (M)