Sql 死锁发生在1个表上,2个用户执行简单语句

Sql 死锁发生在1个表上,2个用户执行简单语句,sql,sql-server,sql-server-2012,deadlock,database-deadlocks,Sql,Sql Server,Sql Server 2012,Deadlock,Database Deadlocks,最终解决方案 实际上,我们所做的是通过创建一个工作表和会话ID绕过逐行插入,并拥有一个存储过程,该过程一次从临时表删除并插入到主表。没有更多的僵局 最后程序: 从表格工作中删除(使用sessionID,以防万一…) 插入表格工作(使用ADODB逐行插入) 我调用一个执行以下操作的存储过程: 开始交易 从表格中删除(带有一些 条件) 将表格工作(1)插入表格 (声明) 承诺 从表格工作中删除(清理) 我们确实认为这是因为索引锁,但我正在等待DBA的确认(解释) 隔离级别没有改变任何事情(我

最终解决方案
实际上,我们所做的是通过创建一个工作表和会话ID绕过逐行插入,并拥有一个存储过程,该过程一次从临时表删除并插入到主表。没有更多的僵局
最后程序:

  • 从表格工作中删除(使用sessionID,以防万一…)
  • 插入表格工作(使用ADODB逐行插入)
  • 我调用一个执行以下操作的存储过程:
    • 开始交易
    • 从表格中删除(带有一些 条件)
    • 将表格工作(1)插入表格 (声明)
    • 承诺
  • 从表格工作中删除(清理)
我们确实认为这是因为索引锁,但我正在等待DBA的确认(解释)

隔离级别没有改变任何事情(我们尝试了所有的可能性,甚至打开和关闭了READ_COMMITTED_快照)


我有一个应用程序,当两个用户同时“写入”数据库时,会导致数据库死锁。它们不处理相同的数据,因为它们具有不同的id,但它们处理相同的表

用户1(id=1),用户2(id=2)

过程

User 1 does : 1 DELETE statement, followed by 3000 INSERT
User 2 does : 1 DELETE statement, followed by 3000 INSERT 

User 2 DELETE in the middle of user 1 INSERT (example : after 1500). Result in Deadlock. 
Run-time error '-2147457259 (80004005)':
Transaction (Process ID76) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 
语句(示例,但它们有效)

我使用ADODB(Microsoft Access…),因此我执行一个简单的查询,例如:

ConnectSQLServer.Execute "DELETE or INSERT statement"
错误消息

User 1 does : 1 DELETE statement, followed by 3000 INSERT
User 2 does : 1 DELETE statement, followed by 3000 INSERT 

User 2 DELETE in the middle of user 1 INSERT (example : after 1500). Result in Deadlock. 
Run-time error '-2147457259 (80004005)':
Transaction (Process ID76) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 
其他信息

  • 没有涉及任何事务,只有简单的插入或删除查询, 一个接一个
  • 没有涉及记录集,也没有打开的记录集
  • 我们试图寻找死锁跟踪,但没有显示任何图形,DBA试图了解原因
  • 我想理解为什么他们会彼此陷入僵局,而不只是“等待”另一个结束!我怎样才能做得更好?=)
  • 访问:它是一个带有SQL Server后端的访问前端。没有链接表,vba代码通过ADODB连接推送查询
编辑:死锁图
在左边我们有1条(共3000条)INSERT语句,在右边是DELETE语句。

更新
我删除了DELETE语句中使用的列上的索引,我不能再重现死锁了!不是一个干净的解决方案,而是暂时的。我们考虑在一个临时表中插入3000行,然后一次从临时表复制到表中(在存储过程中删除和插入)

谢谢


Séb

删除
将在页面上保持更新锁定:

更新(U)

用于可更新的资源防止常见形式的 当多个会话正在读取、锁定和关闭时发生的死锁 以后可能会更新资源。

INSERT
将在同一页面上保留一个意向/独占锁

独家(X)

用于数据修改操作,如插入、更新或 删除确保不能对同一个数据库进行多个更新 同时提供资源。

意图

用于建立锁层次结构。意向锁的类型有: 意向共享(IS),意向独占(IX),与意向共享 独家(六)

如果希望同时运行两个查询, 每个人都必须在给定的时间等待对方

如果整个插入集合不需要回滚,我建议您在单独的事务中运行每个插入。
或者,尝试删除并行化,或者在不同的时间执行这些操作

简而言之:
1) 在进行下一次插入之前,请确保每个插入都已正确提交。
2) 或者尽量避免同时执行这两个操作

另一种猜测是调整产生问题的会话的事务隔离级别。检查以下文档

参考资料:


什么是“仅简单的逐个插入或删除查询”?这听起来像是你在用一个循环?但我也有点困惑。99.999%的问题显然是sql server,但随后您提到了访问权限。是否访问前端,所有处理都在sql server中?获取a如果您想了解死锁,则需要一个。没有两条路可走。如果你有丰富的经验,你可以对什么是僵局以及如何最好地解决僵局进行有根据的猜测,但即便如此,这也是危险的,因为你仍然可以很容易地猜错。如果没有跟踪,我有根据地猜测您的表有多个索引,
INSERT
DELETE
以不同的、不兼容的顺序锁定它们,这通常是通过策略性地增加锁定来解决的。但这只是一个猜测。您是否连接到sql server 2012并将access用作链接表?@SeanLange和M。Hassan:很抱歉访问混乱:它只是前端,没有链接表,我们使用VBA对sql server执行ADODB查询。是的,有一个“循环”模式,因为用户输入内容并生成大约3000条INSERT语句,所有语句一次发送到数据库(一个接一个)。感谢您的回答@Hybris95。我们不使用事务,只将每个查询一个接一个地发送到SQL Server。据我所知,两个不同的用户同时执行1次插入和1次删除操作会导致死锁。这将很难阻止,因为查询字符串是由客户端而不是服务器端发送的。我想知道他们是否可以完全独立(一个接一个地发生)。我尝试了BEGIN TRANS和COMMIT,这两个语句导致了死锁。另一种选择是在数据库中设置一个“设置”,每个进程都会调用它来询问它们是否可以写入。看起来您的应用程序隐式地为整个insert/delete语句创建了一个事务。使用transa