高并发插入 重复的 设计讨论

jldzy 2014-08-21 09:36:56
client端有 5 个 tomcat(在5台机器) 做了负载均衡, 现在要往一张表tba(Id, Name)里面插入数据,先判断是否存在然后再添加.
tomcat 在启动的时候会把表 tba 数据加到内存里面去,先在内存里面判断是否存在,不存在则添加。但是经常会出现重复的,现在有一种方案是:
1 在tba name 上加一个唯一约束,然后 起一个事务,先判断存在,失败就回滚并且读出 已经存在的Id,, 这种在并发高的时候性比较慢,因为事务,约束是比较消耗资源的。 大家一般是怎么设计的 ?
begin try
begin tran
select @id = Id from tba where Name=@name
if @id is null
insert into tba(Name) values(@name)
set@id = @@IDENTITY
commit tran
end try
begin catch
select @id = Id from tba where Name=@name
end catch
...全文
211 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
---涛声依旧--- 2014-08-21
  • 打赏
  • 举报
回复
1、前台程序可这样处理,报错后仍往下执行 如:vb程序的: on error resume next sSQL="insert into tba(Name) values(@name)" ..... 2、后台可以这样处理:

--不用加事务
insert into tba(name) SELECT '123' WHERE NOT EXISTS(SELECT * FROM  tba WHERE [Name]='123')
Tiger_Zhao 2014-08-21
  • 打赏
  • 举报
回复
上面的 @@IDENTITY 不要,我把它看成 IDENTITY() 了,
Tiger_Zhao 2014-08-21
  • 打赏
  • 举报
回复
先给 Name 加上唯一索引
BEGIN TRY
insert into tba(id,Name) values(@@IDENTITY,@name)
END TRY
BEGIN CATCH
--SQL Server 会在索引(内存)中检查唯一约束,产生的重复错误忽略掉
END CATCH
select @id = Id from tba where Name=@name
KeepSayingNo 2014-08-21
  • 打赏
  • 举报
回复
我的建议是建一个中间表,中间表不做任何约束,5台机器直接往中间表插数据,然后用一个job在每天凌晨的时候对中间表中的数据进行迁移,迁移的时候可以做判断,这样的话就比较快
jldzy 2014-08-21
  • 打赏
  • 举报
回复
好的,按照你的方案进行测试下,大概数据量会在1000w 左右,
Tiger_Zhao 2014-08-21
  • 打赏
  • 举报
回复
在内存中检索索引算什么消耗?
只是查找存在,根本没有任何冲突。
jldzy 2014-08-21
  • 打赏
  • 举报
回复
如果并发高的话,其不是非常消耗数据库性能
Tiger_Zhao 2014-08-21
  • 打赏
  • 举报
回复
唯一索引会检查是否存在,存在则报错。
插入不成功,取的是存在记录的ID。
插入成功了,取的是新加记录的ID。
总之保证这个name有且仅有一个ID。
jldzy 2014-08-21
  • 打赏
  • 举报
回复
先给 Name 加上唯一索引 BEGIN TRY insert into tba(id,Name) values(@@IDENTITY,@name) END TRY BEGIN CATCH --SQL Server 会在索引(内存)中检查唯一约束,产生的重复错误忽略掉 END CATCH select @id = Id from tba where Name=@name 这个开始不要判断 是否存在? 如果存在则返回一个 ID 出去

34,576

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