关于生成并发唯一性流水号的解决方案
关于生成并发唯一性流水号的解决方案
看了文章《弃用数据库自增ID,曝光一下我自己用到的解决方法 》,居然还显示到首页上去。我却觉得如果新手不辨真假,盲目顺从,那么会造成误人子弟的事实。
首先从作者的写这篇文章的目的上讲他想实现的无非是下面
目的:
1、不用自增长ID,因为自增长移植的时候不方便。
2、这个存储过程可以很高效的产生唯一性的自增长ID
从我小虎的认知上来回答:
1、对于作者的第一点,完全可以用Guid来替代自增长,或者在移植的时候,可以先去掉自增长的属性。有的人说Guid性能比不上自增长ID,这里我们先不讨论这一点,个
人认为效率问题主要体现在索引技巧上。
2、关键是作者的第二点,完全是不正确的,也是我写这篇文章的首要目的。因为这个存储过程根本就没有实现在多并发(多用户)的情况下能真正产生唯一性的主键ID。
我们看原作者的代码:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

请看我的测试代码以及并发结果图





















结果图1

从上面多线程的测试效果上来说,绝对不要去按照原
作者的方法去做。
不厚道,说我只说不做,所以,我打算就再写一个切实可行的例子,供大家参考,仅仅作为抛砖引玉。
但是本人是经过多线程测试的,至少在我测试情况下
不会出现并发出差错的情况。
1、表结构和效果图,这个表是用来存储基础因子的,需要的可以拓展字段,比
如,升序,降序,起始序号等。









(PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,





2

3

4

5

6

7

8

GetSerialNo
9

10

11

12

13

14

15

16

17

18

19

20

21

22

锁定该条记录,好多人用lock去锁,起始这里只要执行一句update就可以了
23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

![]() |
![]() |
![]() |
第一张图(左)是单独对进货单执行循环多进程
第二张图(中)是单独对发货单执行循环多进程
第三张图(右)是对进货单发货单同时执行循环多进程
也就是上面三个Thread,自己注释测试就可以了。
测试并发代码
1protected void Page_Load(object sender, EventArgs e)
2 {
3 if (!IsPostBack)
4 {
5 for (int i = 0; i < 100; i++)
6 {
7 System.Threading.Thread temp = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
8 System.Threading.Thread temp2 = new System.Threading.Thread(new System.Threading.ThreadStart(Run2));
9 System.Threading.Thread temp3 = new System.Threading.Thread(new System.Threading.ThreadStart(Run3));
10 temp.Start();
11 temp2.Start();
12 temp3.Start();
13 }
14 }
15 }
16
17 private void Run()
18 {
19 System.Data.SqlClient.SqlParameter[] p = {
20 new System.Data.SqlClient.SqlParameter("@sCode", "JHD") };
21 Response.Write(SqlHelper.ExecuteStoredProcedure("GetSerialNo", p).Rows[0][0].ToString() + "<br/>");
22 }
23 private void Run2()
24 {
25 System.Data.SqlClient.SqlParameter[] p = {
26 new System.Data.SqlClient.SqlParameter("@sCode", "XSD") };
27 Response.Write(SqlHelper.ExecuteStoredProcedure("GetSerialNo", p).Rows[0][0].ToString() + "<br/>");
28 }
29 private void Run3()
30 {
31 System.Data.SqlClient.SqlParameter[] p = {
32 new System.Data.SqlClient.SqlParameter("@table_name", "test"),
33 new System.Data.SqlClient.SqlParameter("@key_value",System.Data.SqlDbType.Int) };
34 p[1].Direction = System.Data.ParameterDirection.Output;
35 SqlHelper.ExecuteStoredProcedure("up_get_table_key", p);
36 Response.Write(p[1].Value.ToString() + "<br/>");
37 }
38
总结:我写的整个方法和存储
过程如果要实现流水号的话,还是相当可以的。在当前测试过程中是可以避免并发而导致数据的同步性出错的情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示