0
点赞
收藏
分享

微信扫一扫

Mysql整型类型与自增设计注意点

回溯 2022-07-27 阅读 90


出自:
<姜承尧的MySQL实战宝典 >,本人学习完了在原文又做了一些更改和总结

在真实业务场景中,整型类型最常见的就是在业务中用来表示某件物品的数量。例如上述表的销售数量,或电商中的库存数量、购买次数等。在业务中,整型类型的另一个常见且重要的使用用法是作为表的主键,即用来唯一标识一行数据。

注意点1,用BITINT做主键,而不是INT

整型结合属性 auto_increment,可以实现自增功能,但在表结构设计时用自增做主键,希望你特别要注意以下两点,若不注意,可能会对业务造成灾难性的打击:

  • 用 BIGINT 做主键,而不是 INT;
  • 自增值并不持久化,可能会有回溯现象(MySQL 8.0 版本前)。

从表 1 可以发现,INT 的范围最大在 42 亿的级别,在真实的互联网业务场景的应用中,很容易达到最大值。例如一些流水表、日志表,每天 1000W 数据量,420 天后,INT 类型的上限即可达到。

因此,用自增整型做主键,一律使用 BIGINT,而不是 INT。不要为了节省 4 个字节使用 INT,当达到上限时,再进行表结构的变更,将是巨大的负担与痛苦。

那这里又引申出一个有意思的问题:如果达到了 INT 类型的上限,数据库的表现又将如何呢?是会重新变为 1?我们可以通过下面的 SQL 语句验证一下:
创建表

CREATE TABLE t
(
a INT AUTO_INCREMENT PRIMARY KEY
);

插入int的上限

INSERT INTO t
VALUES (2147483647);

此时t表里面的数据

a

2147483647

再次插入

INSERT INTO t
VALUES (NULL);

可以看到,当达到 INT 上限后,再次进行自增插入时,会报重复错误,MySQL 数据库并不会自动将其重置为 1。
此时会报错,因为超过了int最大的范围, int范围是 -2147483648 ~2147483647
报错信息:
ERROR 1062 (23000): Duplicate entry ‘2147483647’ for key ‘t.PRIMARY’

注意点2.自增可能会存在回溯问题

第二个特别要注意的问题是,MySQL 8.0 版本前,自增不持久化,自增值可能会存在回溯问题

CREATE TABLE t
(
a INT AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO t (a)
VALUES (NULL),
(NULL),
(NULL);
SELECT *
FROM t;

此时表里面的数据是

a

1

2

3

删除a为3的数据

DELETE
FROM t
WHERE a = 3;

查看建表语句

SHOW CREATE TABLE

此时内容:

Table

Create Table

t

CREATE TABLE ​​t​​ (

​a​​​ int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (​​​a​​​)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 |

重点观察上面的AUTO_INCREMENT为4
此时我操作docker重启mysql,mysql版本是5版本

[root@zjj101 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b12e373a64e9 rabbitmq:management "docker-entrypoint.s…" 7 weeks ago Exited (255) 4 weeks ago 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, :::5672->5672/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp rabbit
7d207bd13d18 87eca374c0ed "docker-entrypoint.s…" 7 weeks ago Up 46 hours 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql-service
[root@zjj101 ~]# docker restart 7d207bd13d18

重新执行sql查看建表语句

SHOW CREATE TABLE

Table

Create Table

t

CREATE TABLE ​​t​​ (

​a​​​ int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (​​​a​​​)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 |

重启mysql之后重点观察上面的AUTO_INCREMENT从4变成3了
可以看到,在删除自增为 3 的这条记录后,下一个自增值依然为 4(AUTO_INCREMENT=4),这里并没有错误,自增并不会进行回溯。但若这时数据库发生重启,那数据库启动后,表 t 的自增起始值将再次变为 3,即自增值发生回溯。
若要彻底解决这个问题,有以下 2 种方法:

  • 升级 MySQL 版本到 8.0 版本,每张表的自增值会持久化;
  • 若无法升级数据库版本,则强烈不推荐在核心业务表中使用自增数据类型做主键。

其实,在海量互联网架构设计过程中,为了之后更好的分布式架构扩展性,不建议使用整型类型做主键,更为推荐的是字符串类型


举报

相关推荐

0 条评论