Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 他正好在同一时刻。当得到重复项时,update语句会在表被锁定之前在多个线程中执行。这就是为什么您在0.01%的时间内看到相同的值。比赛条件是那些被身份和顺序堵塞的肮脏漏洞之一。你说过你做到了。0.01%来自你的帖子。如果不是这样,那么这里的问题是什么?@_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 他正好在同一时刻。当得到重复项时,update语句会在表被锁定之前在多个线程中执行。这就是为什么您在0.01%的时间内看到相同的值。比赛条件是那些被身份和顺序堵塞的肮脏漏洞之一。你说过你做到了。0.01%来自你的帖子。如果不是这样,那么这里的问题是什么?@

Sql 他正好在同一时刻。当得到重复项时,update语句会在表被锁定之前在多个线程中执行。这就是为什么您在0.01%的时间内看到相同的值。比赛条件是那些被身份和顺序堵塞的肮脏漏洞之一。你说过你做到了。0.01%来自你的帖子。如果不是这样,那么这里的问题是什么?@,sql,sql-server,tsql,Sql,Sql Server,Tsql,他正好在同一时刻。当得到重复项时,update语句会在表被锁定之前在多个线程中执行。这就是为什么您在0.01%的时间内看到相同的值。比赛条件是那些被身份和顺序堵塞的肮脏漏洞之一。你说过你做到了。0.01%来自你的帖子。如果不是这样,那么这里的问题是什么?@SeanLange下面的guzman为什么不同意您的观点:好吧,您的原始进程可能返回dups的唯一原因是它是在允许脏读的读取未提交隔离级别中调用的。无论并发线程数和隔离级别如何,我发布的版本都不会为给定的SerialNumberID返回相同的值


他正好在同一时刻。当得到重复项时,update语句会在表被锁定之前在多个线程中执行。这就是为什么您在0.01%的时间内看到相同的值。比赛条件是那些被身份和顺序堵塞的肮脏漏洞之一。你说过你做到了。0.01%来自你的帖子。如果不是这样,那么这里的问题是什么?@SeanLange下面的guzman为什么不同意您的观点:好吧,您的原始进程可能返回dups的唯一原因是它是在允许脏读的读取未提交隔离级别中调用的。无论并发线程数和隔离级别如何,我发布的版本都不会为给定的SerialNumberID返回相同的值。SQL是一个支持ACID属性的事务系统(有关详细信息,请参阅google“SQL ACID”)。为了支持这一点,它将在更新行中的列之前锁定该行。如果出现第二个更新请求,它将命中锁并等待第一个请求完成(提交事务)。这适用于声明事务和隐式事务。gut voch!我不确定这会有什么帮助:SET@variable=column=expression将变量设置为与列相同的值。这与SET@variable=column、column=expression不同,后者将变量设置为列的更新前值。--这并不能解决sean所描述的并发问题——假设此处存在并发问题,那么原始进程可能返回dups的唯一原因是在
READ UNCOMMITTED
隔离级别中调用它,该级别允许脏读。无论并发线程数和隔离级别如何,我发布的版本都不会为给定的SerialNumberID返回相同的值。它是:
UPDATE dbo.CfgSerialNumber SET@NextKey=SerialNumber+1,SerialNumber=@NextKey其中SerialNumberID=@TableID
这是一个原子操作,不能多次返回相同的值,但也会返回更新后的值而不是原始值。此外,“double equals”语法取决于版本。我知道它在2008SP2或更早版本中不起作用,也记不起它在2012年是否起作用了。@LaughingVergil,这种语法至少从2005年开始存在,或者可能是2000年,这似乎会导致死锁?sp_getapplock可能会导致死锁,具体取决于代码,但通常此过程用于避免死锁。在这种情况下,如果没有子进程,最好避免更新和选择CFGCeralNumber之间出现问题。@l----------“如果您有快照隔离级别,请务必阅读上面的行锁说明我同意。”。在这种情况下,这是最好的解决办法。(贴在下面;-)
SET QUOTED_IDENTIFIER OFF
SET ANSI_NULLS OFF
GO

ALTER procedure GetNextCerealIdentity
    (@NextKey int output, @TableID int)
AS
    declare @RowCount int, @Err int

    set nocount on

    select  
        @NextKey = 0

    begin transaction

