首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在开始事务时,我们需要在SELECT期间锁定mysql表,从而导致提交任何挂起的事务?

问为什么在开始事务时,我们需要在SELECT期间锁定mysql表,从而导致提交任何挂起的事务?
EN

Stack Overflow用户
提问于 2020-04-14 16:19:52
回答 3查看 520关注 0票数 0

在这页面上写着:

启动事务会导致提交任何挂起的事务。

因此,从本质上说,事务就像一个锁。但是在这页面上写着:

如果查询数据,然后在同一事务中插入或更新相关数据,则常规SELECT语句不会提供足够的保护。其他事务可以更新或删除刚才查询的行。

这些说法在我看来是自相矛盾的,我如何调和它们呢?举个例子,假设我正在实现一个类似的按钮。有一个包含以下列(user, post, is_liked)的表和另一个存储(post, total_likes)的表。因此,为了处理类似的请求,我想:

  1. 读取is_liked的值,这是一个给定user和post的布尔值。
  2. 然后切换is_liked并像计数一样更新

所有这一切都需要用原子的方式来完成。根据第一个引用,我不需要在读取时锁定,因为开始一个事务会导致任何挂起的事务被提交。如果其他事务尝试并发更新行,它将被挂起的事务阻塞。但第二次引用却不这么说。那么谁是正确的,为什么呢?

问题2:如果我确实需要锁定(我怀疑我需要锁),我是使用LOCK IN SHARE MODE还是FOR UPDATE?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-14 16:29:09

启动事务不像锁。这是个误会。

InnoDB默认实现“乐观锁定”。通过启动事务不会获得任何锁。执行锁定SQL语句时,将根据需要获取锁。

在您的例子中,您应该选择SELECT ... FOR UPDATE,因为这是您准备做的事情--在读取记录后更新它。

关于你的评论:

如果要使用SELECT LOCK共享模式,则可能会导致死锁。

代码语言:javascript
复制
SESSION 1                       SESSION 2

SELECT ... LOCK IN SHARE MODE
ok
                                SELECT ... LOCK IN SHARE MODE
                                ok
UPDATE
waits
                                UPDATE
                                waits

在上面的序列中,您将以两个会话相互等待结束,这是一个死锁。两个人都不会放弃,所以MySQL必须杀死其中一个。

票数 1
EN

Stack Overflow用户

发布于 2021-09-05 01:25:39

MySQL文档中的这一声明:

​

​

是不正确的,造成了问题的混乱。如果启动事务会导致提交任何挂起的事务,那么所有事务都会被有效地序列化。正确的语句可能是:开始事务会导致在同一会话(连接)内提交任何挂起的事务。

请参阅https://forums.mysql.com/read.php?10,698642,698642#msg-698642

票数 1
EN

Stack Overflow用户

发布于 2020-04-14 16:31:29

您会将增加或减少隐藏在触发器中。所以没有必要进行交易。

但是你可以把桌子锁上,也可以在一张桌子上看到。

如果查询数据,然后在同一事务中插入或更新相关数据,则常规SELECT语句不会提供足够的保护。其他事务可以更新或删除刚才查询的行。InnoDB支持提供额外安全性的两种类型的锁定读取:

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61212438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档