最近我们的一个 ASP.NET 应用程序显示了一个数据库死锁错误,我被要求检查并修复该错误。我设法找到死锁的原因是一个存储过程,它严格更新游标内的表。
这是我第一次看到这个错误,不知道如何有效地跟踪和修复它。我尝试了我知道的所有可能的方法,最后发现正在更新的表没有主键!幸运的是,这是一个身份栏。
后来我发现为部署编写数据库脚本的开发人员搞砸了。我添加了一个主键,问题就解决了。
我感到很高兴并回到我的项目中,并做了一些研究以找出导致僵局的原因......
显然,这是导致死锁的循环等待条件。没有主键的更新显然比有主键需要更长的时间。
我知道这不是一个明确定义的结论,这就是我在这里发布的原因......
这种死锁类型的可能原因是什么?(一般不是死锁)
锁定通讯缓冲区资源
此指示的系统是否内存不足且缓冲区计数超出限制?
详细错误:
事务(进程 ID 59)在与另一个进程的锁定通信缓冲区资源上发生死锁,并已被选为死锁牺牲品。重新运行事务
我有一个旧应用程序用作替代IDENTITY各种其他表中的字段的表。
表中的每一行都存储了 中LastID命名的字段的最后使用的 ID IDName。
有时,存储过程会出现死锁——我相信我已经构建了一个合适的错误处理程序;但是我很想知道这种方法是否像我认为的那样有效,或者我是否在这里吠错了树。
我相当肯定应该有一种方法可以访问这个表,而不会出现任何死锁。
数据库本身配置了READ_COMMITTED_SNAPSHOT = 1.
首先,这是表:
CREATE TABLE [dbo].[tblIDs](
[IDListID] [int] NOT NULL
CONSTRAINT PK_tblIDs
PRIMARY KEY CLUSTERED
IDENTITY(1,1) ,
[IDName] [nvarchar](255) NULL,
[LastID] [int] NULL,
);
Run Code Online (Sandbox Code Playgroud)
以及该IDName字段上的非聚集索引:
CREATE NONCLUSTERED INDEX [IX_tblIDs_IDName]
ON [dbo].[tblIDs]
(
[IDName] ASC
)
WITH (
PAD_INDEX = OFF
, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF
, DROP_EXISTING = OFF
, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = …Run Code Online (Sandbox Code Playgroud) 我已经研究这个僵局问题好几天了,无论我做什么,它都以一种或另一种方式持续存在。
首先,一般前提:我们有访问与访问项的一对多关系。
访问项目相关信息:
CREATE TABLE [BAR].[VisitItems] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[VisitType] INT NOT NULL,
[FeeRateType] INT NOT NULL,
[Amount] DECIMAL (18, 2) NOT NULL,
[GST] DECIMAL (18, 2) NOT NULL,
[Quantity] INT NOT NULL,
[Total] DECIMAL (18, 2) NOT NULL,
[ServiceFeeType] INT NOT NULL,
[ServiceText] NVARCHAR (200) NULL,
[InvoicingProviderId] INT NULL,
[FeeItemId] INT NOT NULL,
[VisitId] INT NULL,
[IsDefault] BIT NOT NULL DEFAULT 0,
[SourceVisitItemId] INT NULL,
[OverrideCode] INT NOT NULL DEFAULT 0,
[InvoiceToCentre] BIT NOT …Run Code Online (Sandbox Code Playgroud) 我有以下过程(SQL Server 2008 R2):
create procedure usp_SaveCompanyUserData
@companyId bigint,
@userId bigint,
@dataTable tt_CoUserdata readonly
as
begin
set nocount, xact_abort on;
merge CompanyUser with (holdlock) as r
using (
select
@companyId as CompanyId,
@userId as UserId,
MyKey,
MyValue
from @dataTable) as newData
on r.CompanyId = newData.CompanyId
and r.UserId = newData.UserId
and r.MyKey = newData.MyKey
when not matched then
insert (CompanyId, UserId, MyKey, MyValue) values
(@companyId, @userId, newData.MyKey, newData.MyValue);
end;
Run Code Online (Sandbox Code Playgroud)
CompanyId、UserId、MyKey 构成目标表的组合键。CompanyId 是父表的外键。此外,还有一个非聚集索引CompanyId asc, UserId asc。
它是从许多不同的线程调用的,我一直在调用相同语句的不同进程之间出现死锁。我的理解是“with (holdlock)”对于防止插入/更新竞争条件错误是必要的。
我假设两个不同的线程在验证约束时以不同的顺序锁定行(或页面),因此是死锁。
这是一个正确的假设吗? …
这是一个后续问题:https : //stackoverflow.com/questions/7684477/is-it-possible-to-set-transaction-isolation-level-snapshot-automatically
尽管READ_COMMITTED_SNAPSHOT ON.
所以我有两个问题:
注意SQL Server 在验证外键时获取共享锁,即使事务使用的是已提交读快照(使用行版本控制已提交读)或快照隔离级别。在使用这些事务隔离级别时检查事务的死锁图时请注意这一点。如果您看到共享锁,请检查是否在外键引用的对象上获取了这些锁。
我如何检查 FK 是否真的对死锁/超时情况负责,这是否意味着我可以删除这些外键以防止死锁(什么是可以接受的努力)?
注意:我只是从导致死锁的表中读取数据。
非常感谢有关此主题的任何想法。
编辑 这里是一个死锁图。也许有人可以帮助我了解导致僵局的原因。当两个事务想要写入同一个表(一个更新和一个插入,插入作为存储过程)时,似乎没有任何报告运行仅由 Web 应用程序引起。为什么它需要页锁以及如何只启用行锁?Insert-SP 已经使用TRANSACTION ISOLATION LEVEL REPEATABLE READ.
我强烈怀疑两个触发器(一个更新和一个插入)是造成死锁的原因。这是插入触发器:
CREATE TRIGGER [dbo].[CreateRMAFiDates]
ON [dbo].[RMA]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE RMA
SET [fiCreationDate]=(SELECT idDate FROM tdefDate
WHERE CONVERT(VARCHAR, INSERTED.Creation_Date, 112) = tdefDate.Text),
[fiPopDate]=(SELECT idDate FROM tdefDate
WHERE CONVERT(VARCHAR, INSERTED.POP_Date, 112) = tdefDate.Text),
[fiManufactureDate]=(SELECT idDate FROM tdefDate
WHERE …Run Code Online (Sandbox Code Playgroud) 我发现了一个僵局,似乎表明了我认为不可能的事情。死锁涉及两个进程:
1. process8cf948 SPID 63
对临时表 #PB_Cost_Excp_Process_Invoices_Work 执行 ALTER TABLE。
拥有表 #PB_Cost_Excp_Process_Invoices_Work 的 IX 锁,对象 ID 为 455743580
2. process4cb3708 SPID 72
在临时表 #PB_Cost_Excp_Process_Invoices_Work 上执行更新,它应该是它自己唯一的表副本。
在#PB_Cost_Excp_Process_Invoices_Work 上拥有 Sch-M 锁,对象 ID 为 455743580!
这应该是不可能的。我错过了什么吗?#Temporary 表真的在这两个 SPID 之间重用了吗?
这是在 SQL Server 2008 R2 Service Pack 2 和累积更新 1(版本 10.50.4260)上。
完整的未更改死锁跟踪如下。请注意这两个进程如何在具有相同表名的相同对象 ID 上运行 #PB_Cost_Excp_Process_Invoices_Work_SNIP_0000000D8519:
12/14/2012 13:46:03,spid23s,Unknown,waiter id=process8cf948 mode=X requestType=wait
12/14/2012 13:46:03,spid23s,Unknown,waiter-list
12/14/2012 13:46:03,spid23s,Unknown,owner id=process4cb3708 mode=Sch-M
12/14/2012 13:46:03,spid23s,Unknown,owner-list
12/14/2012 13:46:03,spid23s,Unknown,objectlock lockPartition=0 objid=455743580 subresource=FULL dbid=2 objectname=tempdb.dbo.#PB_Cost_Excp_Process_Invoices_Work_________________________________________________________________________________0000000D8519 id=lock371705d00 mode=Sch-M associatedObjectId=455743580
12/14/2012 13:46:03,spid23s,Unknown,waiter id=process4cb3708 mode=Sch-M …Run Code Online (Sandbox Code Playgroud) 我们从 Microsoft ADO.NET 连接器访问 MySQL。
有时我们会在 innodb 状态中看到以下死锁,并且无法确定问题的原因。看起来事务(2)正在等待并持有相同的锁?
------------------------
LATEST DETECTED DEADLOCK
------------------------
110606 5:35:09
*** (1) TRANSACTION:
TRANSACTION 0 45321452, ACTIVE 0 sec, OS thread id 3804 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s)
MySQL thread id 84, query id 3265713 localhost 127.0.0.1 famdev Updating
UPDATE people SET company_id = 1610, name = '<name>', password = '<hash>', temp_password = NULL, reset_password_hash = NULL, email = …Run Code Online (Sandbox Code Playgroud) 我遇到了陷入僵局的情况,我想我已经缩小了罪魁祸首的范围,但我不太确定我能做些什么来解决它。
这是在运行 SQL Server 2008 R2 的生产环境中进行的。
为了让您稍微简化一下情况:
我有 3 个表,定义如下:
TABLE activity (
id, -- PK
...
)
TABLE member_activity (
member_id, -- PK col 1
activity_id, -- PK col 2
...
)
TABLE follow (
id, -- PK
follower_id,
member_id,
...
)
Run Code Online (Sandbox Code Playgroud)
该member_activity表有一个定义为 的复合主键member_id, activity_id,因为我只需要以这种方式查找该表上的数据。
我也有一个非聚集索引follow:
CREATE NONCLUSTERED INDEX [IX_follow_member_id_includes]
ON follow ( member_id ASC ) INCLUDE ( follower_id )
Run Code Online (Sandbox Code Playgroud)
此外,我有一个 Schema-bound 视图network_activity,其定义如下:
CREATE VIEW network_activity
WITH SCHEMABINDING
AS
SELECT …Run Code Online (Sandbox Code Playgroud)