【发布时间】:2021-03-16 03:32:00
【问题描述】:
我正在处理一个大约有 2000 人使用的应用程序。日常用户同时插入大约 300 行/用户(大约上午 7 点到上午 11 点)。我使用仅包含插入语句的存储过程来处理它,但我使用begin tran 来防止主键重复。
当前暂停事务经常发生,所以我的存储过程大约需要 1-2 分钟才能完成,这导致我们的用户等待很长时间才能插入每个数据。 我已经检查过了:
-
磁盘速度正常,大约读取:600mb/s 写入 744mb/s。
-
10 核处理器使用率在 20 - 40% 之间。
-
内存使用只有 6gb,我用了 12gb 的内存。
-
检查来自
sys.dm_exec_requests、sp_who2和sys.dm_os_waiting_tasks。3 号的结果是我发现我的存储过程相互挂起(相同的存储过程不同的执行器)
这是我的存储过程(对不起,命名,因为它是我公司的机密):
ALTER PROC [dbo].[SP_DESTIONATION_TABLE_INSERT]
{params}
WITH RECOMPILE
AS
BEGIN
BEGIN TRAN InsertT
DECLARE @ERRORNMBR INT
SET @ERRORNMBR = 0
IF @T = ''
BEGIN
-------------------------------------------------
DECLARE @TCID VARCHAR(15)
SELECT @TCID = ID
FROM DESTIONATION_TABLE
WHERE NIK = @NIK AND
CUSTOMERID = @CUSTOMERID AND
CUSTOMERTYPE = @CUSTOMERTYPE AND --edit NvA 20180111
DATEDIFF(day,DATE,@DATE) = 0
--IF THERE IS ALREADY A CALL IN SERVER
IF @TCID IS NOT NULL
BEGIN
IF @INTERFACE <> 'WEB' BEGIN
--GET EXISTING CALL ID
SET @ID = @TCID
BEGIN TRAN UBAH
UPDATE DESTIONATION_TABLE
SET
columns=value
WHERE ID = @ID
AND employeeid = @employeeid
AND CUSTOMERID = @CUSTOMERID
SET @ERRORNMBR = @ERRORNMBR + @@ERROR
IF @ERRORNMBR = 0
BEGIN
COMMIT TRAN UBAH
SELECT
columns
FROM DESTIONATION_TABLE WHERE ID = @ID
END
ELSE
BEGIN
ROLLBACK TRAN UBAH
END
END
COMMIT TRAN InsertT
RETURN
END
--------------------------------------------------
-- CHECK @DEVICECONTROLID
IF @DEVICECONTROLID IS NOT NULL
AND @INTERFACE <> 'WEB'
AND EXISTS(SELECT 1 FROM DESTIONATION_TABLE WHERE DEVICECONTROLID = @DEVICECONTROLID)
BEGIN
IF NOT EXISTS(SELECT 1 FROM DESTIONATION_TABLE_TEMP WHERE DEVICECONTROLID = @DEVICECONTROLID)
BEGIN
INSERT INTO DESTIONATION_TABLE_TEMP
(COLUMNS)
VALUES
(VALUES)
END
SELECT * FROM DESTIONATION_TABLE WHERE _DEVICECONTROLID = @_DEVICECONTROLID
END
ELSE
BEGIN
some logic to make primary key formula{string+date+employeeid+increment}
END
END
ELSE
BEGIN
BEGIN TRAN UBAH
IF @PARAMS = 'WEB'
BEGIN
UPDATE DESTIONATION_TABLE
SET
COLUMNS = PARAMS
WHERE ID = @ID
END
ELSE IF PARAMS = 'MOBILE'
BEGIN
UPDATE DESTIONATION_TABLE
SET
COLUMNS = PARAMS
WHERE ID = ID
END
SET @ERRORNMBR = @ERRORNMBR + @@ERROR
IF @ERRORNMBR = 0
BEGIN
COMMIT TRAN UBAH
SELECT
COLUMNS
FROM DESTIONATION_TABLE WHERE ID = ID
END
ELSE
BEGIN
ROLLBACK TRAN UBAH
END
END
COMMIT TRAN InsertT
END
我需要一个建议,接下来我应该检查什么以了解我的服务器出了什么问题。
begin tran 是这里的问题吗?
【问题讨论】:
-
你能分享一下过程是什么样的
-
已经附加了我对存储过程的查询
-
我认为你让这个 proc 做的太多了,它需要精简,1. 你调用它的应用程序应该有
@TCID可用,为什么不能它传递给proc? 2. 更新时为什么要将@employeeid和@CUSTOMERID添加到where 子句?之前的查询你用@employeeid和@CUSTOMERID得到@TCID? 3. 您的主键设计需要替换为SEQUENCE 4. 为什么调用proc 的应用程序不能处理错误?
标签: sql sql-server deadlock database-deadlocks