Again:
    /*Update CfgCerealNumber Table */
    UPDATE CfgCerealNumber 
    SET CerealNumber = CerealNumber + 1  
    WHERE CerealNumberID = @TableID

    SELECT 
        @RowCount = @@RowCount, 
        @Err = @@Error      /*Obtain updated Cereal number previously incremented*/

    IF @Err <> 0            /* If Error gets here then exit         */
    BEGIN
        RAISERROR ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 16, 1, @Err, @TableID)
        ROLLBACK TRANSACTION

        set nocount off
        return 1
    END

    IF @RowCount = 0                /* No Record then assume table is not   */
                                /* been initialized for TableID Supplied*/
    BEGIN
        RAISERROR('No Table Record Exists in CfgCerealNumber for ID:%d   ', 16, 1, @TableID)
        set nocount off
        Rollback Transaction
        return 1
    END

    /*Obtain updated Cereal number previously incremented*/
    SELECT @NextKey = CerealNumber 
    FROM CfgCerealNumber 
    WHERE CerealNumberID = @TableID

    SELECT @Err = @@Error                       /*Obtain updated Cereal number previously incremented*/

    IF @Err <> 0                            /* If Error gets here then exit         */
    BEGIN
        RAISERROR('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 16, 1, @Err, @TableID)
        Rollback Transaction    
        set nocount off
        return 1
    END

    commit transaction
    set nocount off
    return 0
GO
SELECT @NextKey = CerealNumber 
FROM CfgCerealNumber 
WHERE CerealNumberID = @TableID
SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
GO

CREATE PROCEDURE GetNextSerialIdentity
      @NextKey int output
    , @TableID int
AS
SET NOCOUNT ON;

UPDATE dbo.CfgSerialNumber
SET @NextKey = SerialNumber = SerialNumber + 1
WHERE SerialNumberID = @TableID;

IF @@ROWCOUNT = 0
BEGIN
RAISERROR ('No Table Record Exists in CfgCerealNumber for ID:%d   ', 
                  16,1, @TableID);
END
GO
SET QUOTED_IDENTIFIER OFF
SET ANSI_NULLS OFF
GO

    ALTER procedure GetNextCerealIdentity(@NextKey int output,@TableID int)
    AS
    declare @RowCount int, @Err int
    set nocount on
    select  @NextKey = 0
    begin transaction
   --ADDED CODE
    EXEC sp_getapplock @Resource='MyLock', @LockMode='Exclusive'
                , @LockOwner='Transaction', @LockTimeout = 15000
    Again:
    /*Update CfgCerealNumber Table */
    UPDATE CfgCerealNumber Set CerealNumber = CerealNumber + 1  WHERE CerealNumberID = @TableID
    select  @RowCount = @@RowCount, @Err = @@Error      /*Obtain updated Cereal number previously incremented*/

    if @Err <> 0                            /* If Error gets here then exit         */
        begin                        
        raiserror ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 
               16,1, @Err, @TableID)
                Rollback Transaction    
        set nocount off
        return 1
        end

    if @RowCount = 0                        /* No Record then assume table is not   */
                                    /* been initialized for TableID Supplied*/
        begin
        raiserror ('No Table Record Exists in CfgCerealNumber for ID:%d   ', 
                      16,1, @TableID)
        set nocount off
                Rollback Transaction
        return 1
        end

    /*Obtain updated Cereal number previously incremented*/
    SELECT @NextKey = CerealNumber 
     From CfgCerealNumber WHERE CerealNumberID = @TableID

    select   @Err = @@Error                     /*Obtain updated Cereal number previously incremented*/

    if @Err <> 0                            /* If Error gets here then exit         */
        begin                        
        raiserror ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 
               16,1, @Err, @TableID)
                Rollback Transaction    
        set nocount off
        return 1
        end

    commit transaction
    set nocount off
    return 0
UPDATE CfgCerealNumber Set CerealNumber = CerealNumber + 1  
WHERE CerealNumberID = @TableID
declare @CerealNumber int

SELECT @CerealNumber = CerealNumber  + 1
FROM CfgCerealNumber WITH (READCOMMITTED, READPAST, ROWLOCK) 
WHERE CerealNumberID = @TableID

if @CerealNumber is not null
    UPDATE CfgCerealNumber Set CerealNumber = @CerealNumber
    WHERE CerealNumberID = @TableID
else
    raiserror ('Row was locked by another update (no dirty read and no deadlock happen) or no Table Record Exists in CfgCerealNumber for ID:%d   ', 
              16,1, @TableID)
begin tran
    ...
    exec GetNextCerealIdentity ... ; -- the write lock is established
    ...
commit tran -- the write lock is released
ALTER procedure GetNextCerealIdentity(@NextKey int output,@TableID int)
AS
declare @RowCount int, @Err int
set nocount on
select  @NextKey = 0

-- replace begin tran with:    
EXEC sp_getapplock @Resource = 'CfgCerealNumber', @LockMode = 'Exclusive';  
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

