MySQL自增主键用完报什么错?有什么建议?

欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习

0 实验准备

我们首先通过代码输出Integer和Long最大值:

public class IDTest {
    public static void main(String[] args) {
        System.out.println("JAVA Integer.MAX_VALUE = " + Integer.MAX_VALUE);
        System.out.println("JAVA Long.MAX_VALUE = " + Long.MAX_VALUE);
    }
}

// JAVA Integer.MAX_VALUE = 2147483647
// JAVA Long.MAX_VALUE = 9223372036854775807

1 试验一

CREATE TABLE `id_test_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `value` varchar(20) DEFAULT NULL COMMENT '值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483645 DEFAULT CHARSET=utf8;

insert into id_test_1(value) values ("a");
insert into id_test_1(value) values ("b");
insert into id_test_1(value) values ("c");
insert into id_test_1(value) values ("d");

abc可以正确插入数据表:

2147483645 a
2147483646 b
2147483647 c

d不能正确插入数据表:

Duplicate entry '2147483647' for key 'PRIMARY'

2 试验二

主键ID改为无符号int类型后abcd全部可以正确插入:

CREATE TABLE `id_test_2` (
  `id` int(11) UNSIGNED  NOT NULL AUTO_INCREMENT COMMENT '主键',
  `value` varchar(20) DEFAULT NULL COMMENT '值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483645 DEFAULT CHARSET=utf8;

insert into id_test_2(value) values ("a");
insert into id_test_2(value) values ("b");
insert into id_test_2(value) values ("c");
insert into id_test_2(value) values ("d");

3 试验三

CREATE TABLE `id_test_3` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `value` varchar(20) DEFAULT NULL COMMENT '值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9223372036854775805 DEFAULT CHARSET=utf8;

insert into id_test_3(value) values ("a");
insert into id_test_3(value) values ("b");
insert into id_test_3(value) values ("c");
insert into id_test_3(value) values ("d");

abc可以正确插入数据表:

9223372036854775805 a
9223372036854775806 b
9223372036854775807 c

d不能正确插入数据表:

Duplicate entry '9223372036854775807' for key 'PRIMARY'

4 试验四

主键ID改为无符号Long类型后abcd全部可以正确插入:

CREATE TABLE `id_test_4` (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
  `value` varchar(20) DEFAULT NULL COMMENT '值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9223372036854775805 DEFAULT CHARSET=utf8;

insert into id_test_4(value) values ("a");
insert into id_test_4(value) values ("b");
insert into id_test_4(value) values ("c");
insert into id_test_4(value) values ("d");

5 试验总结

5.1 数值范围总结

Int有符号范围:[-2147483648,2147483647]
Int无符号范围:[0,4294967295]
Long有符号范围:[-9223372036854775808,9223372036854775807]
Long无符号范围:[0,18446744073709551615]

5.2 选择合适主键类型

如果希望单表可以存储尽可能多的数据,选择主键类型时Long优先于Int,无符号优先于有符号。


5.3 选择合适时机分库分表

阿里巴巴开发手册建议:单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表,如果预计三年后数据量根本达不到这个级别,请不要在创建表时就分库分表。

在业务初期可能并不用分库分表,但是随着业务发展,当单表记录数超过一定数量时就可以考虑分库分表,而不是等到自增主键用完时再分库分表,因为即使以有符号Int主键值上限分析,单表21亿数据也太多了。

分库分表原理与实际应用请参看笔者的两篇文章:

单表数据量大是否必须分表

多图详解如何不停服分库分表


欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值