我是否需要(我是否需要)LOCK IN SHARED MODE | FOR UPDATE在一个事务中


Do I need (will I ever need) LOCK IN SHARED MODE | FOR UPDATE within a transaction?

我痛苦地挣扎着试图理解如何写出最好的代码和查询

直接回答了这个问题:我是否需要或者我是否需要在事务中显式地写LOCK IN SHARED MODEFOR UPDATE(除了READ UNCOMMITTED)?

如果我有外部键,我是否需要显式地选择行来将锁应用于这些行,或者外键定义就足够了?

简短的回答:绝对可以。

完整的答案:这取决于用例。也许在大多数情况下,InnoDb使用的默认锁就足够了。这些锁确保您的数据在事务中保持一致。但是这里有一个场景需要使用SELECT ... FOR UPDATE锁:

假设你正在制作一个web应用程序,其中会话数据存储在数据库中。当涉及到会话数据时,竞争条件是一个值得关注的问题。虽然当文件用于存储会话数据时,这个问题得到了满足,但如果将它们移动到数据库中,则有责任确保请求不会覆盖彼此的会话更改。在这种情况下,您需要使用FOR UPDATE从MySQL读取会话数据,以确保其他请求将等待此请求回写会话并提交事务,然后才能读取它。

(更新)

下面是共享模式的一个用例:

当您希望确保某些记录在事务结束时保持不变时,共享模式非常有用。例如,当父记录已在以前的事务中插入时,您试图将带有外键的子记录插入到父记录。在这种情况下,您将首先选择以共享模式锁定的父记录,然后尝试插入子记录,以确保在插入子记录时,父记录仍然存在。这样,其他会话仍然可以读取父记录,但没有人可以更改它。这只是我的想法,但在共享模式锁的所有用例中,这一事实仍然是相同的,您希望记录保持不变,而其他人仍然可以读取它。 (更新)

关于SERIALIZABLE的事务隔离级别,MySQL的文档是非常清楚的。如果您以这种方式设置事务级别,以及SET autocommit = 0;,那么它就完全类似于REPEATABLE READ级别加上在最后使用LOCK IN SHARE MODE编写所有选择查询(除非您明确提到FOR UPDATE)。这意味着您将接触的所有内容(显式或隐式)都将被锁定。

选择了没有提及锁或者带有LOCK IN SHARED MODE的选项,则以共享模式锁定,其余的以独占模式锁定。