如何减少并发 DELETE & INSERT 到 SQL 服务器中的单个 table 期间的阻塞

How to reduce blocking during concurrent DELETE & INSERT to a single table in SQL Server

我们有一个存储过程,可以加载有关订单的详细信息。我们总是想要有关订单的最新信息,因此每次调用存储过程时都会重新生成订单的订单详细信息。我们正在使用 SQL Server 2016。

伪代码:

当多个最终用户同时执行存储过程时,会在 orderdetails table 上创建阻塞。一旦第一个呼叫者完成,第二个呼叫者排队,然后是第三个呼叫者。因此,orderdetails 的生成时间随着时间的推移而增加。这种情况尤其发生在包含 > 100k 或 1 或 200 万的详细信息行的大订单的情况下,因为正在发生 table 级锁定。

我们采用的方法

我们根据并发 orderdetails 加载的订单标识符的最后一位数字对 table 进行了分区。这提高了第一次 orderdetails 加载时的性能,因为没有删除。但是,从第二次开始,第一个会话中的 INSERT 导致其他会话 DELETE 阻塞。其他会话被阻止,直到第一个会话完成 INSERT.

我们正在考虑为每个订单创建单独的 orderdetails table 以避免此并发问题。

问题

能否请您提出一些支持并发 DELETEINSERT 场景的方法?

我们通过为 orderdetails 临时 table 解决了争用问题。我们发现巨大的查询花费了更长的 SELECT 时间,而这个更长的时间导致 orderdetails [=31= 上更长的 table 级别锁定].

因此,我们首先将数据加载到临时 table #orderdetail 中,然后在 orderdetail table 中进行 DELETE 和 INSERT。

由于 orderdetail table 已经分区,DELETE 速度更快并且 INSERT 并行发生. INSERT 在这里也非常快,因为它很简单 table 从 #orderdetail table 扫描。

你可以给Hekaton Engine看看。如果您使用 SP1,它甚至可以在 SQL Server Standard Edition 中使用。

如果由于硬件或软件的限制实现起来太复杂,你可以尝试玩玩数据库的Isolation Levels。有时,读取大量数据的查询会被阻塞,甚至是修改部分数据的查询的死锁受害者。你可以问问自己,你是否需要保证用户读取的数据是有效的,或者你可以承受例如一些脏读?