Conflict between UPDATE and SELECT



我有一个表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代码有问题吗?我能做些什么来防止将来发生这样的锁?

谢谢

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

写程序可以阻塞其他写程序,但是,如果我理解正确的话,每次执行只有一次写操作,这样读程序就会插入写操作,从而减少死锁。

希望能有所帮助。

最新更新