SQL 服务器中的许多操作超时并阻止进程
Many operations time out and block process in SQL Server
我们的站点日志中有很多操作超时。
在服务器上安装 Redgate SQL Monitor 后,我们发现我们有很多阻塞的进程,有时会死锁。
使用 Redgate,我们意识到问题出在存储过程上。这是一个简单的存储过程,只是增加产品的查看次数(简单更新)
ALTER PROCEDURE [dbo].[SP_IncreaseProductView]
@PID int
AS
BEGIN
UPDATE dbo.stProduct
SET ViewCount = ViewCount + 1
WHERE ID = @PID
END
当该存储过程关闭时,一切都很好,但有时块过程错误又回来了。
此table(产品)没有任何触发器。但它就像系统的核心,有 12000 条记录。
它有 3 个索引,1 个集群索引和 2 个非集群索引,还有很多统计信息
我们没有任何交易。块过程主要发生在更新查询中。
如何找出问题出在哪里?
抱歉我的语言不好
谢谢
编辑:
我认为问题不在于 SP
,而是关于产品 table 的更新(这是我的意见)。它很大 table。当 SP
关闭但更少时,我仍然得到块进程。
我们有很多 select 并更新此 table。
我还用 LINQ to SQL
重写了增加观看次数,但仍然像打开 SP
时一样进行阻止处理。
编辑 2:
我设置了分析器并获取了关于产品 table 的所有查询。
530 select(大多数与另外 2 table 连接)和每分钟 25 次更新(仅限产品 table)。
目前,[SP_IncreaseProductView]
已关闭。因为当它打开时,我们大约每 10 秒就会让块进程和操作超时,并且网站停止。
之后(将 SP
设置为关闭)块进程仍然存在,但每天大约 50 个。
预计:我想你有很多更新到单个小(12K 行)table。
您可以:
解决您的问题
在你的 UPDATE
中输入 ROWLOCK
提示
将数据库选项更改为 READ_COMMITED_SNAPSHOT
不过请注意:它可能会产生其他问题。
更复杂的方法来完全消除阻塞
不适合胆小的人。
创建 table dbo.stProduct_Increment.
将 [SP_IncreaseProductView]
修改为 INSERT
为增量 table。
创建UPDATE
你的dbo.stProduct的周期性任务并清除增量table。
创建组合 stProduct 和 stProduct_Increment 的视图。
将 stProduct 的所有 SELECT
语句修改为创建的视图。
我会选择 Ingaz 的第二个解决方案,但可以执行进一步的优化或简化:
1) 在产品中存储浏览量 1:1 table. 这在某些查询不需要浏览量时特别有用
2) 观看次数冗余
- 在产品 table 中保留浏览量并从那里读取
- 还在另一个 table 中定义观看次数(仅 productid 和 viewcount 列)
- 应用程序可以在第二个 table 中直接异步更新
- 根据第二个 table
的数据更新产品 table 中的作业
这确保锁定对产品的影响 table 远小于独立更新。
我们的站点日志中有很多操作超时。
在服务器上安装 Redgate SQL Monitor 后,我们发现我们有很多阻塞的进程,有时会死锁。
使用 Redgate,我们意识到问题出在存储过程上。这是一个简单的存储过程,只是增加产品的查看次数(简单更新)
ALTER PROCEDURE [dbo].[SP_IncreaseProductView]
@PID int
AS
BEGIN
UPDATE dbo.stProduct
SET ViewCount = ViewCount + 1
WHERE ID = @PID
END
当该存储过程关闭时,一切都很好,但有时块过程错误又回来了。
此table(产品)没有任何触发器。但它就像系统的核心,有 12000 条记录。
它有 3 个索引,1 个集群索引和 2 个非集群索引,还有很多统计信息
我们没有任何交易。块过程主要发生在更新查询中。
如何找出问题出在哪里?
抱歉我的语言不好
谢谢
编辑:
我认为问题不在于 SP
,而是关于产品 table 的更新(这是我的意见)。它很大 table。当 SP
关闭但更少时,我仍然得到块进程。
我们有很多 select 并更新此 table。
我还用 LINQ to SQL
重写了增加观看次数,但仍然像打开 SP
时一样进行阻止处理。
编辑 2:
我设置了分析器并获取了关于产品 table 的所有查询。 530 select(大多数与另外 2 table 连接)和每分钟 25 次更新(仅限产品 table)。
目前,[SP_IncreaseProductView]
已关闭。因为当它打开时,我们大约每 10 秒就会让块进程和操作超时,并且网站停止。
之后(将 SP
设置为关闭)块进程仍然存在,但每天大约 50 个。
预计:我想你有很多更新到单个小(12K 行)table。
您可以:
解决您的问题
在你的
中输入UPDATE
ROWLOCK
提示将数据库选项更改为
READ_COMMITED_SNAPSHOT
不过请注意:它可能会产生其他问题。
更复杂的方法来完全消除阻塞
不适合胆小的人。
创建 table dbo.stProduct_Increment.
将
[SP_IncreaseProductView]
修改为INSERT
为增量 table。创建
UPDATE
你的dbo.stProduct的周期性任务并清除增量table。创建组合 stProduct 和 stProduct_Increment 的视图。
将 stProduct 的所有
SELECT
语句修改为创建的视图。
我会选择 Ingaz 的第二个解决方案,但可以执行进一步的优化或简化:
1) 在产品中存储浏览量 1:1 table. 这在某些查询不需要浏览量时特别有用
2) 观看次数冗余 - 在产品 table 中保留浏览量并从那里读取 - 还在另一个 table 中定义观看次数(仅 productid 和 viewcount 列) - 应用程序可以在第二个 table 中直接异步更新 - 根据第二个 table
的数据更新产品 table 中的作业这确保锁定对产品的影响 table 远小于独立更新。