Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多线程同时修改sql表单元格_Sql_Multithreading - Fatal编程技术网

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

多线程同时修改sql表单元格,sql,multithreading,Sql,Multithreading,如果表BankAccount中有一列Amount,并且特定行的此列值可以由多个线程同时修改,因此可能发生此情况,以便最后一个设置值的线程将获胜 你通常如何处理这种情况 更新:我听说在MSSQL中有一个UPDATE lock UPDLOCK,用于锁定正在更新的表或行,我可以在这里以某种方式锁定它吗?您通常使用事务来克服这一问题 看看您不能让多个线程同时修改相同的数据:它将始终是最后一个设置“赢”值的线程 如果问题是多个线程几乎同时读取和设置值,并且读取和写入的顺序不正确,那么解决方案是使用: 启

如果表BankAccount中有一列Amount,并且特定行的此列值可以由多个线程同时修改,因此可能发生此情况,以便最后一个设置值的线程将获胜

你通常如何处理这种情况


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

您通常使用事务来克服这一问题


看看

您不能让多个线程同时修改相同的数据:它将始终是最后一个设置“赢”值的线程

如果问题是多个线程几乎同时读取和设置值,并且读取和写入的顺序不正确,那么解决方案是使用:

  • 启动交易
  • 读取值
  • 设置新值
  • 提交事务
这确保了读写操作的一致性,并且没有其他线程能够在同一事务期间修改数据


引用维基百科页面关于:

数据库事务包括 在一个单位内完成的工作单位 数据库管理系统(或类似系统) 系统)对数据库,以及 以连贯可靠的方式处理 独立于其他交易。 数据库环境中的事务 有两个主要目的:

  • 提供可靠的工作单元,允许从 并保留一个数据库 即使在系统故障的情况下也是一致的 失败,当执行停止时 (全部或部分)和许多 对数据库的操作仍然有效 未完成,状态不清楚

  • 在访问数据库的程序之间提供隔离 同时。没有隔离 项目的结果通常是 错误的


  • 引用当前值的update语句将防止覆盖。因此,与其做类似的事情

    SELECT Amount FROM BankAccount WHERE account_id = 1
    
    (结果是350,你想减去50)


    您应该有一个数据库函数/过程,可以使用“Amount”进行操作。如果操作成功或失败,则此函数/过程应返回(例如,您希望获得$1000,但当前金额仅为$550,因此无法继续操作)

    T-SQL中的表达式:

    UPDATE BankAccount SET Amount = Amount - 1000 WHERE BankAcountID = 12345 AND Amount >= 1000
    RETURN @@ROWCOUNT
    
    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
    
    如果更改了AMount,则返回值为1,否则为0

    要知道,您可以安全地运行此函数/过程(也可以在多个线程中):

    编辑: T-SQL中的整个过程:

    UPDATE BankAccount SET Amount = Amount - 1000 WHERE BankAcountID = 12345 AND Amount >= 1000
    RETURN @@ROWCOUNT
    
    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”数据类型不划算,您应该将其更改为表中使用的数据类型。

    在事务期间,我是否要对该表行进行锁定?任何适当的数据库服务器都会根据sql调用的粒度(即行锁定、页面锁定、,表锁等,只要它是做你说的。OP问题留下了一个可能性,即它是从2个线程选择然后更新的。在事务期间我是否对此行有锁定?我的意思是,如果我写一个SP,将+5添加到该单元格中,两个线程(其中一个线程在执行第一个线程时启动事务,因此cel的值是初始值)执行该SP,结果可能是+5而不是+10?我想这取决于您使用的确切DBMS;但是,在一般情况下,第一个线程应该在短时间内锁定表或行,第二个线程应该等待直到释放锁(或直到超时)“Transact-SQL”是Microsoft用于Microsoft SQL Server使用的SQL变体的术语,而不是MSSQL。(我保证,MSSQL是微软SQL Server产品的快捷方式,它使用T-SQL作为语言。我不认为“在MSSQL上”和“在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