/*Update CfgCerealNumber Table */
UPDATE CfgCerealNumber Set CerealNumber = CerealNumber + 1  
WHERE CerealNumberID = @TableID
select  @RowCount = @@RowCount, @Err = @@Error  /*Obtain updated Cereal number previously incremented*/

if @Err <> 0   /* If Error gets here then exit         */
    begin                        
    raiserror ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 
           16,1, @Err, @TableID)
    -- replace Rollback Transaction with:
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    EXEC sp_releaseapplock @Resource = 'CfgCerealNumber';  
    set nocount off
    return 1
    end

if @RowCount = 0 /* No Record then assume table is not   */
                 /* been initialized for TableID Supplied*/
    begin
    raiserror ('No Table Record Exists in CfgCerealNumber for ID:%d   ', 
                  16,1, @TableID)
    set nocount off

    -- replace Rollback Transaction with:
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    EXEC sp_releaseapplock @Resource = 'CfgCerealNumber';  

    return 1
    end

/*Obtain updated Cereal number previously incremented*/
SELECT @NextKey = CerealNumber 
 From CfgCerealNumber WHERE CerealNumberID = @TableID

select   @Err = @@Error /*Obtain updated Cereal number previously incremented*/

if @Err <> 0  /* If Error gets here then exit         */
    begin                        
    raiserror ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 
           16,1, @Err, @TableID)
    -- replace Rollback Transaction with:
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    EXEC sp_releaseapplock @Resource = 'CfgCerealNumber';  
    set nocount off
    return 1
    end

-- replace commit transaction with:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
EXEC sp_releaseapplock @Resource = 'CfgCerealNumber';  

set nocount off
return 0
GO
begin tran
    ...
    exec GetNextCerealIdentity ... ; -- the lock is established AND released
    ...
commit tran -- common "write locks" are released
UPDATE CfgCerealNumber 
SET CerealNumber = CerealNumber + 1 
OUTPUT INSERTED.CerealNumber
WHERE CerealNumberID = @TableID;
SELECT @CerealNumber = CerealNumber + 1 
FROM CfgCerealNumber WITH (HOLDLOCK, UPDLOCK) 
WHERE CerealNumberID = @TableID;

UPDATE CfgCerealNumber
SET CerealNumber = @CerealNumber
WHERE CerealNumberID = @TableID;
CREATE PROC MyCriticalWork(@MyParam INT)      
AS
    DECLARE @LockRequestResult INT
    SET @LockRequestResult=0

    DECLARE @MyTimeoutMiliseconds INT
    SET @MyTimeoutMiliseconds=5000--Wait only five seconds max then timeouit

    BEGIN TRAN

    EXEC @LockRequestResult=SP_GETAPPLOCK 'MyCriticalWork','Exclusive','Transaction',@MyTimeoutMiliseconds
    IF(@LockRequestResult>=0)BEGIN

        /*
        DO YOUR CRITICAL READS AND WRITES HERE
        */

        --Release the lock
        COMMIT TRAN
    END ELSE
        ROLLBACK TRAN   
SET QUOTED_IDENTIFIER OFF
SET ANSI_NULLS OFF
GO

ALTER procedure GetNextCerealIdentity(@NextKey int output,@TableID int)
AS
set nocount on

DECLARE @RowCount int, @Err int
DECLARE @output TABLE (NextKey int)

begin transaction

    /*Update CfgCerealNumber Table */
    UPDATE CfgCerealNumber WITH (UPDLOCK) 
       Set CerealNumber = CerealNumber + 1
    OUTPUT inserted.CerealNumber INTO @output (NextKey)
     WHERE CerealNumberID = @TableID

    select @RowCount = @@RowCount, /*Obtain updated Cereal number previously incremented*/ 
           @Err = @@Error      

    if @Err <> 0                            /* If Error gets here then exit         */
        begin                        
            Rollback Transaction    
            raiserror ('GetNextCerealIDSeries Failed with Error: %d TableID: %d ', 16,1, @Err, @TableID)
            return -1
        end

    if @RowCount = 0                        /* No Record then assume table is not   */
                                    /* been initialized for TableID Supplied*/
        begin
            Rollback Transaction
            raiserror ('No Table Record Exists in CfgCerealNumber for ID:%d   ', 16,1, @TableID)
            return -1
        end

COMMIT TRANSACTION


/*Obtain updated Cereal number previously incremented*/
SELECT @NextKey = NextKey 
 From @output

return 0
GO
UPDATE CfgCerealNumber
Set CerealNumber = CerealNumber + 1
FROM CfgCerealNumber with (tablockx, holdlock)
WHERE CerealNumberID = @TableID