最终解决方案
我们实际上做的是通过创建一个工作表&而绕过逐行插入。会话ID,并且具有从临时表到主表的DELETE和INSERT的存储过程。没有更多的僵局!
最后的过程:
我们认为这是因为索引锁定,但我正在等待DBA的确认(解释here)。
隔离级别没有任何改变(我们尝试了所有可能性,甚至打开和关闭READ_COMMITTED_SNAPSHOT)
我有一个应用程序,当2个用户同时“写入”数据库时,会导致数据库死锁。它们不能处理相同的数据,因为它们具有不同的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.
语句(示例,但它们有效)
DELETE FROM dbo.TheTable WHERE id = 1 /* Delete about 3000 lines */
INSERT INTO dbo.TheTable (id, field2, field3) VALUE (1 , 'value2','value3')
我使用ADODB(Microsoft Access ...)所以我执行一个简单的查询执行,例如:
ConnectSQLServer.Execute "DELETE or INSERT statement"
错误消息
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.
其他信息
编辑:死锁图
在左边我们有一个(3000)INSERT语句,在右边一个DELETE。
更新
我删除了DELETE语句中使用的列的索引,我再也无法重现死锁!不是一个干净的解决方案,但是暂时我们考虑临时表中的INSERT 3000行,然后一次从临时表复制到TheTable(存储过程中的DELETE和INSERT)。
谢谢,
SEB
答案 0 :(得分:0)
DELETE
将在页面上保留更新锁定:
更新(U)
用于可以更新的资源。 防止常见的形式 多个会话正在读取,锁定和发生时发生的死锁 可能会在以后更新资源。
INSERT
将在同一页面上持有意图/排他锁。
独家(X)
用于数据修改操作,例如INSERT,UPDATE或 删除。 确保无法对其进行多次更新 资源同时。
意图
用于建立锁定层次结构。意图锁的类型是: 意图共享(IS), 意图独占(IX) ,并与意图共享 独家(SIX)。
如果您希望同时运行两个查询, 每个人都必须在给定的时间等待另一个人。
如果整套插入不需要回滚,建议您在单独的事务中运行每个插入。
或者,尝试删除并行化,或在不同时间执行这些操作。
简短:
1)在进入下一个INSERT之前,尽量确保每个INSERT都正确提交
2)或者尽量避免同时进行两种操作
另一个猜测是调整产生问题的会话的事务隔离级别。请查看以下文档。