首页新闻找找看学习计划

请教大拿们一个MSSQL数据库并发时表ID重复问题

0
悬赏园豆:80 [已关闭问题] 关闭于 2012-09-11 10:40

目前碰到一个问题,表A的ID列为整形自增列,由于项目需要需从该表获取一新ID,ID不能重复,获取ID和正常insert语句在并发时,存在ID重复情况,请高手们指点。 获取ID的SQL代码如下

                DECLARE @nextId int;
                BEGIN TRANSACTION;
                    SELECT @nextId=IDENT_CURRENT( '表名' ) +1;
                    DBCC CHECKIDENT( '表名',RESEED, @nextId);
                    SELECT @nextId;
                COMMIT TRANSACTION;
问题补充:

本问题的主要目的是如何控制用户A执行INSERT时,用户B获取表ID并设置ID种子增1,两者ID不重复?

------------------------

20120818

谢谢各位的回复,目前尚未得到满意答案,问题继续等待高手解决。

行野摄色的主页 行野摄色 | 初学一级 | 园豆:126
提问于:2012-08-13 15:51
< >
分享
所有回答(9)
0

select @@identity

悟行 | 园豆:12163 (专家六级) | 2012-08-13 16:46

谢谢您的回答。以上语句是在插入数据后获取到当前值,但我只需ID值,不想做数据插入操作,同时这个ID种子还需增加,否则的话,通过insert插入数据时,就会存在重复了。

支持(0) 反对(0) 行野摄色 | 园豆:126 (初学一级) | 2012-08-13 16:53

@Shijun.Huang.HI: 直接查询当前identity那一列最大的值。再加一。

支持(0) 反对(0) 悟行 | 园豆:12163 (专家六级) | 2012-08-13 17:42
2

要不不要自动增长,主键从主键表里取,取主键值的方法加上锁,同时只能执行一份。

会长 | 园豆:6751 (大侠五级) | 2012-08-13 17:07
0

数据还没有写入之前,多次取得的ID肯定都是相同的,并发肯定会有问题,为什么不把取ID的操作放在写入数据写入之后呢?

I,Robot | 园豆:9461 (大侠五级) | 2012-08-13 17:14

因写业务数据不在该表,无法写后取ID,仅用此表做唯一ID系列,数据在特定情况下会移到此表。出现情况,主要是A做INSERT,而同时B在做获取ID并增1操作,并发两者ID重复了。

支持(0) 反对(0) 行野摄色 | 园豆:126 (初学一级) | 2012-08-13 21:55
0

GUID

回复内容太短(最少5个字),再写点吧!

CrazyJinn | 园豆:799 (小虾三级) | 2012-08-13 17:32

GUID的确不存在此问题,但是可惜早期设计成这样,不太好修改

支持(0) 反对(0) 行野摄色 | 园豆:126 (初学一级) | 2012-08-13 21:44

@Shijun.Huang.HI: 我可以理解为你要完成的是一个批量插入的功能么?先得到不重复的ID,但是不插入,然后等缓存到了一定数量的数据的时候批量插入?

支持(1) 反对(0) CrazyJinn | 园豆:799 (小虾三级) | 2012-08-14 08:09

@CrazyJinn: 也可以这么理解,但不是插入到该表,而是其他相似表

支持(0) 反对(0) 行野摄色 | 园豆:126 (初学一级) | 2012-08-16 13:11
0

insert into 表名(...) output inserted.列名 values(...)

轻狂の书生 | 园豆:1040 (小虾三级) | 2012-08-13 21:23
0
 1 -- 回滚事务,不会回滚已经自增的ID
 2 
 3 USE tempdb
 4 
 5 IF OBJECT_ID('t1','U') IS NOT NULL DROP TABLE t1
 6 
 7 CREATE TABLE t1(c1 INT NOT NULL IDENTITY)
 8 
 9 INSERT INTO t1 DEFAULT VALUES
10 SELECT SCOPE_IDENTITY() -- 1
11 SELECT * FROM t1 -- 1
12 
13 INSERT INTO t1 DEFAULT VALUES
14 SELECT SCOPE_IDENTITY() -- 2
15 SELECT * FROM t1 -- 1,2
16 
17 BEGIN TRAN
18     INSERT INTO t1 DEFAULT VALUES
19 ROLLBACK
20 
21 SELECT SCOPE_IDENTITY() -- 3
22 SELECT * FROM t1 -- 1,2
23 
24 INSERT INTO t1 DEFAULT VALUES
25 SELECT SCOPE_IDENTITY() -- 4
26 SELECT * FROM t1 -- 1,2,4
恶灵旧都 | 园豆:202 (菜鸟二级) | 2012-08-14 02:24
0

在插入数据时加事务,锁住该表,避免幻读,设置事务的最高隔离级别set   tran   isolation   level   serializable

仅供参考

Lordbaby | 园豆:202 (菜鸟二级) | 2012-08-14 13:36

需要锁住这个表,同时只能有一个用户操作该表

支持(0) 反对(0) watercity | 园豆:208 (菜鸟二级) | 2012-08-15 13:55
0

需要锁住这个表,同时只能有一个用户操作该表

watercity | 园豆:208 (菜鸟二级) | 2012-08-15 13:55
0

如果存在很多用户操作的时候,不建议使用锁表

建议还是使用自增ID

下面的语句是每次新增或者更新的时候抛出自增ID  无需锁表

IF Not Exists(Select Top 1 ID From EL_Datas Where DataName=@DataName) 
    INSERT INTO EL_Datas(DataHtml,DataName,DataType,SelA,SelB,SelC,SelD,Rst,Score,Comps,Depts,Cats,CrtUser) 
    OUTPUT inserted.ID 
    SELECT @DataHtml,@DataName,@DataType,@SelA,@SelB,@SelC,@SelD,@Rst,@Score,@Comps,@Depts,@Cats,@CrtUser 
ELSE 
    UPDATE EL_Datas 
    SET DataHtml=@DataHtml,DataType=@DataType,SelA=@SelA,SelB=@SelB,SelC=@SelC,SelD=@SelD,Rst=@Rst,Score=@Score,Comps=@Comps,Depts=@Depts,Cats=@Cats,LstMdfUser=@LstMdfUser,LstMdfDate=getdate() 
    OUTPUT inserted.ID 
    Where DataName=@DataName
Shannon | 园豆:601 (小虾三级) | 2012-08-17 08:53

本问题关键不在此,谢谢回复

支持(0) 反对(0) 行野摄色 | 园豆:126 (初学一级) | 2012-08-18 14:53

@Shijun.Huang.HI: 

不能在表A先插入一笔空值取回ID吗?在A表多加入一个字段,IsUse(Bit)  默认值为0

  如果想减少空值行记录,可以增加用户/IP字段。

逻辑:

1、先插入一行空值,获取ID值。

  判断IsUser记录,如果为空则插入空值,不为空则取第一笔空值行ID

2、更新该ID行记录

  设置IsUse为True

 

注意,这个逻辑能解决ID重复问题,但是可能出现空值行记录 以及 内容更新时间不按ID排序。

如果这样不能解决,那你只能锁表了。

支持(0) 反对(0) Shannon | 园豆:601 (小虾三级) | 2012-08-27 09:41
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册