在这页面上写着:
启动事务会导致提交任何挂起的事务。
因此,从本质上说,事务就像一个锁。但是在这页面上写着:
如果查询数据,然后在同一事务中插入或更新相关数据,则常规SELECT语句不会提供足够的保护。其他事务可以更新或删除刚才查询的行。
这些说法在我看来是自相矛盾的,我如何调和它们呢?举个例子,假设我正在实现一个类似的按钮。有一个包含以下列(user, post, is_liked)的表和另一个存储(post, total_likes)的表。因此,为了处理类似的请求,我想:
is_liked的值,这是一个给定user和post的布尔值。is_liked并像计数一样更新所有这一切都需要用原子的方式来完成。根据第一个引用,我不需要在读取时锁定,因为开始一个事务会导致任何挂起的事务被提交。如果其他事务尝试并发更新行,它将被挂起的事务阻塞。但第二次引用却不这么说。那么谁是正确的,为什么呢?
问题2:如果我确实需要锁定(我怀疑我需要锁),我是使用LOCK IN SHARE MODE还是FOR UPDATE?
发布于 2020-04-14 16:29:09
启动事务不像锁。这是个误会。
InnoDB默认实现“乐观锁定”。通过启动事务不会获得任何锁。执行锁定SQL语句时,将根据需要获取锁。
在您的例子中,您应该选择SELECT ... FOR UPDATE,因为这是您准备做的事情--在读取记录后更新它。
关于你的评论:
如果要使用SELECT LOCK共享模式,则可能会导致死锁。
SESSION 1 SESSION 2
SELECT ... LOCK IN SHARE MODE
ok
SELECT ... LOCK IN SHARE MODE
ok
UPDATE
waits
UPDATE
waits在上面的序列中,您将以两个会话相互等待结束,这是一个死锁。两个人都不会放弃,所以MySQL必须杀死其中一个。
发布于 2021-09-05 01:25:39
MySQL文档中的这一声明:

是不正确的,造成了问题的混乱。如果启动事务会导致提交任何挂起的事务,那么所有事务都会被有效地序列化。正确的语句可能是:开始事务会导致在同一会话(连接)内提交任何挂起的事务。
请参阅https://forums.mysql.com/read.php?10,698642,698642#msg-698642
发布于 2020-04-14 16:31:29
您会将增加或减少隐藏在触发器中。所以没有必要进行交易。
但是你可以把桌子锁上,也可以在一张桌子上看到。
如果查询数据,然后在同一事务中插入或更新相关数据,则常规SELECT语句不会提供足够的保护。其他事务可以更新或删除刚才查询的行。InnoDB支持提供额外安全性的两种类型的锁定读取:
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
https://stackoverflow.com/questions/61212438
复制相似问题