绝版佳佳 發表於 2026-1-13 11:48:08

mysql的bigint 和 bigint(20) 主键自增的区别解析

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">✅bigint和bigint(20)主键自增的区别(完整解答,开发必看)</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">一、核心区别:bigint&asymp;bigint(20),只有「显示宽度」的差异</a></li><ul class="third_class_ul"><li><a href="#_label3_0_0_0">✅ 先明确 MySQL 中数值类型(M)的含义</a></li><li><a href="#_label3_0_0_1">✅ 什么是「显示宽度」?</a></li></ul><li><a href="#_lab2_0_1">二、重中之重:这3个关键点,完全一致(核心重点)</a></li><ul class="third_class_ul"><li><a href="#_label3_0_1_2">✅ 1. 取值范围完全相同</a></li><li><a href="#_label3_0_1_3">✅ 2. 占用的磁盘存储完全相同</a></li><li><a href="#_label3_0_1_4">✅ 3. 主键自增的逻辑完全相同</a></li></ul><li><a href="#_lab2_0_2">三、补充:为什么会有bigint(20)这种写法?【历史原因+规范】</a></li><ul class="third_class_ul"><li><a href="#_label3_0_2_5">✅ 1. 历史遗留的「规范写法」</a></li><li><a href="#_label3_0_2_6">✅ 2. 区分「有符号/无符号」的视觉暗示</a></li></ul><li><a href="#_lab2_0_3">四、延伸:这2个坑千万别踩!(99%新手必犯)</a></li><ul class="third_class_ul"><li><a href="#_label3_0_3_7">❌ 坑1:以为bigint(10)比bigint(20)存的数字少</a></li><li><a href="#_label3_0_3_8">❌ 坑2:主键自增列加了DEFAULT NULL</a></li><li><a href="#_label3_0_3_9">✅ 正确的2种主键自增写法(都可以,生产通用)</a></li></ul><li><a href="#_lab2_0_4">五、拓展:ZEROFILL零填充的实际使用(唯一用到显示宽度的场景)</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_0_5">✨ 最终总结(一句话搞定,看完就懂)</a></li><ul class="third_class_ul"><li><a href="#_label3_0_5_10">✅ 开发选型建议</a></li></ul></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>✅bigint和bigint(20)主键自增的区别(完整解答,开发必看)</h2>
<p>你的这个问题是 <strong>MySQL开发高频疑问+面试常考点</strong>,也是新手极易混淆的点,结论先给你:</p>
<blockquote><p><code>id</code> bigint NOT NULL AUTO_INCREMENT<br /><code>id</code> bigint(20) NOT NULL AUTO_INCREMENT<br />✔️ 本质无区别,功能完全一样,生产上用哪个都可以!<br />✔️ 唯一的区别:只是 MySQL 的「显示宽度」不一样,对存储、取值、自增逻辑、性能 0影响!</p></blockquote>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>一、核心区别:bigint&asymp;bigint(20),只有「显示宽度」的差异</h3>
<p class="maodian"><a name="_label3_0_0_0"></a></p><h4>✅ 先明确 MySQL 中数值类型(M)的含义</h4>
<p>MySQL 里的 <code>int(11)</code>、<code>bigint(20)</code>、<code>tinyint(4)</code> 中,<strong>括号里的数字不是「取值范围」,而是「显示宽度(Display Width)」</strong>,这个是重中之重,90%的程序员都理解错了!</p>
<ul><li><code>bigint</code> :等价于 <code>bigint(20)</code>,MySQL 对 bigint 类型的<strong>默认显示宽度就是 20</strong></li><li><code>bigint(20)</code>:手动指定了显示宽度为20</li></ul>
<p class="maodian"><a name="_label3_0_0_1"></a></p><h4>✅ 什么是「显示宽度」?</h4>
<p>显示宽度的作用:<strong>仅用于当</strong>你使用 <code>ZEROFILL</code> 零填<strong>充约束时,控制数字的「展示格式」,仅此而已</strong>。</p>
<ul><li>没有 <code>ZEROFILL</code> 时,<code>bigint</code> 和 <code>bigint(20)</code> 完全一样,查询出来的数字都是正常样式(比如 1、100、10000)</li><li>有 <code>ZEROFILL</code> 时,会自动补0到指定的显示宽度,比如 <code>bigint(6) zerofill</code> 存数字<code>123</code>,查询出来是<code>000123</code></li></ul>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>二、重中之重:这3个关键点,完全一致(核心重点)</h3>
<p>你最关心的「主键自增、存储、取值」这些核心功能,<strong>两者没有任何区别</strong>,这也是为什么生产里两种写法都能见到的原因,3个核心一致点:</p>
<p class="maodian"><a name="_label3_0_1_2"></a></p><h4>✅ 1. 取值范围完全相同</h4>
<p><code>bigint</code> 是 MySQL 的8字节整数类型,不管写不写<code>(20)</code>,取值范围都是固定的:</p>
<ul><li>有符号:<code>-9223372036854775808 ~ 9223372036854775807</code></li><li>无符号:<code>0 ~ 18446744073709551615</code></li></ul>
<blockquote><p>对你的主键自增来说:正数自增从1开始,能存 <strong>90亿亿+</strong> 的数据,这辈子都用不完,不用担心主键不够用。</p></blockquote>
<p class="maodian"><a name="_label3_0_1_3"></a></p><h4>✅ 2. 占用的磁盘存储完全相同</h4>
<p>两者都是 <code>bigint</code> 类型,<strong>固定占用 8 个字节的磁盘空间</strong>,不会因为写了<code>(20)</code>就多占1字节,也不会少占。<br />对比一下你之前踩过的坑(补充给你):</p>
<ul><li><code>int</code> / <code>int(11)</code> &rarr; 固定4字节,最多存2147万</li><li><code>bigint</code> / <code>bigint(20)</code> &rarr; 固定8字节,最多存90亿亿+</li></ul>
<blockquote><p>✅ 开发建议:<strong>主键一律用 bigint 自增</strong>,不管写不写20,永远不会出现主键溢出的问题,这是行业规范。</p></blockquote>
<p class="maodian"><a name="_label3_0_1_4"></a></p><h4>✅ 3. 主键自增的逻辑完全相同</h4>
<p>两种写法的 <code>AUTO_INCREMENT</code> 自增规则没有任何差异:</p>
<ul><li>插入数据时,不用手动赋值id,数据库自动从1开始+1递增</li><li>删数据不会回滚自增序列,比如删了id=10的数据,下次新增还是11</li><li>批量插入、主键回填等功能,两者表现一致</li></ul>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>三、补充:为什么会有bigint(20)这种写法?【历史原因+规范】</h3>
<p>这个写法不是没用的,而是有由来的,也是团队开发里的「约定俗成」,两种常见场景:</p>
<p class="maodian"><a name="_label3_0_2_5"></a></p><h4>✅ 1. 历史遗留的「规范写法」</h4>
<p>MySQL 官方对各类数值类型的<strong>默认显示宽度</strong>做了规定:</p>
<ul><li><code>tinyint</code> &rarr; 默认 <code>tinyint(4)</code></li><li><code>smallint</code> &rarr; 默认 <code>smallint(6)</code></li><li><code>int</code> &rarr; 默认 <code>int(11)</code></li><li><code>bigint</code> &rarr; 默认 <code>bigint(20)</code></li></ul>
<p>很多老程序员/公司的建表规范里,会<strong>手动把默认宽度写上</strong>,比如 <code>int(11)</code>、<code>bigint(20)</code>,目的是「代码可读性更好」,团队里所有人一看就知道是标准的数值类型,仅此而已。</p>
<p class="maodian"><a name="_label3_0_2_6"></a></p><h4>✅ 2. 区分「有符号/无符号」的视觉暗示</h4>
<p>MySQL 中 <code>int(11)</code> 是<strong>有符号</strong>的默认宽度,<code>int(10)</code> 一般是<strong>无符号</strong>的默认宽度;<br />同理 <code>bigint(20)</code> 是有符号的默认宽度,<code>bigint(19)</code> 是无符号的默认宽度。<br />手动写上宽度,团队成员能一眼看出字段的符号属性,是一种「开发默契」。</p>
<p class="maodian"><a name="_lab2_0_3"></a></p><h3>四、延伸:这2个坑千万别踩!(99%新手必犯)</h3>
<p>结合你的场景是「主键自增」,我把和这个问题相关的<strong>高频错误写法+避坑点</strong>一起写给你,都是生产环境踩过的坑,看完直接避坑:</p>
<p class="maodian"><a name="_label3_0_3_7"></a></p><h4>❌ 坑1:以为bigint(10)比bigint(20)存的数字少</h4>
<p><strong>错!</strong> 显示宽度不影响取值范围,<code>bigint(1)</code> 和 <code>bigint(20)</code> 存的数字范围完全一样,都是8字节的bigint,只是展示格式不同。</p>
<p class="maodian"><a name="_label3_0_3_8"></a></p><h4>❌ 坑2:主键自增列加了DEFAULT NULL</h4>
<div class="jb51code"><pre class="brush:sql;">id bigint(20) AUTO_INCREMENT DEFAULT NULL PRIMARY KEY -- ❌ 语法报错
</pre></div>
<p>MySQL 硬性规则:<strong><code>AUTO_INCREMENT</code> 必须搭配 <code>NOT NULL</code></strong>,自增主键永远不会为空,写了<code>DEFAULT NULL</code>会直接报错 <code>Incorrect column specifier for column &#39;id&#39;</code>。</p>
<p class="maodian"><a name="_label3_0_3_9"></a></p><h4>✅ 正确的2种主键自增写法(都可以,生产通用)</h4>
<div class="jb51code"><pre class="brush:sql;">-- 写法1:简写(推荐,简洁)
`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
-- 写法2:规范写法(团队常用,可读性强)
`id` bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',</pre></div>
<p class="maodian"><a name="_lab2_0_4"></a></p><h3>五、拓展:ZEROFILL零填充的实际使用(唯一用到显示宽度的场景)</h3>
<p>前面说过,显示宽度只有搭配 <code>ZEROFILL</code> 时才有实际效果,给你举个例子,帮你彻底理解,这个功能偶尔会用到(比如生成订单号、编号):</p>
<div class="jb51code"><pre class="brush:sql;">-- 创建测试表,给id加zerofill
CREATE TABLE test (
`id` bigint(6) NOT NULL AUTO_INCREMENT ZEROFILL PRIMARY KEY COMMENT '主键ID',
`name` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入数据
INSERT INTO test(name) VALUES('测试1'),('测试2'),('测试100');
-- 查询结果
SELECT * FROM test;</pre></div>
<p>查询出来的id是这样的:</p>
<div class="jb51code"><pre class="brush:sql;">id      name
000001测试1
000002测试2
000100测试100
</pre></div>
<p>✅ 效果:自动补0到指定的显示宽度6位,<strong>但底层存储的还是数字1、2、100</strong>,只是展示的时候补了0,对业务逻辑无影响。</p>
<p class="maodian"><a name="_lab2_0_5"></a></p><h3>✨ 最终总结(一句话搞定,看完就懂)</h3>
<blockquote><p><code>bigint</code> 和 <code>bigint(20)</code> 无功能区别,都是8字节的长整型,主键自增逻辑一致,存储一致,取值范围一致;唯一区别是显示宽度,<code>bigint</code>是默认的20位宽度,<code>bigint(20)</code>是手动指定,开发中用哪个都可以。</p></blockquote>
<p class="maodian"><a name="_label3_0_5_10"></a></p><h4>✅ 开发选型建议</h4>
<ol><li>个人开发/快速建表:用 <code>bigint</code> 即可,简洁高效;</li><li>团队开发/公司规范:用 <code>bigint(20)</code>,符合行业约定,可读性更好;</li><li>所有业务表主键:<strong>一律用 bigint 自增</strong>,别用int,避免数据量上来主键溢出。</li></ol>
<p>这是MySQL的基础核心知识点,很多程序员工作好几年都没搞懂,现在彻底搞懂了,以后写建表语句再也不会纠结了👍</p>
頁: [1]
查看完整版本: mysql的bigint 和 bigint(20) 主键自增的区别解析