【发布时间】:2015-04-05 07:17:37
【问题描述】:
我有以下场景:银行环境中,我不希望特定客户完成从他的账户中提款,除非之前的提款没有提交。
为了实现这一点,我创建了下表
CREATE TABLE [dbo].[Locks](
[CustomerID] [int] NOT NULL,
CONSTRAINT [PK_Locks] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)
现在,每当提款开始时,我都会使用以下代码将客户插入此帮助表(如果他不存在),然后在交易期间锁定该行,以便不会发生其他提款在提交第一个事务之前
BEGIN TRAN
IF NOT EXISTS (SELECT * FROM Locks WHERE CustomerID=@customerId) --if customerid does not exist, insert the row
BEGIN
INSERT INTO Locks (CustomerID)
VALUES (@customerId)
END
SELECT CustomerID FROM Locks WITH (HOLDLOCK XLOCK ROWLOCK) WHERE CustomerID=@customerId --lock on row
--(check if customer has enough balance, then perform withdraw from customer account)
COMMIT
上面的代码似乎可以正常工作,每天有数千次提款,但我确实每周一次左右,我确实遇到了一个锁不起作用并且发现客户余额为负的情况,因为两次提款操作发生在同一时间。
任何想法在什么情况下 HOLDLOCK XLOCK ROWLOCK 可能无法锁定事务?
【问题讨论】:
-
请指定 dbms - 这不是 ANSI SQL。
-
@jarlh 语法显然是SQL Server
-
你不能在初始 SELECT 上只 XLOCK 吗?实际上,我会 UPDLOCK 以允许在非 SI 隔离下并发读取。
-
@jarlh 抱歉,SQL Server
标签: sql sql-server transactions