sql server:仅锁定一行并在并发访问中更新它

zqry0prt  于 2021-08-13  发布在  Java
关注(0)|答案(1)|浏览(491)

在下列情况下请帮助我。
我有一张table

  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. CREATE TABLE [dbo].[Table1](
  6. [Id] [int] IDENTITY(1,1) NOT NULL,
  7. [Value] [int] NULL,
  8. CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
  9. (
  10. [Id] ASC
  11. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  12. ) ON [PRIMARY]
  13. GO

我插入了两行:(id=1,value=10),(id=2,value=20)
然后我做了以下步骤:
在一个ssms连接中,我运行了一个只锁定和更新一行的过程

  1. BEGIN TRAN;
  2. DECLARE @Value INT;
  3. SELECT @Value = Value
  4. FROM Table1 with (HOLDLOCK XLOCK ROWLOCK)
  5. WHERE Id = 1;
  6. WAITFOR DELAY '00:00:20';
  7. UPDATE Table1
  8. SET Value = @Value + 5
  9. WHERE Id = 1;
  10. COMMIT TRAN;
  11. SELECT Value
  12. FROM Table1
  13. WHERE Id = 1

然后我运行另一个ssms连接事务

  1. SELECT [Id], [Value]
  2. FROM [dbo].[Table1]
  3. WHERE Id = 2

我观察到第二个连接冻结并等待第一个事务即将结束。
我不明白为什么第二个事务要等待第一个事务。第一个事务锁定id=1的行,第二个事务只选择一个id=2的行。在我看来,第一次交易的行为就像我使用了 TABLOCKX 提示。
有人能解释一下吗,或者给个建议?谢谢!

alen0pnh

alen0pnh1#

涂抹后

  1. CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
  2. (
  3. [Id] ASC
  4. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  5. ) ON [PRIMARY]
  6. GO

所有工作与以下事务

  1. SELECT [Id]
  2. ,[Value]
  3. FROM [dbo].[Table1] with (XLOCK, ROWLOCK)
  4. where Id = 1
  5. GO

  1. BEGIN TRAN;
  2. DECLARE @Value INT;
  3. SELECT @Value = Value
  4. --FROM Table1 with (HOLDLOCK XLOCK ROWLOCK)
  5. FROM Table1 with (XLOCK ROWLOCK)
  6. WHERE Id = 1;
  7. WAITFOR DELAY '00:00:10';
  8. UPDATE Table1
  9. SET Value = @Value + 5
  10. WHERE Id = 1;
  11. COMMIT TRAN;
  12. SELECT Value
  13. FROM Table1
  14. WHERE Id = 1;

谢谢!

展开查看全部

相关问题