Sql server SQL Server事务隔离问题-全局变量

Sql server SQL Server事务隔离问题-全局变量,sql-server,tsql,sql-server-2008,Sql Server,Tsql,Sql Server 2008,SQL Server 2008 R2(我想是数据中心版) 我对数据库有一个非常具体的要求 我需要插入一行标记有时间戳[ChangeTimeStamp]。时间戳值作为参数传递。时间戳必须是唯一的 两个进程可以同时插入值,我偶尔会遇到重复的键插入。为了避免这种情况,我正在尝试: declare @maxChangeStamp bigint set transaction isolation level read committed begin transaction select @maxCha

SQL Server 2008 R2(我想是数据中心版)

我对数据库有一个非常具体的要求

我需要插入一行标记有时间戳
[ChangeTimeStamp]
。时间戳值作为参数传递。时间戳必须是唯一的

两个进程可以同时插入值,我偶尔会遇到重复的键插入。为了避免这种情况,我正在尝试:

declare @maxChangeStamp bigint

set transaction isolation level read committed
begin transaction 
select @maxChangeStamp = MAX(MaxChangeTimeStamp) from TSMChangeTimeStamp

if (@maxChangeStamp > @changeTimeStamp)
    set @maxChangeStamp = @maxChangeStamp + 1   
else 
    set @maxChangeStamp = @changeTimeStamp

update TSMChangeTimeStamp 
set MaxChangeTimeStamp = @maxChangeStamp 
commit

set @changeTimeStamp = @maxChangeStamp

insert statment
  • 可重复读取-导致死锁
  • 读取已提交-导致重复的密钥插入
@changeTimeStamp
是我的参数。
tsmchangetimstamp
只保存一个值


如果有人知道如何解决这个问题,我将非常感谢任何帮助。

在事务内部,如果模式为“读取提交”或“快照隔离”,SELECT语句将获取共享锁。如果两个进程同时启动SELECT,它们都将获得一个共享锁

稍后,UPDATE语句尝试获取独占锁(或UPDATE锁)。不幸的是,两个进程都不能获得独占锁,因为另一个进程有一个共享锁

尝试在SELECT语句中使用。从MSDN:

上锁

指定要获取并保持更新锁,直到 事务完成。UPDLOCK为读取操作获取更新锁 仅在行级别或页面级别。如果UPDLOCK与 TABLOCK,或由于其他原因而使用表级锁 将取而代之的是独占(X)锁

指定UPDLOCK时,READCOMMITTEDLOCK和READCOMMITTEDLOCK 将忽略隔离级别提示。例如,如果隔离级别 会话的类型设置为可序列化,查询指定(UPDLOCK, READCOMMITTED),READCOMMITTED提示将被忽略,事务 使用可序列化隔离级别运行

例如:

begin transaction
select @maxChangeStamp = MAX(MaxChangeTimeStamp) from TSMChangeTimeStamp with (updlock) 
请注意,如果表()没有索引,则更新锁可能升级为表锁

明确请求XLOCK也可能有效


还要注意,UPDATE语句没有WHERE子句。这会导致更新锁定并更新表中的每条记录(如果适用于您的情况).

在事务内部,如果模式不是读取提交或快照隔离,则SELECT语句将获取共享锁。如果两个进程同时启动SELECT,则它们都将获取共享锁

稍后,UPDATE语句尝试获取独占锁(或UPDATE锁)。不幸的是,两个进程都不能获取独占锁,因为另一个进程具有共享锁

尝试在SELECT语句上使用。从MSDN:

上锁

指定要获取并保持更新锁,直到 事务完成。UPDLOCK为读取操作获取更新锁 仅在行级别或页级别。如果UPDLOCK与 TABLOCK,或由于其他原因而使用表级锁 将取而代之的是独占(X)锁

指定UPDLOCK时,READCOMMITTEDLOCK和READCOMMITTEDLOCK 忽略隔离级别提示。例如,如果 会话的类型设置为可序列化,查询指定(UPDLOCK, READCOMMITTED),READCOMMITTED提示将被忽略,事务 使用可序列化隔离级别运行

例如:

begin transaction
select @maxChangeStamp = MAX(MaxChangeTimeStamp) from TSMChangeTimeStamp with (updlock) 
请注意,如果表()没有索引,则更新锁可能升级为表锁

明确请求XLOCK也可能有效


另请注意,UPDATE语句没有WHERE子句。这会导致UPDATE锁定并更新表中的每条记录(如果适用于您的情况)。

如果不读取增量更新,则无论您如何尝试,都会失败。始终更新并使用OUTPUT子句更新新值:

update TSMChangeTimeStamp 
   set MaxChangeTimeStamp  += 1
   output inserted.MaxChangeTimeStamp;
如果需要,您可以在T-SQL中捕获输出值。但是,尽管这可以满足您的要求,但您肯定不想这样做,特别是在一个足以运行DC edition的高端系统上。生成下一个时间戳将在时间戳资源上放置一个X锁,从而防止每次其他传输从生成新的时间戳到提交当前事务的操作。您可以实现工作的完全序列化,同时只有一个事务处于活动状态。性能将一落千丈


您必须重新审视您的需求,并提出一个更合适的需求。因为现在您的需求也可以表示为“我的系统太快了,我该怎么做?它真的太慢了?”。

您不阅读增量更新,无论您如何尝试,这都将失败。始终更新并使用OUTPUT子句来获得新值:

update TSMChangeTimeStamp 
   set MaxChangeTimeStamp  += 1
   output inserted.MaxChangeTimeStamp;
如果需要,您可以在T-SQL中捕获输出值。但是,尽管这可以满足您的要求,但您肯定不想这样做,特别是在一个足以运行DC edition的高端系统上。生成下一个时间戳将在时间戳资源上放置一个X锁,从而防止每次其他传输从生成新的时间戳到提交当前事务的操作。您可以实现工作的完全序列化,同时只有一个事务处于活动状态。性能将一落千丈


您必须重新审视您的需求,并提出一个更合适的需求。因为现在您的需求也可以表示为“我的系统太快了,我该怎么做?它真的太慢了?”。

您的
UPDATE
语句没有
其中
表只有一行吗?如果是,为什么要使用
MAXSELECT
中使用code>,或者甚至使用单独的
SELECT
语句。时间戳从何处获得,或者是如何生成的?TSMChangeTi是什么