带有 nolocks 和 TRANSACTION ISOLATION LEVEL READ COMMITTED 的 SQL 事务
Posted
技术标签:
【中文标题】带有 nolocks 和 TRANSACTION ISOLATION LEVEL READ COMMITTED 的 SQL 事务【英文标题】:SQL Transactions with nolocks and TRANSACTION ISOLATION LEVEL READ COMMITTED 【发布时间】:2014-06-17 20:19:36 【问题描述】:我有一个这样的存储过程。
CREATE PROCEDURE [dbo].[mysp]
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN
BEGIN TRAN
DECLARE @TrackingCode INT
SELECT @TrackingCode = DefaultsData
FROM dbo.Defaults
WHERE DefaultsID=77
UPDATE dbo.Defaults
SET DefaultsData = @PassedTrackingCode+1
WHERE DefaultsID=77
SELECT @TrackingCode
COMMIT TRAN
END
假设我们同时(同时)执行这个存储过程两次,那么在这两个时间返回的@TrackingCode
值将是多少。如果我在存储过程中的SELECT
语句上使用NOLOCK
会怎样。
【问题讨论】:
如果您希望它以可预测的方式运行,您需要使用 HOLDLOCK 进行选择 您正在使用READ COMMITTED
隔离级别。应该没问题,我认为您不会得到不一致的结果。运行它,看看你自己。
【参考方案1】:
1) 如果您的目的是生成唯一的跟踪代码,那么这是一个坏主意。你可以做这个简单的测试:
CREATE TABLE dbo.Defaults (
DefaultsData INT,
DefaultsID INT PRIMARY KEY
);
GO
INSERT INTO dbo.Defaults VALUES (21, 77);
GO
CREATE PROCEDURE [dbo].[mysp]
AS
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN
BEGIN TRAN
DECLARE @TrackingCode INT
SELECT @TrackingCode = DefaultsData
FROM dbo.Defaults
WHERE DefaultsID=77
WAITFOR DELAY '00:00:05' -- 5 seconds delay
UPDATE dbo.Defaults
SET DefaultsData = @TrackingCode+1
WHERE DefaultsID=77
SELECT @TrackingCode -- Maybe it should return the new code
COMMIT TRAN
END;
GO
然后在 SQL Server Management Studio 中打开一个新窗口 (Ctrl + N) 并执行 (F5)
EXEC [dbo].[mysp]
并打开第二个新窗口并执行(不到 5 秒)
EXEC [dbo].[mysp]
在这种情况下,您将获得相同的值。 NOLOCK
是个坏主意(一般来说),在这种情况下对您没有帮助。
2) 如果(我再说一遍,对不起)您的意图是生成唯一的跟踪代码,那么您可以使用
ALTER PROCEDURE [dbo].[mysp]
@TrackingCode INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Defaults
SET @TrackingCode = DefaultsData = DefaultsData + 1 -- It generate the new code
WHERE DefaultsID=77;
END;
GO
或者您可以使用sequences (SQL Server 2012+)。
【讨论】:
我不想使用唯一的跟踪代码。我希望每个尝试执行 sp 的用户都需要生成一个新的跟踪号,而不是相同的跟踪号。 但是当用户同时执行这个sp时,他们都得到了相同的tracking number。 我认为您建议的第二个选项会起作用。会试一试。谢谢博格丹! @user1176058:是的。您的版本可以轻松生成重复的代码(参见 #1)。试试我的解决方案(见 #2)。以上是关于带有 nolocks 和 TRANSACTION ISOLATION LEVEL READ COMMITTED 的 SQL 事务的主要内容,如果未能解决你的问题,请参考以下文章
使用 nolock 的 Java Hibernate HQL 查询