日期:2014-05-16  浏览次数:20549 次

MSSQL高并发时,如何避免插入重复数据+++++++++++
避免插入重复数据,一般是先用exist判断是否存在,然后再插入,在高并发时,会有插入重复数据的可能
网上搜了一圈解决方案,有给表加唯一约束的(可行),有用触发器做判断的(持怀疑态度),还有insert和exist写在一条sql里的(持怀疑态度),例如下面的:
create     proc [dbo].[Name_Add]
 @Name varchar(50)
as
begin

begin tran
insert Names (Name)
select (@Name) where not exists (select NameId from Names with(HOLDLOCK) where Name = @Name)
commit tran

select NameId,Name from Names with(nolock) where Name = @Name
end

说是可以解决高并发重复插入相同值的问题,
但据我所知,当表里没有@name这条数据时,holdlock不会对任何记录加锁,还是会插入重复的name啊,

大家看看上面这个能解决高并发下不插入重复值的问题吗?我认为是不行的,除非DBMS执行sql是一条条串行的,不会并发的
------解决方案--------------------
HOLDLOCK是SQL的最高隔离级别 可串行化 这个容易导致阻塞 不建议使用。
------解决方案--------------------
可用索引选项(IGNORE_DUP_KEY)过滤而不抛出错误

GO
CREATE TABLE #Test (C1 INT);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C1)
    WITH (IGNORE_DUP_KEY = ON);
GO
INSERT INTO #Test VALUES (1);
INSERT INTO #Test VALUES (1); --已忽略重复的键。

GO
SELECT COUNT(*)AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
/*

1
*/



------解决方案--------------------
引用:
Quote: 引用:

可用索引选项(IGNORE_DUP_KEY)过滤而不抛出错误

GO
CREATE TABLE #Test (C1 INT);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C1)
    WITH (IGNORE_DUP_KEY = ON);
GO
INSERT INTO #Test VALUES (1);
INSERT INTO #Test VALUES (1); --已忽略重复的键。

GO
SELECT COUNT(*)AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
/*

1
*/



谢谢你的办法,不过由于某些原因,无法用唯一约束来做,所以才来论坛求教,
另外我想问的是主题里的sql真能避免高并发重复插入的问题嘛?

通过SQL本身的机制避免重复能做到,但会影响性能。
无论是HOLDLOCK还是唯一索引都可以避免重复数据的插入,但必然会降低处理效率。
一般来说设计系统时,如果考虑到有大并发量的插入更新操作,都会进行相应的优化处理,主要手段包括分库、分表、队列、异步处理之类的,通过种种手段减少单个表在同一时间的操作数,以达到系统需要的效率为目标。
------解决方案--------------------
引用:
Quote: 引用:

可用索引选项(IGNORE_DUP_KEY)过滤而不抛出错误

GO
CREATE TABLE #Test (C1 INT);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C1)
    WITH (IGNORE_DUP_KEY = ON);
GO
INSERT INTO #Test VALUES (1);
INSERT INTO #Test VALUES (1); --已忽略重复的键。

GO
SELECT COUNT(*)AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
/*

1
*/



谢谢你的办法,不过由于某些原因,无法用唯一约束来做,所以才来论坛求教,
另外我想问的是主题里的sql真能避免高并发重复插入的问题嘛?
不能避免,只能忽略。高并发情况下,可能不能单纯靠SQL来避免,听说比较好的方案是前端处理再结合sqlserver自身机制,但是由于略微机密,所以没告诉我怎么实现