0

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

我最近开始遇到很多冲突,所以做了一些修改以在桌子上创建一个锁,不幸的是我刚刚发生了冲突,同时创建了两个潜在客户(到 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
4

1 回答 1

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/

于 2014-06-02T22:50:40.600 回答