【问题标题】:How to prevent concurrency issue with database update?如何防止数据库更新的并发问题?
【发布时间】:2012-08-17 08:32:34
【问题描述】:

我有以下序列,可以在任何时候由我的程序的多个实例执行:

第 1 步:检查账单是否未付

第 2 步:如果账单未付,则将账单标记为已付

我担心我的程序的实例 1 和实例 2 几乎同时执行第 1 步,因此继续执行第 2 步。如何防止这种情况发生?

【问题讨论】:

    标签: database concurrency


    【解决方案1】:

    使用(可序列化的)TRANSACTION。更多细节取决于您的数据库平台

    详情请见http://en.wikipedia.org/wiki/Database_transaction

    【讨论】:

    • 请详细说明。交易将如何帮助?如果我的程序的两个实例都执行事务中的步骤,这有什么帮助?
    • 它们会在不同的事务中,一个会失败,你可以捕获它并采取适当的行动
    • 这取决于您的代码和操作的确切结构 - 它可能只是等到第一个事务完成然后继续,此时第一个事务的原子性质将完成,所以产生不同的结果。更准确地说,需要更多细节。
    • 我的程序在两台或多台机器上同时运行。每个实例都可以随时运行上述序列。
    • 您使用的是什么数据库?这个程序是用什么写的?一个如何连接到另一个?这个数据库代码是在哪里生成的?等
    【解决方案2】:

    如果不看代码很难具体说明这一点,但显而易见的方法是将步骤 1 和 2 结合起来。

    所以,而不是:

    $invoice_status = call_database(
    select INVOICE_STATUS
    from   INVOICES
    where  INVOICE_ID = $invoice_id)
    
    if ($invoice_status = UNPAID){
       call_database (
          UPDATE INVOICES 
          SET INVOICE_STATUS = PAID 
          WHERE INVOICE_ID = $invoice_id)
    }
    

    你会做类似的事情

    call_database(
       update invoices
       set    invoice_status = PAID
       where  invoice_id = $invoice_id
       and    invoice_status = UNPAID)
    

    【讨论】:

    • 使用您的第二个代码段,您将如何向用户报告由于发票已支付而未进行更新?使用您的代码,查询将成功运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    相关资源
    最近更新 更多