sql - SQL Server:仅锁定一行并在并发访问中更新它
问题描述
请在以下情况下帮助我。
我有一张桌子
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table1](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Value] [int] NULL,
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
我插入了两行:(id = 1, value = 10), (id = 2, value = 20)
然后我做了以下步骤:
在一个 SSMS 连接中,我运行一个程序应该只锁定和更新一行
BEGIN TRAN;
DECLARE @Value INT;
SELECT @Value = Value
FROM Table1 with (HOLDLOCK XLOCK ROWLOCK)
WHERE Id = 1;
WAITFOR DELAY '00:00:20';
UPDATE Table1
SET Value = @Value + 5
WHERE Id = 1;
COMMIT TRAN;
SELECT Value
FROM Table1
WHERE Id = 1
之后我运行另一个 SSMS 连接事务
SELECT [Id], [Value]
FROM [dbo].[Table1]
WHERE Id = 2
我观察到第二个连接冻结并等到第一个事务即将结束。
我不明白为什么第二笔交易要等第一笔。第一个事务锁定 id=1 的行,第二个事务只选择一个 id=2 的行。在我看来,第一笔交易就像我使用了TABLOCKX
提示一样。
有人可以解释一下,或者给个建议吗?谢谢!
解决方案
申请后
CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
以下交易一切正常
SELECT [Id]
,[Value]
FROM [dbo].[Table1] with (XLOCK, ROWLOCK)
where Id = 1
GO
和
BEGIN TRAN;
DECLARE @Value INT;
SELECT @Value = Value
--FROM Table1 with (HOLDLOCK XLOCK ROWLOCK)
FROM Table1 with (XLOCK ROWLOCK)
WHERE Id = 1;
WAITFOR DELAY '00:00:10';
UPDATE Table1
SET Value = @Value + 5
WHERE Id = 1;
COMMIT TRAN;
SELECT Value
FROM Table1
WHERE Id = 1;
谢谢!
推荐阅读
- javascript - 如何使用 Vue.js 设置文本节点的样式?
- node.js - 错误:找不到模块 \node_modules\sqlite3\lib\binding\electron-v8.0-win32-x64\node_sqlite3.node'
- python - Python 3 CSV writer 拆分包含逗号的行
- r - 如何过滤以前大于特定值的时间序列中的值
- python - 查找数组的numpy数组的特征值
- java - 尝试在 java 中读取文本文件 - 错误:目录文件不存在 - LINUX
- mysql - 登录 PhpMyAdmin 时出现错误代码 200
- php - PHP / SQL:成功更新数据行但出现PHP致命错误
- javascript - 如何在chrome中缓存大文件?
- java - 为什么我不能使用这种运算符组合来使 NOR 适应 Java