Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.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
MS SQL表提示和锁定、并行性_Sql_Sql Server_Database_Transactions_Parallel Processing - Fatal编程技术网

MS SQL表提示和锁定、并行性

MS SQL表提示和锁定、并行性,sql,sql-server,database,transactions,parallel-processing,Sql,Sql Server,Database,Transactions,Parallel Processing,情况如下: MS SQL 2008数据库,表大约每分钟更新一次。 表结构类似于以下内容: [docID]、[warehouseID]、[docDate]、[docNum]、[partID]、[partQty] 典型工作循环: 用户从内部开发的系统开始数据交换: BEGIN TRANSACTION SELECT * FROM t1 WHERE [docDate] BETWEEN &DateStart AND &DateEnd AND [warehouseID] IN ('w1

情况如下:

MS SQL 2008数据库,表大约每分钟更新一次。 表结构类似于以下内容:

[docID]、[warehouseID]、[docDate]、[docNum]、[partID]、[partQty]

典型工作循环:

用户从内部开发的系统开始数据交换:

BEGIN TRANSACTION

SELECT * FROM t1 
WHERE [docDate] BETWEEN &DateStart AND &DateEnd 
AND [warehouseID] IN ('w1','w2','w3')
…然后系统对所选数据执行相当长的处理,生成要从
t1
中删除的
[docID]s
列表,然后继续

DELETE FROM t1 WHERE [docID] IN ('d1','d2','d3',...,'dN')

COMMIT TRANSACTION
这里的问题是,当第一个事务处理选择数据时,另一个事务处理也读取数据,然后它们一起在内部系统中填充相同的数据

首先,我在SELECT查询中插入了
(TABLOCKX)
表提示。在用户开始抱怨系统性能之前,它运行得相当好

然后我将提示更改为
(ROWLOCK、XLOCK、HOLDLOCK)
,假设它会:

  • 独占锁
  • 所选行(而不是整个表)
  • 直到交易结束
但这似乎使整张桌子都锁上了。我不能访问数据库本身,所以我不能只分析这些锁(实际上,我还不知道如何做,即使我有访问权限)

因此,我想要的是:

  • 用户能够并行处理与不同仓库和日期相关的数据

  • 因此,请避免重复下载的数据

  • 除了锁,我还有其他解决方案(尽管它们看起来都很笨拙):

  • 在t1中实现一个标志,显示数据正在处理中(然后执行
    “选择…其中不包含[flag]”

  • 将t1分为两部分:标题和详细信息,并分别应用锁

  • 我认为我可能误解了一些关于事务隔离级别和/或表提示的概念,还有另一种(更好的)方法。
    请告诉我

    您可以更改工作流的概念

    不删除记录,而是通过将额外字段
    从0设置为1来更新记录

    并不是从表中读取数据,而是从已弃用的视图中读取数据

    BEGIN TRANSACTION
    
    SELECT * FROM vT1 
    WHERE [docDate] BETWEEN &DateStart AND &DateEnd 
    AND [warehouseID] IN ('w1','w2','w3')
    
    其中
    vT1
    视图如下所示:

    select *
    from t1
    where Deprecated = 0
    
    UPDATE t1 SET Deprecated = 1 WHERE [docID] IN ('d1','d2','d3',...,'dN')
    
    COMMIT TRANSACTION
    
    删除将如下所示:

    select *
    from t1
    where Deprecated = 0
    
    UPDATE t1 SET Deprecated = 1 WHERE [docID] IN ('d1','d2','d3',...,'dN')
    
    COMMIT TRANSACTION
    
    使用这种概念,您将实现两个目标:

    • 减少锁的概率
    • 获取仓库的移动历史记录

    此工作流如何帮助我们确保数据只处理一次?如果两个或多个用户同时启动exchange,目标系统将处理两组或多组相同的数据。这是一个新手问题,但视图是否可以仅针对单个用户显示?如果是,我们如何实现它?您可以将
    WITH(readpass)
    提示添加到视图中:
    select*from t1 WITH(readpass),其中Deprecated=0
    。在这种情况下,每个读取某些数据的用户都将等待该数据被更改。的确!感谢您提供如此简单而优雅的解决方案!