如何处理网站中的sql并发问题

时间:2013-05-23 22:50:24

标签: sql-server asp.net-mvc sql-server-2008 entity-framework

我正在使用asp.net mvc创建一个网站。我有一个看起来像这样的表

Create Table Items(
   [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
   [Colname] [nvarchar](20) NOT NULL
   //OTHER UNIMPORTANT COLS HERE
)

ALTER TABLE Items ADD CONSTRAINT UN_Colanme UNIQUE(Colname)

从我的网站,我经常尝试创建新项目,或从数据库中选择项目(使用实体框架)。这是它在c#中的外观。

var item = db.Items.FirstOrDefault(i => i.Colname == "foo");
if(item == null)
{
   item = new Item("foo");
   db.Items.Add(item);
}

//some stuff with item
db.SaveChanges();

有时,2个请求同时进入,都试图创建具有相同colname的项目。虽然唯一约束阻止数据库存储任何错误值,但尝试保存更改会引发异常,因为违反了约束。

捕获此异常是否正常处理此问题?如果不是上面的c#代码,我是否可以获得良好的性能,我创建了一个锁定表的存储过程,然后只有在允许的情况下才插入新行,然后返回该行?这是常见的吗?

2 个答案:

答案 0 :(得分:1)

嗯,有很多方法可以做到这一点。我想说在这种情况下捕获异常是最便宜的。另一种方法是将事务隔离级别提升到更高的级别,如Serializable。

在这种情况下,我只会捕获唯一约束违规并继续。如果我们在编程术语中考虑它,我们可以考虑像double-checked locking这样的情况,因为我们检查,它不在那里,然后进入交易,看到它在那里,然后我们可以放弃我们的价值和使用那里的那个。

答案 1 :(得分:0)

这就是为什么许多开发人员使用GUID或DB分配的Ints作为唯一键。如果您的外部密钥是合法分配的并且是逻辑副本,那么请使用数据库重复约束,如您所示或考虑使用pessemistic锁。 Sql server有一个你可以使用的工具。搜索示例和博客

  • 使用Guid密钥
  • 使用DB allocate Int作为密钥
  • 使用列约束并捕获异常(如您所解释的)
  • 使用悲观锁定,例如SQL内置功能
  

在网上搜索“SQL server sp_getapplock”,了解如何使用。