大家好,我是小米,今年31岁,一个喜欢在代码和生活里都“刨根问底”的程序员。
上周末,我去参加了一场社招面试。整个过程氛围挺轻松的,面试官人也挺和蔼,但有一道题真把我整不会,偏偏又是那种“看似简单却容易翻车”的经典问题。
面试官微微一笑,敲了两下桌子,说:
“小米啊,那我问你个小问题,数据库里定义一个字段 int(20),这个 20 到底是什么意思?”
我当时脑子嗡的一声。明明 int 我天天用,int(20) 我也写过无数次,可真要解释 20 是啥,脑袋竟然一片空白。
我试探着说:“是不是代表这个 int 能存 20 位的整数?”
面试官笑了,摇摇头,递给我一个眼神——“继续猜”。
我一时语塞,只好尴尬地笑笑。
int(20) 真能存 20 位整数吗?
很多人跟我当时一样,第一反应就是:int(20) 能存 20 位数字。毕竟直觉告诉我们,括号里的 20,好像就是长度。
但很遗憾,这个理解是错的。
在 MySQL 里,int 类型的存储空间固定是 4 个字节,最大能表示的范围就是 -2147483648 ~ 2147483647(有符号) 。无论你写 int(3) 还是 int(20),占用空间都一样,能存的数也完全一样。
所以,int(20) 里那个 20,根本不会影响存储范围。
这下就很尴尬了,那它到底有什么用?
int(20) 的历史使命:显示宽度
其实,括号里的数字,在 MySQL 里曾经代表的是 显示宽度(display width) 。什么意思呢?
假设你定义了一个字段:
然后插入一个值:
查出来会是这样:
是不是恍然大悟了?
这个 5 就是说:显示的时候,最少用 5 位,不够的地方在前面补 0。
但要注意了,这个“补零”的效果,只有你加了 ZEROFILL 关键字才会生效。否则的话,int(5) 跟 int(20),显示完全没区别。
所以,int(20) 里的 20,其实就是给 ZEROFILL 做准备的“显示宽度”。
为什么面试官爱问这个?
当时我答错了,面试官笑而不语。后来我想通了:这个问题其实就是个坑,考的不是你死记硬背,而是你对 MySQL 数据类型理解的深度。
很多人写 SQL 的时候,喜欢顺手写个 int(11),int(20),以为这样更“专业”。其实这就是历史遗留的一个误解。
在 MySQL 5.7 之前,int(M) 还挺常见,大家都喜欢乱写。
但到了 MySQL 8.0,官方直接就把这个“显示宽度”特性废弃了,原因很简单:
- 容易误导人
- 没啥实际价值
- 除了 ZEROFILL,几乎没场景用
所以在 MySQL 8.0 之后,你再写 int(20),会直接报 warning,说这是废弃的写法。
int 的本质:和存储空间无关
我当时为了搞懂这个问题,还专门查了官方文档,才彻底理清楚。
重点来了:
- int 类型固定占 4 个字节(32 位)
- bigint 占 8 个字节
- mediumint 占 3 个字节
- smallint 占 2 个字节
- tinyint 占 1 个字节
所以,int(20) 根本不会改变占用的字节数,能存的范围也不会变化。
你要能存 20 位的整数,那必须用 bigint,甚至 decimal。
面试官要的就是你能说清楚这一点,别被 int(20) 的“假象”给骗了。
ZEROFILL 的尴尬现状
说实话,zerofill 这个特性用得真不多。
想想看,我们现在前端展示一个数字,需要补零,完全可以用格式化工具来搞,比如 Java 里 String.format("%05d", 123),或者前端直接补齐。干嘛非得依赖数据库?
而且,zerofill 有个很坑的地方:
一旦你给 int 加了 zerofill,MySQL 会自动把这个字段设成 UNSIGNED,也就是无符号整数。
这就意味着,你存不了负数了!
这是不是很诡异?
我曾经在一个老项目里,遇到过 int(6) zerofill,结果某次业务里需要存 -1,居然报错。后来才发现是 zerofill 搞的鬼。
面试回答的正确姿势
那如果你在面试里遇到这个问题,怎么答才算漂亮呢?
我整理了一个标准答案,你们可以参考:
- int(20) 中的 20 在 MySQL 里表示的是 显示宽度,不会影响存储范围。
- 显示宽度只有在 搭配 ZEROFILL 的时候才会生效,比如 int(5) zerofill 存 123,会显示为 00123。
- 在 MySQL 8.0 中,int(M) 的显示宽度已经被 废弃,官方建议直接写 int。
- 如果想存储超过 int 范围的数,需要用 bigint 或 decimal,而不是写 int(20)。
是不是很完整?既讲了原理,又提到了版本差异,还点到了最佳实践。面试官听了,至少不会怀疑你是在背八股。
我的踩坑经历
我还记得几年前,在一个金融类项目里,数据库里很多字段都写成了 int(20)。当时的 DBA 说:“这样更大气,看起来能放更多数字。”
后来我们发现,根本没啥卵用。一个客户的账号字段,本来以为 int(20) 就能搞定,结果随着业务发展,账号早就超过 int 的范围了,直接报错。最后不得不改成 bigint。
那一刻我才真正明白:
别被括号里的数字骗了,决定存储能力的是类型本身,不是那个括号。
总结
回到开头的那个面试题,如果再让我答一次,我会这样说:
“int(20) 里的 20 其实是显示宽度,不会影响存储范围。只有在 zerofill 的时候才会生效,比如 int(5) zerofill 会显示 00123。在 MySQL 8.0 以后,这个特性已经废弃了,实际工作里完全没必要写 int(20),直接写 int 就好。如果要存储更大的数,应该用 bigint 或 decimal。”
面试官听到这句话,十有八九会点点头,然后翻开下一道题。
最后
写到这里,突然想起一句话:很多坑,不是因为技术难,而是因为我们以为自己懂。
int(20) 这个小括号,就是典型的“自以为懂”。它看似专业,其实是个历史遗留的迷惑性特性。
所以,下次你再写 SQL,能不能不要随手写个 int(11) 或 int(20)?
要知道,真正专业的人,往往写得很简单。
END
好啦,今天的小故事就分享到这。
如果你在面试里也被这个问题坑过,或者在项目里因为 int(20) 踩过坑,欢迎在评论区留言,我们一起聊聊!
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!