sql表单元格同时被多个线程修改

时间:2009-12-09 11:56:36

标签: sql multithreading

如果您的表 BankAccount 具有 Amount 列,并且特定行的此列的值可以由多个线程同时修改所以它可能发生,以便设置值的最后一个将赢。

你通常如何处理这种情况?

UPDATE:我听说在MSSQL中有更新锁定UPDLOCK来锁定正在更新的表或行,我可以在这里以某种方式吗?

4 个答案:

答案 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   在一个单位内完成的工作单位   数据库管理系统(或类似的   系统)对数据库,和   以连贯可靠的方式对待   独立于其他交易。   数据库环境中的事务   有两个主要目的:

     
      
  1. 提供可靠的工作单元,以便从中正确恢复   失败并保留数据库   即使在系统的情况下也是一致的   执行停止时失败   (完全或部分)和许多   对数据库的操作仍然存在   未完成,状态不明。

  2.   
  3. 在访问数据库的程序之间提供隔离   同时即可。没有隔离的   程序的结果通常是   错误的。

  4.   

答案 2 :(得分:2)

您通常使用交易来克服此问题。

查看Database transaction

答案 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”数据类型不值钱,您应该将其更改为表中使用的数据类型。