2

我有一个DB.DATA_FEED使用 T/SQL 过程更新的表。每分钟,针对不同的数据执行以下过程 100 次。

ALTER PROCEDURE [DB].[UPDATE_DATA_FEED]  
   @P_MARKET_DATE varchar(max),
   @P_CURR1 int,
   @P_CURR2 int,
   @P_PERIOD float(53),
   @P_MID float(53)
AS 

   BEGIN

      BEGIN TRY

         UPDATE DB.DATA_FEED
            SET 
               MID = @P_MID, 
               MARKET_DATE = convert(datetime,@P_MARKET_DATE, 103)
            WHERE 
               cast(MARKET_DATE as date) = 
               cast(convert(datetime,@P_MARKET_DATE, 103) as date) AND 
            CURR1 = @P_CURR1 AND 
            CURR2 = @P_CURR2 AND 
            PERIOD = @P_PERIOD

         IF @@TRANCOUNT > 0
            COMMIT WORK 

      END TRY

      BEGIN CATCH

         --error code

      END CATCH

   END

 END

当用户使用应用程序时,他们也会根据下面的 SQL 从此表中读取数据。此选择可能在一分钟内运行数千次。(问号被解析器替换为适当的日期/数字)

DECLARE @MYDATE AS DATE;
SET @MYDATE='?'
SELECT *
FROM DB.DATA_FEED
WHERE MARKET_DATE>=@MYDATE AND MARKET_DATE<DATEADD(D,1,@MYDATE)
AND CURR1 = ?
AND CURR2 = ?
AND PERIOD = ?

ORDER BY PERIOD

我有时,虽然很少,得到一个数据库锁。

使用来自http://sqlserverplanet.com/troubleshooting/blocking-processes-lead-blocker的脚本,我看到它是 SPID=58。然后我做了 DECLARE @SPID INT; 设置@SPID = 58; DBCC INPUTBUFFER(@SPID) 找到原来是我的选择语句的 SQL 脚本。

我的 SQL 代码有问题吗?我能做些什么来防止将来发生这种锁定?

谢谢

4

1 回答 1

0

读者优先于作者,因此当有人在写作时,读者必须等待写作完成。您可以尝试两种表提示,一种是 NOLOCK,它读取未提交的行(脏读),另一种是 READPAST(仅读取上次提交时已提交的信息)。在这两种情况下,读取器都不会阻塞表,因此不会死锁写入器。

作家可以阻止其他作家,但如果我理解正确的话,每次执行只能写入一次,因此读者会插入写入,从而减少死锁。

希望能帮助到你。

于 2014-08-01T13:39:24.530 回答