表架构 (SQL Server 2012)
Create Table InterestBuffer
(
AccountNo CHAR(17) PRIMARY KEY,
CalculatedInterest MONEY,
ProvisionedInterest MONEY,
AccomodatedInterest MONEY,
)
Create Table #tempInterestCalc
(
AccountNo CHAR(17) PRIMARY KEY,
CalculatedInterest MONEY
)
我正在做一个更新。更新存在的行并插入其他行。
UPDATE A
SET A.CalculatedInterest = A.CalculatedInterest + B.CalculatedInterest
FROM InterestBuffer A
INNER JOIN #tempInterestCalc B ON A.AccountNo = B.AccountNo
INSERT INTO InterestBuffer
SELECT A.AccountNo, A.CalculatedInterest, 0, 0
FROM #tempInterestCalc A
LEFT JOIN InterestBuffer B ON A.AccountNo = B.AccountNo
WHERE B.AccountNo IS NULL
一切正常。并发执行期间出现问题。我#tempInterestCalc
通过加入其他各种表来插入数据,包括与表的左连接,并且为每个并发执行InterestBuffer
插入不同的数据集。#tempInterestCalc
我的问题是,有时执行会被另一个执行锁定,直到我串行提交它们。
我的问题是,当我提供不同的数据集时,它不应该对其他并发操作产生任何行锁影响。任何建议将不胜感激。
更新 1:我已用于SP_LOCK
InterestBuffer 表。它说IndId = 1, Type = KEY, Mode = X, Status = GRANT
。
我认为更新和插入会阻止其他事务以进行幻读。
更新2:对不起!以前我告诉过更新很好。但现在我意识到第一个事务写入阻塞了第二个事务写入。在第一个事务中,我运行更新并插入。在第二个事务中,在#tempInterestCalc 表中插入数据后,我只需执行以下操作,它就可以正常工作。
--INSERT DATA INTO #tempInterestCalc
SELECT * FROM #tempInterestCalc
RETURN
--UPDATE InterestBuffer
--INSERT InterestBuffer
更新3:我认为我的问题是在更新期间从InterestBuffer 读取数据并插入到InterestBuffer 中。
更新 4:如果我REBUILD INDEX
在 InterestBuffer 表中的 BranchCode 有时我的回答是有效的。批量插入/更新是否有任何原因导致索引出现问题???
更新 5:我已经读过,如果需要锁定页面的最大行以进行批量更新,那么 SQL 服务器可能会锁定该页面。有什么方法可以查看哪个页面包含哪一行,或者哪个页面在执行期间将被锁定和释放?
更新 6:我正在提供我的方案。
CREATE TABLE [dbo].[Account](
[AccountNo] [char](17) NOT NULL,
[BranchCode] [char](4) NOT NULL,
CONSTRAINT [PK_Account] PRIMARY KEY CLUSTERED
(
[AccountNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[InterestBuffer](
[AccountNo] [char](17) NOT NULL,
[BranchCode] [char](4) NOT NULL,
[CalculatedInterest] [money] NOT NULL,
CONSTRAINT [PK_Buffer] PRIMARY KEY CLUSTERED
(
[AccountNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
查询分支 0001:
BEGIN TRAN
Declare @BranchCode AS Char(4) = '0001'
Declare @CalculatedInterestNew MONEY = 10
CREATE TABLE #tempInterestCalc
(
AccountNo Char(17),
BranchCode Char(4),
CalculatedInterestNew MONEY,
CalculatedInterestOld MONEY
)
INSERT INTO #tempInterestCalc
SELECT A.AccountNo, A.BranchCode, ISNULL(B.CalculatedInterest, 0), B.CalculatedInterest
FROM Account A
LEFT JOIN InterestBuffer B ON A.AccountNo = B.AccountNo AND A.BranchCode = B.BranchCode
WHERE A.BranchCode = @BranchCode
UPDATE A
SET A.CalculatedInterest = B.CalculatedInterestNew + @CalculatedInterestNew
FROM InterestBuffer A
INNER JOIN #tempInterestCalc B ON A.AccountNo = B.AccountNo AND A.BranchCode = B.BranchCode
WHERE A.BranchCode = @BranchCode
INSERT INTO InterestBuffer
SELECT A.AccountNo, A.BranchCode, A.CalculatedInterestNew + @CalculatedInterestNew
FROM #tempInterestCalc A
WHERE A.CalculatedInterestOld IS NULL
DROP TABLE #tempInterestCalc
--ROLLBACK
--COMMIT TRAN
对于 Branch 0002、0003,只需将 @BranchCode 变量值更改为 0002 &0003 并同时运行它们。