SELECT ... FOR UPDATE 在 MySQL 中的事务范围之外是否有任何风险?

Kri*_*gji 7 mysql select locking

在我工作的项目中,用于选择对象的 sql 总是选择更新,无论上下文是否为事务。

我的问题是它是否有任何风险、性能问题、或导致死锁或其他顽皮的可能性?

我知道 select for update 只能在事务内锁定一行,这是常见的用例。

我提供了以下两个具体用例,无论是否在事务内部,都在选择更新后使用。

用例 1 - 只需选择一本书并将其归还

book = booksRepository->getBook(7);
return book;
Run Code Online (Sandbox Code Playgroud)

用例 2 - 交易,选择图书,检查是否有效,如果有效则更新

bookRepository->startTransaction();
book = booksRepository->getBook(7);
if (//some condition with the book properties) {
   bookRepository->updateBookAuthor(7, 'bbb');
}
bookRepository->commitTransaction();
Run Code Online (Sandbox Code Playgroud)

在上面的两个例子中,存储库中的函数 getBook 确实选择更新

SELECT * FROM BOOKS
WHERE id = :id
FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)

我问了其他开发人员,他们为什么这样做的答案是“因为否则我们将不得不在存储库中创建两个函数,一个 getBook 和一个 getBookForUpdate,所以我们只选择始终进行更新”...

该答案没有为我可以学习的地方提供任何见解或解释,所以我在这里问。

aku*_*sky 6

即使您没有明确启动查询,查询也始终在事务中。 SELECT FOR UPDATE在它匹配的行上获取排他锁。有可能其他事务想要修改相同的记录并且必须等到SELECT FOR UPDATE完成并释放锁。

因此,如果您运行 不会发生任何不好的事情SELECT FOR UPDATE,但是由于可能的锁定等待,整体性能可能会降低。

死锁也是可能的。如果另一个事务持有共享锁,然后想要在SELECT FOR UPDATE等待时更新记录。