MsSql Url缩短db碰撞原子性失败

时间:2013-10-09 13:54:22

标签: sql-server atomicity

我有一个链接缩短服务,数据库中存在大量密钥,这些密钥在一定时间后过期,然后可以重新分配。

我最近开始得到很多冲突,所以做了一些修改来创建一个锁在桌面上,不幸的是我只是在同一时间创建了两个引线(至1/000秒)

想知道如果有人对如何解决这个问题有任何想法,我无法想象它会在几周内发生,但随着业务的增长,这将使问题更加激烈。

该列不是唯一的,因为我们保留了系统中创建的每个URL的记录,因此url键在表中多次使用。

代码如下所示:

BEGIN TRAN GetNextUrlToAssign    
DECLARE @res AS INT

EXEC @res = sp_getapplock                 
                @Resource = 'GetKeyForURL',
                @LockMode = 'Exclusive',
                @LockOwner = 'Transaction',
                @LockTimeout = 20000, -- time in milliseconds.
                @DbPrincipal = 'public'
IF @res < 0
BEGIN
    RAISERROR ( 'psp_GetKeyForURL: Unable to acquire Lock', 16, 1 )
    ROLLBACK TRAN GetNextUrlToAssign
    --RETURN -1
END         

SELECT TOP 1 @OldIMID = IMID, @URLKey = URLKey
FROM IM A WITH (INDEX(IX_DateAvailable) )
WHERE DateAvailable < CURRENT_TIMESTAMP
AND DateReallocated IS NULL     

UPDATE IM
SET DateReallocated = GETDATE()
WHERE IMID = @OldIMID


EXEC @res = sp_releaseapplock @Resource = 'GetKeyForURL';

COMMIT TRAN GetNextUrlToAssign

1 个答案:

答案 0 :(得分:0)

过了一会儿,但这个问题让人头疼,开始在我的数据库上创建锁定。

在与另一位开发人员交谈后,他告诉我MsSql不应该真正用作队列。有用于创建队列的特定软件:

http://msdn.microsoft.com/en-us/library/ms711472(v=vs.85).aspx

http://www.iron.io/mq

没有任何经验,但从简短的阅读中看,它们似乎是使用的技术。

但是我仍然需要修复我的问题,慢查询和锁定数据库,一些查询正在建立,最慢的需要30秒才能完成。

我的解决方案是构建第二个表,我的主表有1000行,存储过程确保表总是每五分钟完全填充一次。

聪明的部分来自使用事务,锁定提示UPDLOCK和READPAST。

UPDLOCK为您提供了对该行的锁定,READPAST允许下一个请求读取后续行,如下面的示例所示。您需要在正在使用的列上有索引。

这个解决方案给了我一个相当高效的查询,我在开发的两秒钟内测试了三个客户端上的大约150个链接。

BEGIN TRAN GetNextUrlToAssign

    SELECT TOP 1 @OldID = q.ID, @URLKey = q.URLKey
    FROM Queue q WITH (UPDLOCK, READPAST)
    WHERE q.Deleted = 0
        AND q.DateReallocated IS NULL   

    UPDATE Queue 
    SET Deleted = 1 
    WHERE ID = @OldID

COMMIT TRAN GetNextUrlToAssign

如需进一步阅读,请尝试以下文章:

http://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in-sql-server-with-readpast-and-updlock/