背景
在短视频电商系统中,有很多需要产生递增的业务流水号的需求,例如:
- 订单号:D202111190000001(D+yyyyMMdd+7位递增数字)
- 用户ID:拼友0000000001(拼友+10位递增数字)
- …
这里仅介绍成本较低的基于数据库的实现,也可以基于Redis等实现,我们这里不讨论。
方案
方案一 使用Max()函数(不推荐)
使用Mysql的Max() 函数获取字段最大的那条记录的相应值。
大致伪代码如下。
select max(no) from order;
no = max(no) + 1;
insert into order values (no);
存在并发问题,要用锁解决,不推荐使用哈。
方案二 自增序列 AUTO_INCREMENT(看情况)
MySQL 自增序列是一组整数:1, 2, 3, …
一张数据表只能有一个自增主键且递增列必须使用索引。
所以这里主键id 不能设置自动递增,改为程序设置雪花ID或者UUID。
CREATE TABLE `order` (
`id` bigint(20) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`no` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `no` (`no`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;
可以使用AUTO_INCREMENT=1000 设定自增起始点
这个方案成本极低,视情况选择吧,兄弟们。
方案三 自定义序列表(推荐)
https://blog.csdn.net/weixin_42383575/article/details/103023379
CREATE TABLE `sequence` (
`name` varchar(10) NOT NULL COMMENT '业务名称 例如订单:ORDER_NO,用户:USER_NO',
`current_value` int(11) NOT NULL COMMENT '当前值,初始值',
`increment` int(11) NOT NULL DEFAULT '1' COMMENT '步长',
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP FUNCTION IF EXISTS currval;
DELIMITER $
CREATE FUNCTION currval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE value INTEGER;
SET value = 0;
SELECT current_value INTO value
FROM sequence
WHERE name = seq_name;
RETURN value;
END
$
DELIMITER ;
DROP FUNCTION IF EXISTS nextval;
DELIMITER $
CREATE FUNCTION nextval (seq_name VARCHAR(50))
RETURNS INTEGER
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
UPDATE sequence
SET current_value = current_value + increment
WHERE name = seq_name;
RETURN currval(seq_name);
END
$
DELIMITER;
INSERT INTO sequence VALUES ('ORDER_NO', 0, 1);
INSERT INTO sequence VALUES ('USER_NO', 1000, 1);
伪代码如下:
no = SELECT NEXTVAL('ORDER_NO');
insert into order values (no);
扩展
1.针对订单号D202111190000001(D+yyyyMMdd+7位递增数字)的处理。
可以在库里预生产每天的自增业务序列,例如:
INSERT INTO sequence VALUES ('ORDER_NO_20211119', 0, 1);
INSERT INTO sequence VALUES ('ORDER_NO_20211120', 0, 1);
业务使用示例如下:
no = SELECT NEXTVAL('ORDER_NO_20211119');
insert into order values (no);
2.针对用户拼友0000000001的处理。
有很多骚需求,例如666、888、999等非常雕的号码留着。可以使用代码处理下吧。
no = SELECT NEXTVAL('ORDER_NO_20211119');
insert into order values (no);
参考:
- https://blog.csdn.net/weixin_42383575/article/details/103023379
|