如果您的表 BankAccount 具有 Amount 列,并且特定行的此列的值可以由多个线程同时修改所以它可能发生,以便设置值的最后一个将赢。
你通常如何处理这种情况?
UPDATE:我听说在MSSQL中有更新锁定UPDLOCK来锁定正在更新的表或行,我可以在这里以某种方式吗?
答案 0 :(得分:4)
引用当前值的更新语句将阻止覆盖。所以,而不是做像
这样的事情SELECT Amount FROM BankAccount WHERE account_id = 1
(它返回350,你想减去50)......
UPDATE BankAccount SET Amount = 300 WHERE account_id = 1
DO
UPDATE BankAccount SET Amount = Amount - 50 WHERE account_id = 1
答案 1 :(得分:3)
你不能让几个线程在同一时间修改相同的数据:它总是最后一个设置“赢”赢的值。
如果问题是几个线程几乎同时读取和设置值,并且读取和写入没有按正确顺序到达,则解决方案是使用Transactions:
这确保了读取和写入将一致地完成,并且在同一事务期间没有其他线程能够修改数据。
引用维基百科页面关于Database Transactions:
数据库事务包括a 在一个单位内完成的工作单位 数据库管理系统(或类似的 系统)对数据库,和 以连贯可靠的方式对待 独立于其他交易。 数据库环境中的事务 有两个主要目的:
提供可靠的工作单元,以便从中正确恢复 失败并保留数据库 即使在系统的情况下也是一致的 执行停止时失败 (完全或部分)和许多 对数据库的操作仍然存在 未完成,状态不明。
- 醇>
在访问数据库的程序之间提供隔离 同时即可。没有隔离的 程序的结果通常是 错误的。
答案 2 :(得分:2)
您通常使用交易来克服此问题。
答案 3 :(得分:1)
您应该有一个数据库函数/过程,它使用“Amount”进行操作。如果操作成功或失败,则应返回此函数/过程(例如,您需要获取$ 1000,但当前AMount仅为550美元,因此无法执行操作。)
在T-SQL中进行Expamle:
UPDATE BankAccount SET Amount = Amount - 1000 WHERE BankAcountID = 12345 AND Amount >= 1000
RETURN @@ROWCOUNT
如果更改了数字,则返回值为1,否则为0。
知道,你可以安全地运行这个函数/程序(在几个线程中):
DECLARE @Result_01 int, Result_02 int, Result_03 int
EXEC @Result_01 = ChangeBankAccountAmount @BankAcountID = 12345, @Amount = 1000
EXEC @Result_02 = ChangeBankAccountAmount @BankAcountID = 12345, @Amount = 15
EXEC @Result_03 = ChangeBankAccountAmount @BankAcountID = 12345, @Amount = 600, @Amount = -2000
修改强> T-SQL中的整个过程:
CRATE PROC ChangeBankAccountAmount
@BankAccountID int,
@ChangeAmount int,
@MMinAmount int = 0
AS BEGIN
IF @ChangeAmount >= 0
UPDATE BankAccount SET Amount = Amount + @ChangeAmount WHERE BankAcountID = 12345
ELSE
UPDATE BankAccount SET Amount = Amount + @ChangeAmount WHERE BankAcountID = 12345 AND Amount >= @MMinAmount
RETURN @@ROWCOUNT
END
当然 - “int”数据类型不值钱,您应该将其更改为表中使用的数据类型。