用数据库函数生成流水号,避免高并发时,流水号重复(当然最简单的方法是使用UUID,这就不多说了....)

首先说一下设计思路,最终目的是生成一个时间+六位自增流水,实例:20180524000001.

具体实现过程简述:

1.创建两个数据库:

mr_invest_id14,投资id-内存表,用于存储新生成且未使用的流水号;
tb_invest_id14,投资id-物理表,用于存储已经使用过了的流水号;

2.流水号每天从当天年月日+000000 ~ 当天年月日+999999; 

   a. 每批次生成500个,存放到内存表,使用一个内存表就会删除相应的流水号,并将其存放到物理表留痕;

   b.当内存表中的剩余未使用流水号<=50时,再依次生成500个流水号存放到内存表中,

        所生成新流水号与上一批次最后一个流水号是连续的;


实现代码如下:

CREATE TABLE `mr_invest_id14` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `seq_date` varchar(63) DEFAULT NULL COMMENT 'Serial日期',
  `seq_number` bigint(20) NOT NULL COMMENT '数值型10进制序列号',
  `seq_code` varchar(63) DEFAULT '' COMMENT '返回的SeqNo值',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `use_flag` tinyint(1) DEFAULT '0' COMMENT '使用状态:false:未使用;true:已使用',
  PRIMARY KEY (`id`),
  KEY `IDX_UseFlag` (`use_flag`) USING BTREE,
  KEY `IDX_SeqDate` (`seq_date`) USING BTREE
) ENGINE=MEMORY AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='投资id-内存表';


CREATE TABLE `tb_invest_id14` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `seq_date` varchar(63) DEFAULT NULL COMMENT 'Serial日期',
  `seq_number` bigint(20) NOT NULL COMMENT '数值型10进制序列号',
  `seq_code` varchar(63) DEFAULT '' COMMENT '返回的SeqNo值',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `use_flag` tinyint(1) DEFAULT '0' COMMENT '使用状态:false:未使用;true:已使用',
  `use_time` datetime DEFAULT NULL COMMENT '使用时间',
  PRIMARY KEY (`id`),
  KEY `IDX_UseFlag` (`use_flag`) USING BTREE,
  KEY `IDX_SeqDate` (`seq_date`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='投资id-物理表';


DROP FUNCTION IF EXISTS `getInvestId`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `getInvestId`() RETURNS varchar(16) CHARSET utf8
    COMMENT '生成投资id'
BEGIN
	DECLARE resultNo varchar(16) DEFAULT '';
	DECLARE resultSerialId bigint(20) default 0;
	

	DECLARE currDateTime datetime DEFAULT NOW();
	DECLARE serialDate varchar(16) DEFAULT DATE_FORMAT(currDateTime,'%Y%m%d');
	
	DECLARE lastSeqNumber bigint(20) default 0;
	DECLARE unUseSerialTotal int(11) default 0;

  DELETE FROM `mr_invest_id14` where `seq_date` < serialDate ;

	
	select count(1) into unUseSerialTotal from `mr_invest_id14` where `seq_date`=serialDate and `use_flag`=0 ;

	
	
	if (unUseSerialTotal <= 50) then 
		
		select  `seq_number` into lastSeqNumber   from `mr_invest_id14` where  `seq_date`=serialDate  order by seq_number desc limit 1 ;

		if(lastSeqNumber <= 0) then 
			select  `seq_number` into lastSeqNumber   from `tb_invest_id14`  where  `seq_date`=serialDate   order by seq_number desc limit 1 ;
		end if ;

		if(lastSeqNumber <= 0) then 
			
			set lastSeqNumber = 0;
		end if;	

		set @insertNumber=500;
		set @inum=0;
		while @inum < @insertNumber do  
			set @insertSerialNumber=lastSeqNumber + @inum + 1;
			set @serialCode=LPAD(@insertSerialNumber,6,'0');
			insert into  `mr_invest_id14`(`seq_date`,`seq_number`,`seq_code`,`create_time`,`use_flag`)
			values (serialDate,@insertSerialNumber,@serialCode,now(),0);
			set @inum = @inum + 1;  
		end while; 
	end if;
	
	select `id`,concat(serialDate,`seq_code`) into resultSerialId,resultNo from `mr_invest_id14` where   `seq_date`=serialDate  and `use_flag` = 0   order by `seq_number` asc limit 1;
	
	insert into `tb_invest_id14`(`seq_date`,`seq_number`,`seq_code`,`create_time`,`use_flag`,`use_time`)
	select `seq_date`,`seq_number`,concat(serialDate,`seq_code`),`create_time`,1,NOW() from `mr_invest_id14` where `id`=resultSerialId;
	delete from `mr_invest_id14` where `id`=resultSerialId;
	return resultNo;
END
;;
DELIMITER ;

结果演示:

用数据库函数生成流水号,避免高并发时,流水号重复(当然最简单的方法是使用UUID,这就不多说了....)_第1张图片

用数据库函数生成流水号,避免高并发时,流水号重复(当然最简单的方法是使用UUID,这就不多说了....)_第2张图片

用数据库函数生成流水号,避免高并发时,流水号重复(当然最简单的方法是使用UUID,这就不多说了....)_第3张图片




你可能感兴趣的:(工作记录)