相关疑难解决方法(0)

Merge 语句本身死锁

我有以下过程(SQL Server 2008 R2):

create procedure usp_SaveCompanyUserData
    @companyId bigint,
    @userId bigint,
    @dataTable tt_CoUserdata readonly
as
begin

    set nocount, xact_abort on;

    merge CompanyUser with (holdlock) as r
    using (
        select 
            @companyId as CompanyId, 
            @userId as UserId, 
            MyKey, 
            MyValue
        from @dataTable) as newData
    on r.CompanyId = newData.CompanyId
        and r.UserId = newData.UserId
        and r.MyKey = newData.MyKey
    when not matched then
        insert (CompanyId, UserId, MyKey, MyValue) values
        (@companyId, @userId, newData.MyKey, newData.MyValue);

end;
Run Code Online (Sandbox Code Playgroud)

CompanyId、UserId、MyKey 构成目标表的组合键。CompanyId 是父表的外键。此外,还有一个非聚集索引CompanyId asc, UserId asc

它是从许多不同的线程调用的,我一直在调用相同语句的不同进程之间出现死锁。我的理解是“with (holdlock)”对于防止插入/更新竞争条件错误是必要的。

我假设两个不同的线程在验证约束时以不同的顺序锁定行(或页面),因此是死锁。

这是一个正确的假设吗? …

sql-server deadlock sql-server-2008-r2 merge

24
推荐指数
3
解决办法
2万
查看次数

在 IsolationLevel.ReadUncommitted 上发出共享锁

我读到,如果我使用 IsolationLevel.ReadUncommitted,则查询不应发出任何锁。但是,当我对此进行测试时,我看到了以下锁定:

Resource_Type:HOBT
Request_Mode:S(共享)

什么是 HOBT 锁?与 HBT(堆或二叉树锁)相关的东西?

为什么我还会得到 S 锁?

在不打开隔离级别快照选项的情况下进行查询时如何避免共享锁定?

我正在 SQLServer 2008 上对此进行测试,并且快照选项设置为关闭。查询仅执行选择。

我可以看到 Sch-S 是必需的,尽管 SQL Server 似乎没有在我的锁定查询中显示它。为什么它仍然发出共享锁?根据:

设置事务隔离级别 (Transact-SQL)

在该READ UNCOMMITTED级别运行的事务不会发出共享锁,以防止其他事务修改当前事务读取的数据。

所以我有点困惑。

sql-server-2008 sql-server locking isolation-level

10
推荐指数
2
解决办法
2911
查看次数

SQL Server 2014 并发输入问题

在表中Orders,我存储了我们从所有商店收到的订单。由于一个订单可以有多个行,列中有OrderIDOrderLineID 在那里OrderID可以复制,但OrderLineID必须是一个顺序中是唯一的。

由于订单可以修改,存储过程首先检查收到的订单OrderLineID是否已经存在于表中,然后决定插入还是更新。为此,我们:

  • 从 XML 输入动态构建插入和更新语句
  • 插入客户表
  • 插入到 shippingAddresses 表中

然后是主表:

IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID ......)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID
Run Code Online (Sandbox Code Playgroud)

或者该MERGE功能是否提供更好的性能/控制?

但问题如下:

由于线路问题/服务器繁忙等,Order消息(或修改)可能会被多次发送,我们不知道按哪个顺序发送。因此,为了避免Order修改后到达,从而覆盖修改,我们添加了一个时间列:

IF NOT EXISTS (Select 1 from Orders where OrderLineID=@OrderLineID)
INSERT INTO Orders () VALUES ()
ELSE UPDATE Orders SET ... WHERE OrderLineID=@OrderLineID AND LastModified<@CreatedTime
Run Code Online (Sandbox Code Playgroud)

这样,如果后一条消息比前一条消息旧,则对表没有影响。

但是,消息及其修改可能会在很短的时间内发送两次(或更多),以至于后一条消息在保存前一条消息之前到达。因此,对于存储过程的两次执行,它 …

sql-server concurrency unique-constraint

5
推荐指数
1
解决办法
1191
查看次数

SQL Server 并发插入和删除

来自:SQL Server 2014 并发输入问题

后续问题:
我们如何在并行、多线程环境中删除和重新插入行,同时避免竞争条件、死锁等?我们仍然使用 ( UPDLOCK, SERIALIZABLE) 或其他锁吗?

我们有两个表:OrderOrderLineDetail。表Order是存储一般信息的父级;和OrderLineDetail是子表,因为订单有多个明细行项目。

订单可以更新,所以我们首先检查OrderId表中是否存在,并相应地插入或更新。

由于客户修改、线路问题、服务器繁忙等,订单文件可以多次发送。我们有一个时间Lastfiledatetime栏。如果传入的时间戳较旧,则对表没有影响。

对于OrderLineDetail表,有时我们的文件中没有自然键或代理键,因此我们删除所有子OrderLineDetail项,然后重新填充(这是一个较旧的遗留系统的 xml 文件)。

Create Table Orders 
(OrderId bigint primary key,  -- this is in xml files
 Lastfiledatetime datetime null
)

Create Table OrderLineDetail 
(OrderLineDetailid bigint primary key identity(1,1),  -- this is Not in the xml files
 OrderLineDescription varchar(50), 
 OrderLineQuantity int, 
 OrderId bigint foreign key references Orders(OrderId),
 Lastfiledatetime datetime
) …
Run Code Online (Sandbox Code Playgroud)

database-design sql-server concurrency ddl update

5
推荐指数
1
解决办法
1万
查看次数