1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > mysql存入订单号不重复_MSSQL高并发下生成连续不重复的订单号

mysql存入订单号不重复_MSSQL高并发下生成连续不重复的订单号

时间:2023-05-23 21:50:58

相关推荐

mysql存入订单号不重复_MSSQL高并发下生成连续不重复的订单号

一、确定需求

只要做过开发的基本上都有做过订单,只要做过订单的基本上都要涉及生成订单号,可能项目订单号生成规则都不一样,但是大多数规则都是连续增长。

所以假如给你一个这样的需求,在高并发下,以天为单位,生成连续不重复的订单号,比如4月12日有1000条订单,那么当天的订单号是170412001至1704121000,第二天13号又有2000条订单就是170413001至1704132000。

二、实现需求

首先我们建立一个订单表

CREATE TABLE [dbo].[tbOrder]([ID] [int] IDENTITY(1,1) NOT NULL,[OrderNo] [varchar](50) NULL,[InputTime] [datetime] NULL,CONSTRAINT [PK_tbOrder] PRIMARY KEY CLUSTERED([ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])ON [PRIMARY]

GO

表中只有自增ID,订单编号,录入时间三列。

然后开始在代码里面生成订单号。

1 public static stringGetOrderNo()2 {3 string result = string.Empty;4 using (IDbConnection conn =SqlHelper.OpenConnection())5 {6 string sql = "SELECT ISNULL(COUNT(*),0)+1 FROM tbOrder WHERE DATEDIFF(DAY,InputTime,GETDATE())=0";7 int num = conn.ExecuteScalar(sql);8 if (num < 1000)9 {10 result = num.ToString().PadLeft(3, '0');11 }12 else

13 {14 result =num.ToString();15 }16 }17 result = DateTime.Now.ToString("yyMMdd") +result;18 returnresult;19 }

接着我们开10个线程,每个线程都执行插入100次订单表,每次插入之前都从这个方法里获取订单编号。

1 static void Main(string[] args)2 {3 for (int i = 0; i < 10; i++)4 {5 Thread thread = new Thread(newThreadStart(InserOrder));6 thread.Start();7 }8 }9

10 public static voidInserOrder()11 {12 using (IDbConnection conn =SqlHelper.OpenConnection())13 {14 for (int i = 0; i < 100; i++)15 {16 conn.Execute("INSERT INTO tbOrder(OrderNo,InputTime)VALUES(@OrderNo,GETDATE())", new { OrderNo =GetOrderNo() });17 }18 }19 }

运行一下,看结果如何。

结果不出所料,一塌糊涂!

三、调整战略

因此,我们要改变思路和战略,重点是订单编号不能根据当前订单总数的基础上加1那么简单了,而是必须有一个ID池,给每次请求分发ID,用后即弃。

相当于去银行办理业务,进去就会让你去机器领号,叫到你的号码的时候才可以去办理业务。

那么谁来当这个ID池呢?

这里有三个方案:

1.SQL表

2.Redis的Incr

3.队列

这里我使用的第一种。

首先我们建立一张表,用来存放ID

CREATE TABLE [dbo].[tbDocID]([PreName] [varchar](50) NOT NULL,--标识,用于区分不同的业务[ID] [int] NOT NULL, --用于自增的列,每次用后自增加1CONSTRAINT [PK_tbDocID] PRIMARY KEY CLUSTERED([PreName] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])ON [PRIMARY]

GO

然后创建一个存储过程,存储过程主要负责根据这张表返回ID

--根据前导字符获取ID值--参数:前导字符--返回:字符串

CREATE PROCEDURE [dbo].[sp_GetOrderNo](@PreName varchar(20)

)AS

BEGIN TRAN

SET NOCOUNT ON

--1、定义变量

Declare @ReturnValue varchar(10),@OrderID varchar(20),@ID int,@StrID varchar(10),@IDLen int

Declare @DocLen int

Set @DocLen=10

--2、取出当前ID值+1,然后更新当前的值

Select @ID=ID+1 From [tbDocID] WITH(ROWLOCK,UPDLOCK) where PreName=@PreName

IF ISNULL(@ID,0)=0 Set @ID=0

IF @ID=0

BEGIN

INSERT INTO [tbDocID]WITH(HOLDLOCK)(PreName,ID)VALUES(@PreName,0)SET @ID=1

END

Update [tbDocID] Set ID=ID+1 where PreName=@PreName

--3、处理ID的长度

Set @StrID=convert(varchar(10),@ID)Set @IDLen=Len(@StrID)Select @StrID=CASE @IDLen

WHEN 1 THEN '00'+@StrID

WHEN 2 THEN '0'+@StrID

ELSE @StrID

End

Set @ReturnValue=@StrID

--4、返回

Set @OrderID=@ReturnValue

Select @OrderID asDocIDCOMMIT TRAN

RETURN

GO

修改获取订单编号的方法,从存储过程中获取

public static string GetOrderNo(stringprefix)

{string result = string.Empty;

DynamicParameters param= newDynamicParameters();

param.Add("@PreName", prefix);using (IDbConnection conn =SqlHelper.OpenConnection())

{string returnValue = conn.Query("sp_GetDocID", param, null, true, null, CommandType.StoredProcedure).FirstOrDefault();if (!string.IsNullOrEmpty(returnValue))

{

result=returnValue;

}

}

result= DateTime.Now.ToString("yyMMdd") +result;returnresult;

}

四、测试

最后一波测试

static void Main(string[] args)

{for (int i = 0; i < 10; i++)

{

Thread thread= new Thread(newThreadStart(InserOrder));

thread.Start();

}

}public static voidInserOrder()

{using (IDbConnection conn =SqlHelper.OpenConnection())

{for (int i = 0; i < 100; i++)

{string perfix = string.Format("ORDER_{0}", DateTime.Now.ToString("yyMMdd"));

conn.Execute("INSERT INTO tbOrder(OrderNo,InputTime)VALUES(@OrderNo,GETDATE())", new { OrderNo =GetOrderNo(perfix) });

}

}

}

结果:

作者:黄昌

出处:/h-change/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。