Laravel在保存之前获得最新的非递增值,没有竞争条件


Laravel get the latest non incrementing value before save without race condition

我正在尝试在我的模型中增加一个完全独立于模型的自动递增 ID 的非自动递增整数列。

为了简化我想说的话,考虑一张放书的桌子。在此表中,我们有四个字段:

Book_id (auto incrementing ID)
book_title  (a string) 
book_contents (Also a string for the purposes of this example)
book_edition (an integer representing the edition of the book. Think College textbooks)

因此,假设我们有一本名为"哈利波特"的书和另一本名为"米老鼠"的书。我们的数据库目前看起来像这样

id:            1
book_title:    "Harry Potter" 
book_contents: "Book Contents"
book_edition:  1 
--------------------------
id:            2
book_title:    "Mickey Mouse"
book_contents: "This is a book about Mickey"
book_edition:  1 

现在让我们说,出于某种原因,"哈利波特"的书必须进行重大更改,无论是为了"导演剪辑版"还是其他任何相当于这本书的原因。此条目将如下所示

id:            3
book_title:    "Harry Potter" 
book_contents: "Updated book contents"
book_edition:  2

我的问题是,在Laravel 5+中获取原书版本的最佳方法是什么?

我是否需要实际执行Model::where({{查询以获取最新}}),或者我可以以另一种方式处理此问题?我看到有一个增量函数,但它没有很好地记录

作为次要问题,如果我确实做了一个模型::如上所述,如果我将其包装在 Laravel DB::transaction 中,我是否可以免受两个人同时更新哈利波特书的可能竞争条件的影响?例

function saveBook()
{
    DB::transaction(function ($arr) {
          $latest = Book::where('book_title', '=', 'Harry Potter')->orderBy("book_edition", "desc")->first();
          $this->book_edition = $latest->book_edition + 1;
          $this->save();
      });
}

这里是否有可能遇到竞争条件?提前感谢!

book_titlebook_edition创建复合唯一索引应该从一开始就解决问题:

ALTER TABLE `books` ADD UNIQUE `unique_edition`(`book_title`, `book_edition`);

在这种情况下,添加事务不会带来任何好处,因为您只执行一个写入操作,虽然该操作取决于读取操作的结果,但唯一索引约束已经保护该操作免受任何竞争条件的影响。

要处理唯一异常,您可以执行以下操作:

function saveBook()
{
    ...
    $latestEdition = Book::where('book_title', 'Harry Potter')->max('book_edition');
    $this->book_edition = $latestEdition + 1;
    try {
        $this->save();
    } catch (Illuminate'Database'QueryException $e) {
        // Your checking for 1062 because that's
        // the MySQL error message for duplicate entry
        if ($e->errorInfo[1] == 1062) {
            // set your error message here
        }
    }
    ...
}

您也可以查看使用悲观锁定,但只能作为替代方法,因为如果您已经在使用唯一约束,锁定将是多余的。但在这种情况下,唯一约束更有意义。